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 }
1.4.5