Thread: Custom Thermostat

  1. #1
    Registered User
    Join Date
    May 2011
    Posts
    11

    Custom Thermostat

    Hi everyone, should hopefully be a quick one!! Below is some code for a thermostat, pay attention to the lower half. Essentially I am looking to have a thermostat with 3 set temperatures to choose from (22, 30 and 40), with 22C being the default option until one is selected.

    However, when the circuit is active, it boots displaying the SETTEMP (user chosen) to 40C, even though none of the switches have been pressed. Pressing the other two switches has no effect. I am at a loss at to how to adapt the code to get it working effectively.. Anyone have any ideas? In particular the "if" statements...

    Code:
     #include <pic.h>
    #include <string.h>
    #include <stdio.h>
    
    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
      & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    
    int i, j, k, n, z, p;                  //  Use Global Variables for Debug
    int TEMP = 0;
    int SETTEMP;
    
    
    
    char TopMessage[17];
    char BottomMessage[17];
    
    #define E  RC4                  //  Define the LCD Control Pins
    #define RS RC5
    
    const int thirtythreems = 20000; 
    const int Fourtyms = 2500;
    const int Twentyms = 1150;      //  Declare a Constant for 20 ms Delay
    const int Fivems = 300;
    const int TwoHundredus = 10;
    
    LCDWrite(int LCDData, int RSValue)
    {
    
        PORTC = (LCDData >> 4) & 0x0F;  //  Get High 4 Bits for Output
        RS = RSValue;
        E = 1;  E = 0;              //  Toggle the High 4 Bits Out
    
        PORTC = LCDData & 0x0F;     //  Get Low 4 Bits for Output
        RS = RSValue;
        E = 1;  E = 0;              //  Toggle the Low 4 Bits Out
    
        if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
            n = Fivems;             //  Set Delay Interval
        else
            n = TwoHundredus;
    
        for (k = 0; k < n; k++);    //  Delay for Character
    
    }  //  End LCDWrite
    
    LCDReadout() 
       { 
    		for (i = 0; TopMessage[i] != 0; i++)
    		LCDWrite(TopMessage[i], 1);
    		LCDWrite(0b11000000, 0);		// move curosr to second line
    		for (i = 0; BottomMessage[i] != 0; i++)
    		LCDWrite(BottomMessage[i], 1);
    	}
    
    Delay()
    	{
    		for (i =0; i < z; i++);								// wait for 0.32sec								
    		for (i =0; i < z; i++);								// wait for 0.32sec	  for (i =0; i < z; i++);	
    		for (i =0; i < z; i++);								// wait for 0.32sec								
    		for (i =0; i < z; i++);								// wait for 0.32sec
    		for (i =0; i < z; i++);
    	}
    
    int main(void)
    {
    
        PORTC = 0;                  //  Start with Everything Low
    	PORTA = 0;
        CMCON0 = 7;                 //  Turn off Comparators
        ANSEL = 0b0000001;          //  Set RA0 as analogue input
    	TRISA=  0b00001111;			//  Port A as inputs- RA4 AND RA3 is output
        TRISC = 0;                  //  All of PORTC are Outputs
    
    	ADCON0= 0b00000001;    //* Result left justified format, voltage reference= VDD, 
                                                   //AN2= analogue input, initiates ADC and waiting to start conversion.
    	ADCON1= 0b00010000;    //For 4 Mhz, 8Tosc= 2 uS, which > 1.6 uS, the minimum requirement.
    
    
    //  Initialise LCD 
        j = Twentyms;
        for (i = 0; i < j; i++);    //  Wait for LCD to Power Up
    
        PORTC = 3;                  //  Start Initialization Process
        E = 1;  E = 0;              //  Send Reset Command
        j = Fivems;
        for (i = 0; i < j; i++);
    
        E = 1;  E = 0;              //  Repeat Reset Command
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        E = 1;  E = 0;              //  Repeat Reset Command Third Time
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        PORTC = 2;                  //  Initialize LCD 4 Bit Mode
        E = 1;  E = 0;
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        LCDWrite(0b00101000, 0);    //  LCD is 4 Bit I/F, 2 Line
        LCDWrite(0b00000001, 0);    //  Clear LCD 
        LCDWrite(0b00000110, 0);    //  Move Cursor After Each Character
        LCDWrite(0b00001110, 0);    //  Turn On LCD and Enable Cursor
    
    	z = thirtythreems;
    	p = 0;
    	SETTEMP=22;
    
    	while (1==1)				
    	{											
    			
    		if (RA1==1);
    { SETTEMP=22;
    		for (i =0; i < z; i++);
    }
    		
    		if (RA2==1);
    { SETTEMP=30;
    		for (i =0; i < z; i++);
    }
    
    		if (RA3==1);
    { SETTEMP=40;
    		for (i =0; i < z; i++);
    }
    
    
    						// Turn off LED
    
    		
    		GODONE = 1;
    		TEMP = ADRESH;
    
    		LCDWrite (0b00000001, 0);
    		sprintf (TopMessage, " Temp =      %dC", TEMP);		// Display measured temp
    		sprintf (BottomMessage, " Tgt. Temp = %dC", SETTEMP);	// Display ideal temp
    		LCDReadout();
    		for (i =0; i < z; i++);					// wait for 0.32sec	
    			
    		if (TEMP > SETTEMP)	
    		{
    			RA4 = 0;
    			
    		}
    		else
    		{
    			RA4 = 1;
    
    		}	
    		
    	}
    }

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,667
    > if (RA1==1);
    You must all be in the same class, because everyone who comes here with a PIC problem has made the same mistake.

    The ; at the end means you have
    Code:
    if ( something ) {
      // do nothing
    }
    {
      // do this anyway, it's not part of the if
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    May 2011
    Posts
    11
    Apologies, have edited the code to remove the ";"'s. However the program is still stuck displaying "Tgt. Temp = 40C", with no response/change from the switches at RA1, 2 and 3. The temperature itself using the RA0 pin is displaying perfectly along the top line at 26C.

  4. #4
    Registered User
    Join Date
    May 2011
    Posts
    11
    I have edited the more important section of code to the following.. What is still wrong? I can't understand why it is stuck on 40C when RA3 has not been pressed at all!

    Code:
    	SETTEMP=22;
    
    	while (1==1)				
    	{											
    for (i =0; i < z; i++)	
    	
    		if (RA1==1)
    {
    SETTEMP=22;
    }
    		
    		if (RA2==1)
    {
    SETTEMP=30;
    }
    
    		if (RA3==1)
    {
    SETTEMP=40;
    }
    
    		
    		GODONE = 1;
    		TEMP = ADRESH;
    
    		LCDWrite (0b00000001, 0);
    		sprintf (TopMessage, " Temp =      %dC", TEMP);		// Display measured temp
    		sprintf (BottomMessage, " Tgt. Temp = %dC", SETTEMP);	// Display ideal temp
    		LCDReadout();
    		for (i =0; i < z; i++);					// wait for 0.32sec	
    			
    		if (TEMP > SETTEMP)	
    		{
    			RA4 = 0;
    			
    		}
    		else
    		{
    			RA4 = 1;

  5. #5
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    You really need to work on indentation and code formatting, so you (and we) can actually follow your code. I recommend one of the first 3 styles mentioned here: Indent style - Wikipedia, the free encyclopedia.

    Code:
        TRISA = 0b00001111; //  Port A as inputs- RA4 AND RA3 is output
    That line worries me. It says RA3 is an output, but you try to deal with it as an input. It probably always reads back 1 when configured as an output, causing SETTEMP to be 40 every time.

  6. #6
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Properly indent every thing inside the "while (1==1)" loop
    And, I think it might help to find the problem; I am not seeing it.

    Note: Your delay loop "for (i =0; i < z; i++)" has no ";" at the end.

    This code should be after the init code like TRISA and ADCON1 setup
    Code:
        PORTC = 0;                  //  Start with Everything Low
    	PORTA = 0;
    Tim S.
    Last edited by stahta01; 05-18-2011 at 10:58 AM.

  7. #7
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Also, I'm not sure this line is correct:
    Code:
        ANSEL = 0b0000001;      //  Set RA0 as analogue input
    You only specify 7 of the 8 bits. If bit 0 is supposed to be 1 for this, you're fine, but might want to add a 0 to the left just for consistency. If bit 1 should be 1 for this, you need to add a 0 to the end of that.

  8. #8
    Registered User
    Join Date
    May 2011
    Posts
    11
    Code:
     TRISA = 0b00001111; //  Port A as inputs- RA4 AND RA3 is output
    This is remnants of old notation - sorry, ports RA0 through to RA3 are all inputs! RA4 is an output, along with the RC's being sent to the LCD. I am still fairly new to C, so indentation is something I do need to spend some time on

    If I already have "PortA= 0;", then nothing should read as high when turned on surely?

  9. #9
    Registered User hk_mp5kpdw's Avatar
    Join Date
    Jan 2002
    Location
    Northern Virginia/Washington DC Metropolitan Area
    Posts
    3,817
    Code:
    const int thirtythreems = 20000; 
    
    ...
    
    z = thirtythreems;
    
    ...
    
    for (i =0; i < z; i++);					// wait for 0.32sec
    I think these loops (in many places throughout your code) probably won't have any effect, at least not the one claimed by the nearby comment. The compiler will likely optimize them away.
    "Owners of dogs will have noticed that, if you provide them with food and water and shelter and affection, they will think you are god. Whereas owners of cats are compelled to realize that, if you provide them with food and water and shelter and affection, they draw the conclusion that they are gods."
    -Christopher Hitchens

  10. #10
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    Quote Originally Posted by Oscar Morrell View Post
    If I already have "PortA= 0;", then nothing should read as high when turned on surely?
    The above is only true for the output pins; RA3 is set as an input pin.

    What do you have hooked up to RA3?
    If nothing is hooked up, it might float high or it might float low.

    Tim S.
    Last edited by stahta01; 05-18-2011 at 11:25 AM.

  11. #11
    Registered User
    Join Date
    May 2011
    Posts
    11
    Components are: RA0= Analogue temperature sensor, RA1+RA2+RA3 are switches, RA1 being 22C, RA2 being 30C and RA3 being 40C. Or at least those are the values I am trying to assign by saying, for example:

    Code:
     		if (RA2==1)
    {
    SETTEMP=30;
    }
    I just don't understand why it's stuck on 40C when no buttons are pressed. it "occasionally" flicks to 22C and 30C randomly every minute or so.

  12. #12
    Registered User
    Join Date
    Mar 2011
    Posts
    278
    Can we get an updated post of the code with decent indentation?
    Last edited by mike65535; 05-18-2011 at 11:36 AM.

  13. #13
    Registered User
    Join Date
    May 2009
    Posts
    4,183
    To say you have it hooked it up to a switch is NOT an answer.
    Ground the RA3 input and see if the problem goes away.

    Tim S.

  14. #14
    Registered User
    Join Date
    Nov 2010
    Location
    Long Beach, CA
    Posts
    5,909
    Quote Originally Posted by Oscar Morrell View Post
    This is remnants of old notation - sorry, ports RA0 through to RA3 are all inputs! RA4 is an output, along with the RC's being sent to the LCD.
    Yeah, I caught that later when I actually counted the bits. I think you're fine there.

    If I already have "PortA= 0;", then nothing should read as high when turned on surely?
    Once you set them as inputs, any attempt to read the values should ignore any previous output value they had, and actually give you the value from the switch. You shouldn't need to initialize any inputs by setting the equivalent output pins to 0. I would start to question your schematics/wiring at this point. Maybe you can put your thermostat code aside for a moment and try wiring up 3 LEDs to output ports, and make sure you can turn them on/off based on the button presses of RA1, RA2 and RA3. Very simple code like
    Code:
    if (RA1 == 1)
        RB1 = 1;
    // same for RA2 and RA3
    And hk has a point, the compiler may choose to optimize out those delay loops, though given the prevalence of that (awful) delay code all over the PIC world, I would guess your little compiler wont. Usually it's best to declare delay loop counters as volatile so the compiler can't optimize it away:
    Code:
    volatile int i;
    for (i = 0; i < z; i++);

  15. #15
    Registered User
    Join Date
    May 2011
    Posts
    11
    I've tried to improve the indenation to make it more readable, sorry again, am still new to this so indentation is on the agenda for learning! See the following in it's current form..

    Code:
    #include <pic.h>
    #include <string.h>
    #include <stdio.h>
    
    __CONFIG(INTIO & WDTDIS & PWRTEN & MCLRDIS & UNPROTECT \
      & UNPROTECT & BORDIS & IESODIS & FCMDIS);
    
    int i, j, k, n, z, p;                  //  Use Global Variables for Debug
    int TEMP = 0;
    int SETTEMP;
    
    
    
    char TopMessage[17];
    char BottomMessage[17];
    
    #define E  RC4                  //  Define the LCD Control Pins
    #define RS RC5
    
    const int thirtythreems = 20000; 
    const int Fourtyms = 2500;
    const int Twentyms = 1150;      //  Declare a Constant for 20 ms Delay
    const int Fivems = 300;
    const int TwoHundredus = 10;
    
    LCDWrite(int LCDData, int RSValue)
    {
    
        PORTC = (LCDData >> 4) & 0x0F;  //  Get High 4 Bits for Output
        RS = RSValue;
        E = 1;  E = 0;              //  Toggle the High 4 Bits Out
    
        PORTC = LCDData & 0x0F;     //  Get Low 4 Bits for Output
        RS = RSValue;
        E = 1;  E = 0;              //  Toggle the Low 4 Bits Out
    
        if ((0 == (LCDData & 0xFC)) && (0 == RSValue))
            n = Fivems;             //  Set Delay Interval
        else
            n = TwoHundredus;
    
        for (k = 0; k < n; k++);    //  Delay for Character
    
    }  //  End LCDWrite
    
    LCDReadout() 
       { 
    		for (i = 0; TopMessage[i] != 0; i++)
    		LCDWrite(TopMessage[i], 1);
    		LCDWrite(0b11000000, 0);		// move curosr to second line
    		for (i = 0; BottomMessage[i] != 0; i++)
    		LCDWrite(BottomMessage[i], 1);
    	}
    
    Delay()
    	{
    		for (i =0; i < z; i++);								// wait for 0.32sec								
    		for (i =0; i < z; i++);								// wait for 0.32sec	  for (i =0; i < z; i++);	
    		for (i =0; i < z; i++);								// wait for 0.32sec								
    		for (i =0; i < z; i++);								// wait for 0.32sec
    		for (i =0; i < z; i++);
    	}
    
    int main(void)
    {
    
        CMCON0 = 7;                 //  Turn off Comparators
        ANSEL = 0b00000001;          //  Set RA0 as analogue input
    	TRISA=  0b00001111;			//  Port A as inputs
        TRISC = 0;                  //  All of PORTC are Outputs
    
    	ADCON0= 0b00000001;    //* Result left justified format, voltage reference= VDD, 
                                                   //AN2= analogue input, initiates ADC and waiting to start conversion.
    	ADCON1= 0b00010000;    //For 4 Mhz, 8Tosc= 2 uS, which > 1.6 uS, the minimum requirement.
        PORTC = 0;                  //  Start with Everything Low
    	PORTA = 0;
    
    //  Initialise LCD 
        j = Twentyms;
        for (i = 0; i < j; i++);    //  Wait for LCD to Power Up
    
        PORTC = 3;                  //  Start Initialization Process
        E = 1;  E = 0;              //  Send Reset Command
        j = Fivems;
        for (i = 0; i < j; i++);
    
        E = 1;  E = 0;              //  Repeat Reset Command
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        E = 1;  E = 0;              //  Repeat Reset Command Third Time
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        PORTC = 2;                  //  Initialize LCD 4 Bit Mode
        E = 1;  E = 0;
        j = TwoHundredus;
        for (i = 0; i < j; i++);
    
        LCDWrite(0b00101000, 0);    //  LCD is 4 Bit I/F, 2 Line
        LCDWrite(0b00000001, 0);    //  Clear LCD 
        LCDWrite(0b00000110, 0);    //  Move Cursor After Each Character
        LCDWrite(0b00001110, 0);    //  Turn On LCD and Enable Cursor
    
    	z = thirtythreems;
    	p = 0;
    
    	SETTEMP=22;
    
    	while (1==1)				
    	{											
    		if (RA1==1)
    			{
    			SETTEMP=22;
    			}
    		
    		if (RA2==1)
    			{
    			SETTEMP=30;
    			}
    
    		if (RA3==1)
    			{
    			SETTEMP=40;
    			}
    
    
    		GODONE = 1;
    		TEMP = ADRESH;
    
    		LCDWrite (0b00000001, 0);
    		sprintf (TopMessage, " Temp =      %dC", TEMP);		// Display measured temp
    		sprintf (BottomMessage, " Tgt. Temp = %dC", SETTEMP);	// Display ideal temp
    		LCDReadout();
    	
    			
    		if (TEMP > SETTEMP)	
    			{
    			RA4 = 0;
    			}
    	
    		else
    			{
    			RA4 = 1;
    			}	
    		
    	}
    }

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Custom Template
    By DarrenY in forum C++ Programming
    Replies: 12
    Last Post: 10-14-2007, 06:59 AM
  2. custom pause
    By _izua_ in forum C++ Programming
    Replies: 10
    Last Post: 08-13-2007, 12:32 AM
  3. Custom UI
    By cfrost in forum Windows Programming
    Replies: 5
    Last Post: 08-20-2004, 12:52 PM
  4. Custom PC Business....
    By o0obruceleeo0o in forum A Brief History of Cprogramming.com
    Replies: 22
    Last Post: 07-04-2003, 11:27 AM