#include "main.h" // arrays to hold strings for LCD static char lm35_string[17]; static char diode_string[17]; /** @brief Initialises general pins for use. * * @note Does not initialise LCD pins. That is handled by lcdlibrary */ void pin_init() { /* Pin Mappings: * PC0 -> ADC0 input for diode measurement * PC1 -> ADC1 input for LM35 */ // Pin Config for Diode ADC DDRC &= ~(1 << DDC0); DIDR0 |= (1 << ADC0D); // Disable digital input // Pin Config for LM35 ADC DDRC &= ~(1 << DDC1); DIDR0 |= (1 << ADC1D); // Disable digital input } /** @brief Initializes ADC with required settings */ void adc_init() { /* ADC Settings * Use 1v1 reference as Vref * Initially set input as GND * Data right-adjusted * No Interrupts */ // Set Vref ADMUX |= (1 << REFS1) | (1 << REFS0); // Set the clock prescaler to 128 (slower ADC means more accurate measurements) ADCSRA |= (1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0); // Enable ADC ADCSRA |= (1 << ADEN); } /** @brief Blocking function to read an ADC conversion from a selected ADC input. * * @note Blocks until conversion finishes, so speed of this function is dependant * on ADC prescaler. * * @param adc_selection Value from 0-5, selects from ADC[0-5] * * @return Raw value of ADC conversion */ uint16_t adc_run_conversion(uint8_t adc_selection) { // Select ADC input, using ADMUX = (ADMUX & 0xF0) | (0x0F & adc_selection); // Start conversion ADCSRA |= (1 << ADSC); // Wait until conversion is complete while (!(ADCSRA & (1 << ADIF))); // Read out conversion value return ADC; } /** @brief Converts an ADC value from a measurement on an LM35 into a temperature. * * @param adc_reading Raw ADC measurement from LM35. * * @return Measured temperature, configure parameters in main.h */ int8_t lm35_convert(uint16_t adc_reading) { return (adc_reading * ADC_VREF / ADC_RESOLUTION) / LM35_SENSITIVITY; } /** @brief Converts and ADC value from a measurement on a diode into a temperature. * * @param adc_reading Raw ADC measurement from diode. * * @return Measured temperature, configure parameters in main.h */ int8_t diode_convert(uint16_t adc_reading) { int16_t value_diff = adc_reading - DIODE_VALUE_25C; int16_t temp_diff = value_diff / DIODE_SENSITIVITY; return temp_diff + 25; } int main() { // Initialise display // NOTE: LCD uses PB0-PB6 lcd_init(LCD_DISP_ON); // Initialise peripherals pin_init(); adc_init(); while (1) { // Reset position lcd_gotoxy(0, 0); // Read LM35 value, and write to LCD uint16_t lm35_value = adc_run_conversion(1); int8_t lm35_temp = lm35_convert(lm35_value); // Convert measured value to string sprintf(lm35_string, "LM35 : %4d %3dC", lm35_value, lm35_temp); // Display temp on LCD lcd_puts((const char*) lm35_string); lcd_gotoxy(0, 1); // Read diode value, and write to uint16_t diode_value = adc_run_conversion(0); int8_t diode_temp = diode_convert(diode_value); sprintf(diode_string, "Diode: %4d %3dC", diode_value, diode_temp); // Display diode info on LCD lcd_puts((const char*) diode_string); // Refreshing too fast can make the data appear weird _delay_ms(500); } }