![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
Programmable Central Heating controller |
Posted: Sat Nov 22, 2008 5:10 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
arunb
Joined: 08 Sep 2003 Posts: 492 Location: India
|
RE; |
Posted: Sat Nov 22, 2008 7:12 am |
|
|
Try to keep the ISR as short as possible.
What other things do you planning to do for the PIC ?
thanks
arunb |
|
![](templates/subSilver/images/spacer.gif) |
dyeatman
Joined: 06 Sep 2003 Posts: 1924 Location: Norman, OK
|
|
Posted: Sat Nov 22, 2008 8:44 am |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Sat Nov 22, 2008 11:13 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
newguy
Joined: 24 Jun 2004 Posts: 1903
|
|
Posted: Sat Nov 22, 2008 12:37 pm |
|
|
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. |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Sat Nov 22, 2008 5:50 pm |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Rohit de Sa
Joined: 09 Nov 2007 Posts: 282 Location: India
|
|
Posted: Sun Nov 23, 2008 12:49 am |
|
|
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 . 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 |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Sun Nov 23, 2008 6:20 am |
|
|
Thanks Rohit,
I appreciate your input and now have a good base to start from.
Carl |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
LCD Display |
Posted: Sat Nov 29, 2008 4:22 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sat Nov 29, 2008 5:25 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
FvM
Joined: 27 Aug 2008 Posts: 2337 Location: Germany
|
|
Posted: Sat Nov 29, 2008 6:26 am |
|
|
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.. |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Sat Nov 29, 2008 7:40 am |
|
|
Thankyou both for your reply. I will look into it.
Carl |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Tue Dec 30, 2008 9:54 am |
|
|
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 |
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
|
Posted: Mon Feb 02, 2009 1:52 pm |
|
|
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;}
|
|
|
![](templates/subSilver/images/spacer.gif) |
carl
Joined: 06 Feb 2008 Posts: 240 Location: Chester
|
Programmable Central Heating controller - Completed |
Posted: Mon Feb 02, 2009 1:54 pm |
|
|
Programmable Central Heating controller - Completed |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|