CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

Programmable Central Heating controller

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

Programmable Central Heating controller
PostPosted: Sat Nov 22, 2008 5:10 am     Reply with quote

Hi All,

Could I possibly ask for your expert opinion on a new project I am doing. It is for a Programmable Central Heating controller.

I need several things:

RTC - which can be set when powered on and constantly displayed on LCD. I have looked at ckielstra's technique and it looks good but how to implement it? because I will need to be doing lots of different things which will take a long time - wont this affect the ISR for the RTC?
http://www.ccsinfo.com/forum/viewtopic.php?t=26177&highlight=rtc

Thermostat - I will use Maxim DS1620 - ideal for the job and easier than using a thermocouple with ADC on the PIC.

The power arrangements are not important at the moment.

Timers for setting the ON/OFF of the program for the heating over 7 days - still thinking about this.

Any suggestions would be very appreciated.
Carl
arunb



Joined: 08 Sep 2003
Posts: 492
Location: India

View user's profile Send private message Send e-mail

RE;
PostPosted: Sat Nov 22, 2008 7:12 am     Reply with quote

Try to keep the ISR as short as possible.

What other things do you planning to do for the PIC ?

thanks
arunb
dyeatman



Joined: 06 Sep 2003
Posts: 1934
Location: Norman, OK

View user's profile Send private message

PostPosted: Sat Nov 22, 2008 8:44 am     Reply with quote

As long as this is just a short term hobby project, using the RTC should be
OK. For an actual implementation I would not use an ISR based RTC, I
would instead use a Maxim DS series hardware RTC.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Nov 22, 2008 11:13 am     Reply with quote

Thankyou both for replying,

Keeping the ISR short is in the forefront of my mind - but do you think I can do it all with one PIC - this is what I want to do.

Will the RTC work in the background, and how do I update the time onto the LCD - I presume that it is done in main and not in the ISR - but because it will be constantly updated, won't this hinder my task of doing other things??

This is just a short hobby project so I aim to do it in the PIC - and not a separate RTC IC (Unless it is necessary).

I haven't chosen the PIC yet. nor the canned oscillator (probably 20MHz).

With a series of ON/OFF timers needed for the Mon-Sun programs I will be using lots of timers and alarms - how will this integrate with the real time clock and LCD refreshing??

Thanks for any help
Carl
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Sat Nov 22, 2008 12:37 pm     Reply with quote

Carl,

There's a couple of different ways to go about this. If you can find a RTC chip that will generate a one pulse per second "tick", you can route this 1PPS to the PIC's external interrupt (many PICs have 3 EXT interrupts, usually on pins B0 - B2). Setup your code to wait in an infinite while() loop and look for the "one_minute" flag to become true. Inside your external interrupt ISR, simply count up the seconds, incrementing minutes, hours and days as necessary. If the minutes changed, set your one_minute flag to TRUE inside the ISR.

In your main program loop (inside the while()), simply look for one_minute to be set. When it does become set, do a few things:
- update your LCD to reflect the current time
- check to see if the set temperature has to be updated, based on the current day and time
- take a temperature measurement (once per minute in a house is plenty fast enough)
- if the measured temp < set temp and the furnace isn't already on, turn it on
- if the measured temp > set temp + hysteresis temp and the furnace is on, turn it off
- perhaps read exact time from the RTC chip (only down to the minute - ignore seconds) to confirm that the PIC's internal time matches the RTC
- exit "one_minute" loop

This can all be performed very, very quickly - no need to worry whether a PIC is fast enough. You can even put the PIC to sleep to conserve power - the 1PPS can wake it up.

The second way can be implemented if you use a RTC that cannot supply a 1PPS external signal. Simply setup one of the PIC's timers to "roll over" a little faster than once every second. There's actually a couple of different plans of attack here as well. You can either set up a timer to "fire" rather quickly - i.e. about once per second, or you can set it up to fire rather slowly - i.e. about once per minute.

Every time the timer rolls over, an interrupt will be triggered. All you really need to do INSIDE of this ISR is to set a flag to be used within your main's while() loop. Let's call it check_time. When check_time is TRUE, enter a routine similar to the one above, but the first item on the agenda is to read the true time from the RTC. If the minutes have rolled over, update the LCD and proceed with the rest of the tasks as above. If the minutes have not changed, just exit the loop.

