133 lines
3.4 KiB
C
Executable File
133 lines
3.4 KiB
C
Executable File
#include "main.h"
|
|
|
|
|
|
const char* lm35_string = "LM35 Temp: ";
|
|
const struct {
|
|
x = sizeof(lm35_string);
|
|
y = 0;
|
|
} lm35_value_pos;
|
|
|
|
#ifdef CALIBRATION
|
|
const char* diode_string = "Diode Value: ";
|
|
#else
|
|
const char* diode_string = "Diode Temp: ";
|
|
#endif
|
|
|
|
const struct {
|
|
x = sizeof(diode_string);
|
|
y = 1;
|
|
} diode_value_pos;
|
|
|
|
/** @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 << DDRC0);
|
|
DIDR0 |= (1 << ADC0D); // Disable digital input
|
|
|
|
// Pin Config for LM35 ADC
|
|
DDRC &= ~(1 << DDRC1);
|
|
DIDR0 |= (1 << ADC1D); // Disable digital input
|
|
}
|
|
|
|
/** @brief Initializes ADC with required settings
|
|
*/
|
|
void adc_init() {
|
|
/* ADC Settings
|
|
* Use Aref as Vref
|
|
* Initially set input as GND
|
|
* Data right-adjusted
|
|
* No Interrupts
|
|
*/
|
|
|
|
// Set MUX[3:0] to 0b1111 (GND reference)
|
|
ADMUX |= (1 << MUX3) | (1 << MUX2) | (1 << MUX1) | (1 << MUX0);
|
|
// Make sure data is right adjusted
|
|
ADMUX &= ~(1 << ADLAR);
|
|
|
|
// 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.
|
|
*/
|
|
uint16_t adc_run_conversion(uint8_t adc_selection) {
|
|
// Select ADC
|
|
ADMUX &= 0xF0 | adc_selection;
|
|
|
|
// Start conversion
|
|
ADCSRA |= (1 << ADSC);
|
|
|
|
// Wait until conversion is complete
|
|
while (ADCSRA & (1 << ADIF));
|
|
|
|
// Read out conversion value
|
|
// may not be correct
|
|
return ADC;
|
|
}
|
|
|
|
|
|
float lm35_convert(uint16_t adc_reading) {
|
|
return (float) (adc_reading * ADC_VREF / ADC_RESOLUTION) / LM35_SENSITIVITY;
|
|
}
|
|
|
|
int main() {
|
|
// Initialise peripherals
|
|
pin_init();
|
|
adc_init();
|
|
|
|
// Initialise display
|
|
// NOTE: LCD uses PB0-PB6
|
|
lcd_init(LCD_DISP_ON);
|
|
|
|
// Write "base" strings to LCD
|
|
lcd_puts(lm35_string);
|
|
lcd_gotoxy(0, diode_value_pos.y); // Switch to bottom
|
|
lcd_puts(diode_string);
|
|
|
|
|
|
// Note that special compiler/linker flags have to be added to enable
|
|
// printf-ing floats
|
|
// See: https://startingelectronics.org/articles/atmel-AVR-8-bit/print-float-atmel-studio-7/
|
|
while (1) {
|
|
// Read LM35 value, and write to LCD
|
|
float lm35_temp = lm35_convert(adc_run_conversion(1));
|
|
// Convert measured value to string
|
|
char[6] lm35_temp_str;
|
|
sprintf(lm35_temp_str, "%3.1f", lm35_temp);
|
|
|
|
// Display temp on LCD
|
|
lcd_gotoxy(lm35_value_pos.x, lm35_value_pos.y);
|
|
lcd_puts((const char*) lm35_temp_str);
|
|
|
|
|
|
// Read diode value, and write to LCD
|
|
#ifdef CALIBRATION
|
|
uint16_t diode_value = adc_run_conversion(0);
|
|
char[6] diode_str;
|
|
sprintf(diode_str, "%d", diode_value);
|
|
#else
|
|
float diode_temp = diode_convert(adc_run_conversion(0));
|
|
char[6] diode_str;
|
|
sprintf(diode_str, "%3.1f", diode_temp);
|
|
#endif
|
|
|
|
// Display diode info on LCD
|
|
lcd_gotoxy(diode_value_pos.x, diode_value_pos.y);
|
|
lcd_puts((const char*) diode_str);
|
|
}
|
|
|
|
}
|