Temperature.c

Go to the documentation of this file.
00001 /* This file has been prepared for Doxygen automatic documentation generation.*/
00024 //  Include files
00025 #include "Main.h"
00026 #include "Temperature.h"
00027 #include "math.h"
00028 
00029 //  Global variables
00030 unsigned char ADCresult_calc_cnt = 0;   // variable to count number of temperature calcualtions
00031 int ADCresult_average = 0;              // integer to keep the ADC results for later averaging
00032 float Temperature;                      // float to calculate the temperature
00033 
00034 
00038 void ADC_init(unsigned char Operation)
00039 {
00040     SET_POINT = 25;                     // set SET_POINT to 25 degree Celsius
00041 
00042     ADMUX |= Operation;                 // set the selected opeartion, either Single Ended or Differential
00043 
00044     Delay(50);                          // delay in order for channel selection to settle
00045 
00046     ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS0);    // set ADC prescaler to , 1MHz / 8 = 125kHz
00047 
00048     DIDR1 = 0xFF;                       // disable digital input on PORTF
00049 
00050     ADC_conversion();                   // run a dummy conversion the first time the ADC is used after a power up
00051 }
00052 
00053 
00056 void PWM_init(void)
00057 {
00058     ICR1H = 0x03;               // set the TOP value for the PWM to 0x3FF = 10bit
00059     ICR1L = 0xFF;
00060 
00061     OCR1AH = OCR1BH = 0x00;
00062     OCR1AL = OCR1BL = 0xF0;     // set a initial value in the OCR1A-register
00063 
00064     TCCR1A = (1<<COM1A1) | (1<<COM1A0) | (1<<COM1B1) | (1<<COM1B0); // set OC1A/B on upcounting, clear on downcounting
00065     TCCR1B = (1<<WGM13) | (1<<CS11);        // select Phase and Frequency Corrcet, and set CLK(I/O) / 8 (From prescaler)
00066 }
00067 
00068 
00071 void ADC_conversion(void)
00072 {
00073     int ADC_temp;
00074     int ADCresult = 0;
00075     unsigned char i;
00076 
00077     for(i=0;i<8;i++)            // do the ADC conversion 8 times for better accuracy
00078     {
00079         ADCSRA |= (1<<ADSC);        // do single conversion
00080         while(!(ADCSRA & 0x10));    // wait for conversion done, ADIF flag active
00081 
00082         ADC_temp = ADCL;            // read out ADCL register
00083         ADC_temp += (ADCH << 8);    // read out ADCH register
00084 
00085         ADCresult += ADC_temp;      // accumulate result (8 samples) for later averaging
00086     }
00087 
00088     ADCresult = ADCresult >> 3;     // average the 8 samples
00089 
00090     ADCresult_calc_cnt++;           // increment the counter that keeps track of how many calulations that have been donet
00091 
00092     ADCresult_average += ADCresult; // add the ADCresult to the previous measurements
00093 
00094     if(ADCresult_calc_cnt >= 32)    // if 32 calculations
00095     {
00096         ADCresult_calc_cnt = 0;     // clear the counter
00097 
00098         ADCresult_average = ADCresult_average >> 5;   // find the average ADC result for the last 32 times
00099 
00100         Temp_calculation(ADCresult_average);       // call the temperature calculation function
00101 
00102         ADCresult_average = 0;      // clear the ADCresult_average
00103     }
00104 }
00105 
00106 
00111 void Temp_calculation(int iADC_value)
00112 {
00113     float V_ADC;
00114 
00115     if((ADMUX & 0x1F) == SingleEnded)       // check if Single_ended operation
00116         V_ADC = (iADC_value * V_ref)/1024;      // calculate the voltage over the NTC
00117     else if((ADMUX & 0x1F) == Differential) // check if Differential operation
00118         V_ADC = (iADC_value * V_ref)/512;       // calculate the voltage over the NTC
00119 
00120     Temperature = (Beta / ((log(V_ADC/(V_ref-V_ADC))/log(__E)) + (Beta/T_amb))) - T_zero;   // calculate the temperature
00121 
00122     TEMP_HIGHBYTE = Temperature;                // store the integer to "TEMP_HIGHBYTE"
00123     Temperature = (Temperature - TEMP_HIGHBYTE);    // subtract the the integer from Temperature_average
00124     TEMP_LOWBYTE = (Temperature * 100);         // multiply Temperature_average by 100 to get the decimal, and store it to "TEMP_LOWBYTE"
00125 
00126     Temperature_regulation();                   //call the Temperatur_regulation rutine
00127 }
00128 
00129 
00133 void Temperature_regulation(void)
00134 {
00135     int Offset_OCR1;
00136     unsigned char PWM_8LSB;
00137     unsigned char PWM_2MSB;
00138 
00139     OFFSET = (TEMP_HIGHBYTE - SET_POINT);   // find the offset between measured temperature and SET POINT
00140 
00141     if( OFFSET & 0x80 )   // if a negative offset
00142     {
00143         OFFSET =~ OFFSET;       // 2'nd complement the OFFSET to get a positive value
00144 
00145         if(OFFSET > 1)          // if the offset is more than 1 degree below the set point
00146         {
00147             TCCR1A &= 0x0F;         // disable COM1Ax and COM1Bx
00148             TCCR1A |= 0xC0;         // set COM1A1 and COM1A0
00149             PORTB = Heater;         // set the Heater as output
00150         }
00151     }
00152     else if( OFFSET )       // if the offset is more than 1 degree above the set point
00153     {
00154         TCCR1A &= 0x0F;         // disable COM1Ax and COM1Bx
00155         TCCR1A |= 0x30;         // set COM1B1 and COM1B0
00156         PORTB = Cooler;         // set the Cooler as output
00157     }
00158     else                    // else then if OFFSET equals the measured temperature, diable Heating and Cooling
00159     {
00160         TCCR1A &= 0x0F;                     // disable COM1Ax and COM1Bx
00161         PORTB = (1<<PORTB6) | (1<<PORTB5);  // shut down LED5 and LED6 (active low on the STK500)
00162     }
00163 
00164     Offset_OCR1 = OFFSET;               // copy the OFFSET to the Offset_OCR1A
00165 
00166     Offset_OCR1 *= (Offset_OCR1 * 2);   // Multiply the offset by itself times two, this is done just to
00167                                         // fill up the 10 bit in the OCR1A register
00168     if(Offset_OCR1 > 0x03FF)            // if the Offset_OCR1A is beyond the maximum value of OCR1A in 10-bit mode
00169         Offset_OCR1 = 0x3FF;                // write 0x3FF to it.
00170 
00171     PWM_8LSB = Offset_OCR1;             // load the 8LSB to PWM_8LSB
00172     Offset_OCR1 >>= 8;                  // move the value in Offset_OCR1 8 times to the right
00173     PWM_2MSB = Offset_OCR1;             // load the 2MSB int
00174 
00175     OCR1AH = OCR1BH = PWM_2MSB;     // write the high byte of the OCR1A/B registers
00176     OCR1AL = OCR1BL = PWM_8LSB;     // write the low byte of the OCR1A/B registers
00177 }

Generated on Fri Feb 17 12:28:30 2006 for AVR064: A Temperature Monitoring System with LCD Output by  doxygen 1.4.5