You can also put the PIC to sleep in this situation if you use a 32.768 kHz watch crystal on (I believe) the external clock pins which drive timer 1. If you go this route, however, the RTC chip itself becomes redundant.
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Nov 22, 2008 5:50 pm     Reply with quote

New Guy,

That is an extremely thorough reply and I thank you greatly. It gives me lots to think about and a very good base to start from. I haven't decided which technique to use for the clock yet, but having an external IC would probably be simpler.

I am going to start this next week.

Thanks again.
Carl
Rohit de Sa



Joined: 09 Nov 2007
Posts: 282
Location: India

View user's profile Send private message Visit poster's website

PostPosted: Sun Nov 23, 2008 12:49 am     Reply with quote

Quote:
You can also put the PIC to sleep in this situation if you use a 32.768 kHz watch crystal on (I believe) the external clock pins which drive timer 1. If you go this route, however, the RTC chip itself becomes redundant.
I would go this way. It eliminates an additional chip completely.

I have a (pretty old) air-conditioning unit at home, and for some reason the thermostat (the old bimetallic kind) keeps getting messed up. So I decided to make my own AC controller. I have a 16F876 running at 4 MHz, a 32.768kHz watch crystal on the timer1 pins, and Sony SIRC based infrared remote control code running on the PIC. I use a thermistor for temperature measurement (I had to spend some time calibrating this against a lab thermometer). A 16x1 LCD is used for display.

So even at 4MHz, running temperature averaging code, checking for IR remote signals, checking for timer1 roll-overs, displaying information on the LCD, turning ON and OFF the control relay, flashing a status LED, I still have time to put the processor to sleep Very Happy . I power down the LCD when sleeping, to conserve energy.

The trick is to prioritize what is you need to do. Naturally, the timer would need to use an interrupt; a whole lot of things can be run off this interrupt - temperature sampling, LED flashing, LCD updating. The only other thing I use an external interrupt for, is the IR signals.

Rohit
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sun Nov 23, 2008 6:20 am     Reply with quote

Thanks Rohit,

I appreciate your input and now have a good base to start from.
Carl
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

LCD Display
PostPosted: Sat Nov 29, 2008 4:22 am     Reply with quote

Hi all,

I am just doing the flowcharts/implementation for this project and and now looking at the menu system - with LCD.

Does anyone know an easy way to highlight/blink individule lines of an LCD - which would change between lines 1 and 2 with button presses. Also I will need to blink more than one character at a time.

I know how to do it with one character, but not the above request.

I will be using the flex driver.

Thanks
Carl
Ttelmah
Guest







PostPosted: Sat Nov 29, 2008 5:25 am     Reply with quote

I posted a 'menu' system for LCD's a little while ago. Was 'cut out' of working code, so had a few bugs, but the poster at the time seemed to get it working. Allowed an array of menu 'lines', with two lines displayed. Used three buttons, 'up', 'down', and 'select'. This flashed the selected line at a rate dependant on a timer based clock, and as you moved down, the second line flashed, then moved down again, and the display showed lines 2&3 from the array of lines, with the second of these flashing. Within the limits of size on your chip, you could make the menu as long as you wanted, with a few 'tweaks'. A search here should find it.

Best Wishes
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Sat Nov 29, 2008 6:26 am     Reply with quote

Usual character LCD controllers of HD44780 type only support a blinking cursor position. Diplaying a blinking line would imply continuous rewriting of display content. This can work sufficient fast with a parallel interfaced display, but as far as I remember, doesn't look really good..
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Sat Nov 29, 2008 7:40 am     Reply with quote

Thankyou both for your reply. I will look into it.

Carl
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Tue Dec 30, 2008 9:54 am     Reply with quote

Slowly getting there, but can anyone help me with the DS1620.

