[AVR] simulate Digital thermostat

Status
Not open for further replies.

Iana Bancila

Newbie level 3
Joined
Dec 2, 2014
Messages
3
Helped
0
Reputation
0
Reaction score
0
Trophy points
1
Visit site
Activity points
26
Hi all, I'm new on this field, and if someone can help me to simulate Digital thermostat
Develop a thermostat (embedded system maintaining a specific temperature):
-> Input: Temperature (as voltage reference, from 0 to VCC - use ADC) (it's up to you to set the
correspondence of 0..Vcc to real-life Celsius temperature, recommended -- 0..99, but not mandatory)
-> Input: Desired temperature, set by a button labelled "+" and a button labelled "-"
-> Output: 0 or 1 to a pin, outputting to a resistor (emulating a heating element)
-> Output: Desired temperature as a three-digit number (shown on 7-seg or 8-seg displays)
Tips:
For setting a certain voltage level:
Use a variable resistor (prefer the ones from the ACTIVE library of the Resistor component type),
connect one pin to power, one pin to ground, and the middle pin to the controller.
Don't forget to set data direction registers (DDR or PxSEL): input for ADC, output for the heating
element.
ADC:
Refer to the user guide of specific controller for details.
1) ADMUX register to set the desired source and voltage reference (AREF is recommended -- connect
it to Vcc in Proteus)
2) ADCSRA: ADEN to enable ADC, ADSC to start conversion, ADIE to enable the interrupt,
ADPS[2:0] to set prescaler (not so important, since we don't have time issues)
3) SFIOR: relevant only if you set the ADATE bit in ADCSRA to 1, meaning there is a specific trigger
to start a conversion
4) Read from ADCH and ADCL (resolution is 10 bits, AVR is on 8 bits, so two registers are needed --ADLAR specifies which way it's adjusted)
Writing an interrupt:
 

Before you start coding, you better get familiar with the system properties.

Latency from heater to sensor, and resulting overshoot
Desired hysteresis or regulation error and desired minimum cycle time of heating system. ( i.e. gas takes longer to preheat)

In home gas furnaces, the problem with most digital thermometers is they have excess hysteresis due to latency of sensor change and amount of defined hysteresis to overcome thermal noise or variations from drafts. Old analog thermostats used a tiny heater element to reduce hysteresis of mercury switch to minimize hysteresis but the coil sensor had far lower latency or lag than cheap thermistors used these days. Even the wires connected to the thermistor affect the temperature from heat conduction.

The problem I see with even fancy setback programmable digital thermostats is overshoot, so sensor location within the unit and unit location within the dwelling are both important. If just electrical control for electrical heaters, proportional dither on off control with zero crossing is desirable.

For Gas not possible, but often , even with 0.5'C resolution software chooses +/- 0.5C hysteresis which can be too much for some with more than 1~2'C overshoot from latency and 0.1'C is too little from excessive cycling. Multiple sensors help regulate a central furnace better.

You, however may opt out and have the same issues as most other digital thermostats. the best commercial heating systems (steam) use proportional thermostat controllers with PID control to adjust heat by valve control in each room.
 

Code:
#define F_CPU (12000000UL)
#include <avr/io.h>

#include <util/delay.h>
#include <stdlib.h>
#include <avr/interrupt.h>
void ADC_init(void);
unsigned int ADC_read(unsigned char);
int user_D_temp(void);
void seven_seg(unsigned int x);
int main(void)
{
    DDRB.2 = 1;//  is used for output resistor
	DDRB.0 = 0; // temperature increase switch
	DDRB.1 = 0; // temperature decrease switch
	DDRC = 0xFF;
	PORTC = 0x00; // 7 segment 1st and 2nd  digit
	DDRD=0xFF;
	PORTD=0x00;   // 7 segment	3rd digit				 
	
	ADC_init();
	
	unsigned int ADC_data;
	unsigned int i,temp_D;
	float t_duty,t1,t2,ADC_data1;
	while(1)
    {
		lcd_clear();
		ADC_data = ADC_read(0);
		ADC_data1=ADC_data/4;
		
		temp_D=user_D_temp();
		
		t_duty = (1-(((ADC_data1)-temp_D)/2));
		PORTB.2=1;
		t1=10*t_duty;
		
	
		for(i=0;i<t1;i++)
		_delay_ms(1000);
		PORTB.2=0;
		t2=10*(1-t_duty);
		
		for(i=0;i<t2;i++)
		_delay_ms(1000);  
        //TODO:: Please write your application code 
    }
}

void ADC_init(void) // Initialization of ADC
{
	ADMUX =(1<<REFS0); // internal 2.56v with external capacitor at AREF
	ADCSRA=(1<<ADEN)|(1<<ADPS2)|(1<<ADPS1)|(1<<ADPS0);
	// Enable ADC and set Prescaler division factor as 128`
}

unsigned int ADC_read(unsigned char ch)
{
	ch= ch & 0b00000111; // channel must be b/w 0 to 7
	ADMUX |= ch; // selecting channel
	
	ADCSRA|=(1<<ADSC); // start conversion
	while(!(ADCSRA & (1<<ADIF))); // waiting for ADIF, conversion complete
	ADCSRA|=(1<<ADIF); // clearing of ADIF, it is done by writing 1 to it
	
	return (ADC);
}

int user_D_temp(void)
{
	unsigned int temp=0;
	if(PORTB.0==1)
	{
		temp++;
		seven_seg(temp);
	}
	else if(PORTB.1==1)
	{
		temp--;
		seven_seg(temp);
	}
	else
		temp=temp;
	return(temp);
}

void seven_seg(unsigned int x)
{
   unsigned int y,z;
   y=x/100;	   //1st digit on lower nibble
   PORTC &=(0x0F)&y;
   y=x%100;
   z=y/10;	  //2nd digit on higher nibble
   PORTC |=(0xF0)|(z<<4);
   z=y%10;	  //3rd digit on lower nibble
   PORTD &=z;
}
 

Status
Not open for further replies.

Similar threads

Cookies are required to use this site. You must accept them to continue using the site. Learn more…