ece312/lab_3/main.c
2019-11-05 20:53:18 -07:00

131 lines
3.3 KiB
C
Executable File

#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);
}
}