Here is a workable compilable extract from the main program:
Code:
#include <18F4525.h>
#include <lcd.c>
#use delay(clock=4000000)
#fuses NOWDT,NOPROTECT,BROWNOUT,PUT,NOLVP,NOPBADEN,XT
#use standard_io(a)     
#use standard_io(b)
#use standard_io(c)     
#use standard_io(d)
#use standard_io(e)
#define DQ          pin_b2
#define CLKD      pin_b3
#define   RST         pin_b4
unsigned long int temp_data;      // raw temp
unsigned long int data; 
void DS1620_InitTemp(void);
unsigned long int DS1620_Read(void);
void DS1620_Write(Data);
void main() {
   lcd_init();
   DS1620_InitTemp();
   delay_ms(10);
   DS1620_read();
   printf(LCD_PUTC,"\f%lu \n",temp_data);
}
void DS1620_InitTemp(void)
{
   // set CLK and RST to correct states
   output_high(CLKD);
   delay_us(2);
   output_low(RST);
   // set DS1620 config to continuous convert
   // and CPU communications mode
   output_high(RST);
   DS1620_Write(0x0C);           // send Write Config command
   delay_ms(11);
   DS1620_Write(0x02);           // configure for CPU mode, continuous convert
   output_low(RST);
   // start conversion
   output_high(RST);
   DS1620_Write(0xEE);           // send Start Convert command
   output_low(RST);
}  // End DS1620_InitTemp

void DS1620_Write(Data)
{
   byte i;
   set_tris_b(0x00);
   for(i=0; i<8; i++)
   {
     output_low(CLKD);
     output_bit(DQ, shift_right(&data,1,0));
     output_high(CLKD);
   }
}
// read & display temperature from DS1620.
unsigned long int DS1620_Read(void)
{
   byte i;
   output_high(RST);
   DS1620_Write(0xAA);          // send Read Temp command
   set_tris_b(0x84);
   temp_data = 0;             // clear temp_data on entry
   for(i=0; i<9; i++)         // loop for 9-bits
   {
     output_low(CLKD);
     temp_data = temp_data >> 1;
     if (input(DQ))
     {
        temp_data = temp_data | 0x100;
     }
     output_high(CLKD);
   }
   temp_data = temp_data/2;      // convert temp_data to whole deg C
   output_low(RST);
return(temp_data);
}



The problem I am having with it though is that the ambient temperature reading is around 26C. This varies accordingly when the enviroment (IC) gets hotter or colder as it should - but the initial reading from the chip should not be 26C.

I have checked the serial binary reading which gives 000110100. In hex this is 34h - and to get the temperature according to the datasheet we divide by2 - 34h/2 = 26 in decimal. in other words the correct method for determining the value is correct - but the initial value is wrong.

Do you think it could be because the chip is damaged or just because their is extra temperature due to the heat of the electronics. Maybe it needs some sort of scaling??

Any help would be appreciated.

Carl
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

PostPosted: Mon Feb 02, 2009 1:52 pm     Reply with quote

I finally completed this project. The code for the DS1620 was the biggest pain and is shown below for others to see. THe High and Low settings are external variables - set somewhere in main or pre-compiler.

In my program I made it so that when the set point was adjusted - the Thigh and Tlow were also automatically adjusted.


Code:

#use delay(clock=32000000)
#define DQ          pin_e0
#define CLKD      pin_e1
#define   RST         pin_e2
unsigned long int temp_data;      // raw temp
unsigned long int data; 
extern unsigned long int htemp;
extern unsigned long int ltemp;
void DS1620_InitTemp(void);
unsigned long int DS1620_Read(void);
unsigned long int DS1620_Readh(void);
unsigned long int DS1620_Readl(void);
void DS1620_Write(data);
void DS1620_Write2(data);
void DS1620_HWrite(void); 
void DS1620_LWrite(void);
void DS1620_stop(void);

void DS1620_InitTemp(void)
{
   // set CLK and RST to correct states
   output_high(CLKD);
   delay_us(2);
   output_low(RST);
   // set DS1620 config to continuous convert
   // and CPU communications mode
   output_high(RST);
   DS1620_Write(0x0C);           // send Write Config command
   delay_ms(100);
   DS1620_Write(0x02);           // configure for CPU mode, continuous convert
   output_low(RST);
   delay_ms(10);

   output_high(RST);
   DS1620_HWrite();
   output_low(RST);
   delay_ms(10);

   output_high(RST);
   DS1620_LWrite();
   output_low(RST);
   delay_ms(10);

   // start conversion
   output_high(RST);
   DS1620_Write(0xEE);           // send Start Convert command
   output_low(RST);
   delay_ms(100);
}  // End DS1620_InitTemp

