I'm working on modifying a PID-controller for a reflow oven to use two thermocouples, and I'm hoping that someone would be good enough to check my code and make sure that I haven't messed up somewhere. :D Since I'm still new to programming in C, a second opinion would be most welcome.
The original controller was built around an ATMega32U running at 16MHz. I've adjusted the inputs to use ADC channels 8, 9, and 10 instead of 0 and 1... plus made the actual ADC read a function call instead of doing it directly each time.
For reference, here is the original code...
#include "thcouple.h" // 12-bit temperature (0.25 deg/div) int16_t thcouple_read(void) { ADCSRB &= ~(1<<MUX5); // ADC0 channel - thermocouple ADCSRA |= (1<<ADSC); // start conversion do {} while ( !(ADCSRA & (1<<ADIF)) ); ADCSRA |= (1<<ADIF); // clear ADIF flag // 41 uV/*C, K = 196 -> 41*196 = 8.036 mV/*C / 2.5 mV/div -> 3.2144 div/*C -> 0.311 *C/div uint16_t th_temp = ADC; th_temp *= 31; th_temp /= 100; // 1 *C/div th_temp <<= 2; // 1/4 *C/div ADCSRB |= (1<<MUX5); // ADC8 channel - TMP37 (cold junction) ADCSRA |= (1<<ADSC); // start conversion do {} while ( !(ADCSRA & (1<<ADIF)) ); ADCSRA |= (1<<ADIF); // clear ADIF flag // 20 mV/*C, 0V at 0*C -> 1/8 *C/div uint16_t tmp37_temp = ADC; tmp37_temp >>= 1; // 1/4 *C/div th_temp += tmp37_temp; return th_temp; } void adc_setup(void) { // ADC @ 250 kHz single conversion mode, 2.56V ARef DIDR0 = (1<<ADC0D); // thermocouple DIDR2 = (1<<ADC8D); // TMP37 cold junction sensor ADMUX = (1<<REFS0) | (1<<REFS1); ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2); ADCSRB = (1<<ADHSM); ADCSRA |= (1<<ADSC); // dummy conversion do {} while ( !(ADCSRA & (1<<ADIF)) ); ADCSRA |= (1<<ADIF); // clear ADIF flag }
And my modified version...
#include "thcouple.h" // 12-bit temperature (0.25 deg/div) int16_t thcouple_read(void) { // Get the cold-junction reading first... // Channel ADC8 = TMP37 (cold junction) // 20 mV/*C, 0V at 0*C -> 1/8 *C/div uint16_t tmp37_temp = adc_read(); tmp37_temp >>= 1; // 1/4 *C/div ADMUX |= (1<<MUX0); // Channel ADC9 = thermocouple #1 uint16_t th_temp = adc_read(); // Get the first temperature reading... ADMUX |= (1<<MUX1); // Channel ADC10 = thermocouple #2 th_temp += adc_read(); // Add the second temperature reading to the first... th_temp <<= 1 ; // Divide by 2 for average // Now convert to temperature in *C // 41 uV/*C, K = 196 -> 41*196 = 8.036 mV/*C / 2.5 mV/div -> 3.2144 div/*C -> 0.311 *C/div th_temp *= 31; th_temp /= 100; // 1 *C/div th_temp <<= 2; // 1/4 *C/div th_temp += tmp37_temp; // Add in the cold-junction temp for true reading... return th_temp; } void adc_setup(void) { // ADC @ 250 kHz single conversion mode, 2.56V ARef, using channels 8-10 // ADC8 = TMP37 cold junction sensor // ADC9 = Thermocouple #1 // ADC10 = Thermocouple #2 DIDR2 = (1<<ADC8D) | (1<<ADC9D) | (1<<ADC10D); ADMUX = (1<<REFS0) | (1<<REFS1); ADCSRA = (1<<ADEN) | (1<<ADPS1) | (1<<ADPS2); ADCSRB = (1<<ADHSM) | (1<<MUX5) ; adc_read(); // Dummy read to finish initialization } uint16_t adc_read(void) { ADCSRA |= (1<<ADSC); // start conversion while (ADSRA & (1<<ADSC)) ; // Wait for the conversion to finish... ADMUX &= ~(1<<MUX0) | ~(1<<MUX1) ; // Reset ADC Mux to Channel 8 (TMP_37) return (ADC) ; }
Any advice about functionality, as well as readability, would be greatly appreciated.