void DS1620_Write(Data)
{
   byte i;
   set_tris_e(0x00);
   for(i=0; i<8; i++)
   {
     output_low(CLKD);
     output_bit(DQ, shift_right(&data,1,0));
     output_high(CLKD);
   }
}
void DS1620_Write2(Data)
{
   byte i;
   set_tris_e(0x00);
   for(i=0; i<9; i++)
   {
     output_low(CLKD);
     output_bit(DQ, shift_right(&data,1,0));
     output_high(CLKD);
   }
}
// read & display temperature from DS1620.
unsigned long int DS1620_Read(void)
{
   byte i;
   output_high(RST);
   DS1620_Write(0xAA);          // send Read Temp command
   set_tris_e(0x02);
   temp_data = 0;             // clear temp_data on entry
   for(i=0; i<9; i++)         // loop for 9-bits
   {
     output_low(CLKD);
     temp_data = temp_data >> 1;
     if (input(DQ))
     {
        temp_data = temp_data | 0x100;
     }
     output_high(CLKD);
   }
   temp_data = temp_data/2;      // convert temp_data to whole deg C
 //  temp_data = temp_data-4;       This shouldn't be neccassary
   output_low(RST);
return(temp_data);
}
void DS1620_HWrite(void)
{
   output_high(RST);
   delay_ms(100);
   DS1620_Write(0x01);
   delay_ms(100);
   DS1620_Write2(htemp);
   delay_ms(100);       
   output_low(RST);   
}
void DS1620_LWrite(void)
{
   output_high(RST);
   delay_ms(100);
   DS1620_Write(0x02);
   delay_ms(100);
   DS1620_Write2(ltemp); 
   delay_ms(100);     
   output_low(RST);   
}
void DS1620_stop(void)
{
   output_high(RST);
   delay_ms(100);
   DS1620_Write(0x22); 
   delay_ms(100);
   output_low(RST);
}
unsigned long int DS1620_Readh(void)
{
   byte i;
   output_high(RST);
   DS1620_Write(0xA1);          // send Read Temp command
   set_tris_e(0x02);
   temp_data = 0;             // clear temp_data on entry
   for(i=0; i<9; i++)         // loop for 9-bits
   {
     output_low(CLKD);
     temp_data = temp_data >> 1;
     if (input(DQ))
     {
        temp_data = temp_data | 0x100;
     }
     output_high(CLKD);
   }
   temp_data = temp_data/2;      // convert temp_data to whole deg C
   output_low(RST);
return(temp_data);
}
unsigned long int DS1620_Readl(void)
{
   byte i;
   output_high(RST);
   DS1620_Write(0xA2);          // send Read Temp command
   set_tris_e(0x02);
   temp_data = 0;             // clear temp_data on entry
   for(i=0; i<9; i++)         // loop for 9-bits
   {
     output_low(CLKD);
     temp_data = temp_data >> 1;
     if (input(DQ))
     {
        temp_data = temp_data | 0x100;
     }
     output_high(CLKD);
   }
   temp_data = temp_data/2;      // convert temp_data to whole deg C
   output_low(RST);
return(temp_data);
}


And the main three instructions are shown below which was included in part of my code:

Code:

            DS1620_InitTemp();             // initialises and starts the DS1620 and sets high/low temps.
            delay_ms(500);
            DS1620_read();                  // Get A Reading
            delay_ms(500);
            level = input_state(pin_c0);
            delay_ms(500);
            if(level==true){
            output_bit(pin_c1,0);
            DS1620_stop();}               // Stop
            else if(level==!true){
            output_bit(pin_c1,1);
            DS1620_stop();
            break;}
carl



Joined: 06 Feb 2008
Posts: 240
Location: Chester

View user's profile Send private message

Programmable Central Heating controller - Completed
PostPosted: Mon Feb 02, 2009 1:54 pm     Reply with quote

Programmable Central Heating controller - Completed
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group