diff --git a/lambda-test/Makefile b/lambda-test/Makefile index d5fcefd..f319fa6 100644 --- a/lambda-test/Makefile +++ b/lambda-test/Makefile @@ -18,7 +18,8 @@ ## Here you can link to one more directory (and multiple .c files) EXTRA_SOURCE_DIR = ../lambda/ -EXTRA_SOURCE_FILES = USART.c adc.c sensors.c integers.c +EXTRA_SOURCE_FILES = USART.c interrupts.c adc.c sensors.c integers.c \ +lcdroutines.c display.c ##########------------------------------------------------------########## ########## Programmer Defaults ########## diff --git a/lambda-test/lambda-test.c b/lambda-test/lambda-test.c index 4a3bbe7..b7dfc35 100644 --- a/lambda-test/lambda-test.c +++ b/lambda-test/lambda-test.c @@ -24,9 +24,11 @@ #include #include #include "USART.h" +#include "interrupts.h" #include "adc.h" #include "integers.h" #include "sensors.h" +#include "display.h" #include "avrjunit.h" static const tableEntry testTable[] = { @@ -34,6 +36,40 @@ {20, 20} }; +/* Module interrupts */ + +bool testSetupPorts(void) { + setupPorts(); + + // test that pull-up resistor for the mouton is enabled + assertTrue(bit_is_set(PORTB, PB0)); + + return true; +} + +bool testSetupSleepMode(void) { + setupSleepMode(); + + // set_sleep_mode(SLEEP_MODE_ADC); + assertTrue(bit_is_set(SMCR, SM0)); + + return true; +} + +bool testInitInterrupts(void) { + initInterrupts(); + + // ADC interrupt enabled + assertTrue(bit_is_set(ADCSRA, ADIE)); + // PC interrupts enabled + assertTrue(bit_is_set(PCICR, PCIE0)); + assertTrue(bit_is_set(PCMSK0, PB0)); + // sei(); // enable global interrupts + assertTrue(bit_is_set(SREG, SREG_I)); + + return true; +} + /* Module adc */ bool testSetupADC(void) { @@ -53,20 +89,8 @@ return true; } -bool testSetupSleepMode(void) { - setupSleepMode(); - - // set_sleep_mode(SLEEP_MODE_ADC); - assertTrue(bit_is_set(SMCR, SM0)); - // sei(); // enable global interrupts - assertTrue(bit_is_set(SREG, SREG_I)); - // ADC interrupt enabled - assertTrue(bit_is_set(ADCSRA, ADIE)); - - return true; -} - bool testGetVoltage(void) { + initInterrupts(); setupADC(); setupSleepMode(); @@ -264,10 +288,38 @@ return ! strcmp(info, RICH); } +/* Module display */ + +// TODO assertions +bool testCycle(void) { + + return true; +} + +// TODO assertions +bool testUpdateInitial(void) { + + return true; +} + +// TODO assertions +bool testUpdate(void) { + // set first display option so display() won't actually log something + // via USART which would break the test result XML + // TODO elegant solution for this and testing display()? + + // measurement meas = {0, 0, 0, 0, 0, 0}; + // update(meas); + + return true; +} + // these long function names passed along as strings use a lot of memory test tests[] = { + {"interrupts", "testSetupPorts", testSetupPorts}, + {"interrupts", "testSetupSleepMode", testSetupSleepMode}, + {"interrupts", "testInitInterrupts", testInitInterrupts}, {"adc", "testSetupADC", testSetupADC}, - {"adc", "testSetupSleepMode", testSetupSleepMode}, {"adc", "testGetVoltage", testGetVoltage}, {"integers", "testDivRoundNearest", testDivRoundNearest}, {"integers", "testDivRoundNearestNumNeg", testDivRoundNearestNumNeg}, @@ -290,7 +342,10 @@ {"sensors", "testToInfoLean", testToInfoLean}, {"sensors", "testToInfoOkay", testToInfoOkay}, {"sensors", "testToInfoIdeal", testToInfoIdeal}, - {"sensors", "testToInfoRich", testToInfoRich} + {"sensors", "testToInfoRich", testToInfoRich}, + {"display", "testCycle", testCycle}, + {"display", "testUpdateInitial", testUpdateInitial}, + {"display", "testUpdate", testUpdate} }; int main(void) { diff --git a/lambda/Makefile b/lambda/Makefile index 677df4a..5cc8122 100644 --- a/lambda/Makefile +++ b/lambda/Makefile @@ -14,7 +14,8 @@ ## If you've split your program into multiple .c / .h files, ## include the additional source (in same directory) here -LOCAL_SOURCE = USART.c adc.c sensors.c integers.c lcdroutines.c +LOCAL_SOURCE = USART.c interrupts.c adc.c sensors.c integers.c lcdroutines.c \ +display.c ## Here you can link to one more directory (and multiple .c files) EXTRA_SOURCE_DIR = diff --git a/lambda/adc.c b/lambda/adc.c index 10913db..1d9eee0 100644 --- a/lambda/adc.c +++ b/lambda/adc.c @@ -13,8 +13,10 @@ #include #include "adc.h" -// set up a fake ISR to just return to where sleep_mode() was called -// when ADC conversion is complete (ADC_vect) +/** + * Sets up a fake ISR to just return to where sleep_mode() was called + * when ADC conversion is complete (ADC_vect). + */ EMPTY_INTERRUPT(ADC_vect); void setupADC(void) { @@ -29,14 +31,6 @@ ADCSRA |= (1 << ADEN); } -void setupSleepMode(void) { - set_sleep_mode(SLEEP_MODE_ADC); - // enable ADC interrupt - ADCSRA |= (1 << ADIE); - // enable global interrupts - sei(); -} - uint16_t getVoltage(uint8_t pin) { ADMUX = (0b11110000 & ADMUX) | pin; diff --git a/lambda/adc.h b/lambda/adc.h index e4b9bb3..6dfd73e 100644 --- a/lambda/adc.h +++ b/lambda/adc.h @@ -25,11 +25,6 @@ void setupADC(void); /** - * Sets up sleep mode and enables ADC and global interrupts. - */ -void setupSleepMode(void); - -/** * Returns the voltage sampled at the given ADC input pin doing * 16x oversampling and taking in account the calibrated AREF and * ADC offset voltages. diff --git a/lambda/display.c b/lambda/display.c new file mode 100644 index 0000000..8237f9b --- /dev/null +++ b/lambda/display.c @@ -0,0 +1,98 @@ +/* + * display.c + * + * Created on: 10.04.2015 + * Author: dode@luniks.net + */ + +#include +#include +#include +#include +#include +#include "USART.h" +#include "lcdroutines.h" +#include "integers.h" +#include "sensors.h" +#include "display.h" + +#define MAX(x, y) (((x) > (y)) ? (x) : (y)) +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +#define MENU_OFF 0 +#define MENU_MIN_VALUES 1 +#define MENU_MAX_VALUES 2 + +uint8_t position = MENU_OFF; +char* hint = " "; +measurement measCur; +measurement measMin = {0, 20, 0, 20, 0, 2000}; +measurement measMax = {0, 0, 0, 0, 0, 0}; + +/** + * Cycles through the "menu" (display options) when the menu button is pressed. + */ +ISR(PCINT0_vect) { + if (bit_is_clear(PINB, PB0)) { + _delay_ms(30); + if (bit_is_clear(PINB, PB0)) { + cycle(); + } + } +} + +void cycle(void) { + position++; + if (position == MENU_MIN_VALUES) { + // PORTB |= (1 << PB1); + hint = " <"; + display(measMin); + } else if (position == MENU_MAX_VALUES) { + // PORTB |= (1 << PB1); + hint = " >"; + display(measMax); + } else { + position = MENU_OFF; + // PORTB &= ~(1 << PB1); + hint = " "; + display(measCur); + } +} + +void update(measurement meas) { + measCur = meas; + + measMin.tempI = MIN(measMin.tempI, meas.tempI); + measMin.tempO = MIN(measMin.tempO, meas.tempO); + measMin.lambda = MIN(measMin.lambda, meas.lambda); + + measMax.tempI = MAX(measMax.tempI, meas.tempI); + measMax.tempO = MAX(measMax.tempO, meas.tempO); + measMax.lambda = MAX(measMax.lambda, meas.lambda); + + if (position == MENU_OFF) { + display(meas); + } +} + +void display(measurement meas) { + uint16_t lambdax100 = divRoundNearest(meas.lambda, 10); + div_t lambdaT = div(lambdax100, 100); + + char log[64]; + snprintf(log, sizeof(log), + "Ti %3d C %4u - To %3d C %4u - L %4u %4u %s\r\n", + meas.tempI, meas.tempIVoltage, meas.tempO, meas.tempOVoltage, + meas.lambda, meas.lambdaVoltage, hint); + printString(log); + + char line0[17]; + char line1[17]; + snprintf(line0, sizeof(line0), "Ti %3dC To %3dC ", meas.tempI, meas.tempO); + snprintf(line1, sizeof(line1), "L %d.%02d %s %s", + lambdaT.quot, abs(lambdaT.rem), toInfo(lambdax100), hint); + lcd_setcursor(0, 1); + lcd_string(line0); + lcd_setcursor(0, 2); + lcd_string(line1); +} diff --git a/lambda/display.h b/lambda/display.h new file mode 100644 index 0000000..11196d0 --- /dev/null +++ b/lambda/display.h @@ -0,0 +1,28 @@ +/* + * display.h + * + * Created on: 10.04.2015 + * Author: dode@luniks.net + */ + +#ifndef DISPLAY_H_ +#define DISPLAY_H_ + +/** + * Cycles through the "menu" (display options). + */ +void cycle(void); + +/** + * Updates the measurements, tracks min and max values since last start/reset + * and display the current measurements unless the "menu" is active. + */ +void update(measurement); + +/** + * Formats the given values, displays them on an 16x2 LCD + * and prints them over USART. + */ +void display(measurement); + +#endif /* DISPLAY_H_ */ diff --git a/lambda/interrupts.c b/lambda/interrupts.c new file mode 100644 index 0000000..a182ce1 --- /dev/null +++ b/lambda/interrupts.c @@ -0,0 +1,34 @@ +/* + * interrupts.c + * + * Created on: 10.04.2015 + * Author: dode@luniks.net + */ + +#include +#include +#include "interrupts.h" + +void setupPorts(void) { + // pull-up resistor for the mouton + PORTB |= (1 << PB0); + + // PB1 as output + // DDRB |= (1 << PB1); +} + +void setupSleepMode(void) { + set_sleep_mode(SLEEP_MODE_ADC); +} + +void initInterrupts(void) { + // enable ADC interrupt + ADCSRA |= (1 << ADIE); + + // enable PC interrupts + PCICR |= (1 << PCIE0); + PCMSK0 |= (1 << PB0); + + // enable global interrupts + sei(); +} diff --git a/lambda/interrupts.h b/lambda/interrupts.h new file mode 100644 index 0000000..2a14296 --- /dev/null +++ b/lambda/interrupts.h @@ -0,0 +1,26 @@ +/* + * interrupts.h + * + * Created on: 10.04.2015 + * Author: dode@luniks.net + */ + +#ifndef INTERRUPTS_H_ +#define INTERRUPTS_H_ + +/** + * Sets up ports. + */ +void setupPorts(void); + +/** + * Sets up sleep mode. + */ +void setupSleepMode(void); + +/** + * Inits the interrupts. + */ +void initInterrupts(void); + +#endif /* INTERRUPTS_H_ */ diff --git a/lambda/lambda.c b/lambda/lambda.c index 8fe800d..3fe192b 100644 --- a/lambda/lambda.c +++ b/lambda/lambda.c @@ -21,10 +21,12 @@ #include #include #include "USART.h" +#include "lcdroutines.h" #include "adc.h" +#include "interrupts.h" #include "sensors.h" #include "integers.h" -#include "lcdroutines.h" +#include "display.h" /** * Initializes the USART transmitter and receiver, the lcd, sets up the ADC @@ -35,13 +37,15 @@ int main(void) { initUSART(); lcd_init(); + setupPorts(); setupADC(); setupSleepMode(); + initInterrupts(); // main loop while (1) { measurement meas = measure(); - display(meas); + update(meas); _delay_ms(1000); } diff --git a/lambda/sensors.c b/lambda/sensors.c index 2a56e95..15554ff 100644 --- a/lambda/sensors.c +++ b/lambda/sensors.c @@ -12,11 +12,9 @@ #include #include #include -#include "USART.h" #include "adc.h" #include "sensors.h" #include "integers.h" -#include "lcdroutines.h" /** * Table used to look up the lambda value at 12 V heater voltage @@ -61,9 +59,9 @@ /** * Global variables holding averaged voltages. */ -uint32_t lambdaVoltageAvg = 4; -uint32_t tempIVoltageAvg = 4; -uint32_t tempOVoltageAvg = 4; +uint32_t lambdaVoltageAvg = 44 << 3; // Lambda 2.00 +uint32_t tempIVoltageAvg = 100 << 3; // 20°C +uint32_t tempOVoltageAvg = 644 << 3; // 20°C /** * Measures the "input" and "output" temperatures and the lambda value, @@ -78,7 +76,6 @@ tempOVoltageAvg = tempOVoltage + tempOVoltageAvg - ((tempOVoltageAvg - 4) >> 3); - // OP factor is 11 uint32_t lambdaVoltage = getVoltage(PC2); lambdaVoltageAvg = lambdaVoltage + lambdaVoltageAvg - ((lambdaVoltageAvg - 4) >> 3); @@ -95,28 +92,6 @@ return meas; } -void display(measurement meas) { - uint16_t lambdax100 = divRoundNearest(meas.lambda, 10); - div_t lambdaT = div(lambdax100, 100); - - char log[64]; - snprintf(log, sizeof(log), - "Ti %3d C %4u - To %3d C %4u - L %4u %4u\r\n", - meas.tempI, meas.tempIVoltage, meas.tempO, meas.tempOVoltage, - meas.lambda, meas.lambdaVoltage); - printString(log); - - char line0[17]; - char line1[17]; - snprintf(line0, sizeof(line0), "Ti %3dC To %3dC ", meas.tempI, meas.tempO); - snprintf(line1, sizeof(line1), "L %d.%02d %s ", - lambdaT.quot, abs(lambdaT.rem), toInfo(lambdax100)); - lcd_setcursor(0, 1); - lcd_string(line0); - lcd_setcursor(0, 2); - lcd_string(line1); -} - int16_t toTempI(uint16_t mV) { int temp = divRoundNearest(mV, 5); diff --git a/lambda/sensors.h b/lambda/sensors.h index a64148f..fa53989 100644 --- a/lambda/sensors.h +++ b/lambda/sensors.h @@ -45,12 +45,6 @@ measurement measure(void); /** - * Formats the given values, displays them on an 16x2 LCD - * and prints them over USART. - */ -void display(measurement); - -/** * Returns the temperature for the given voltage of a type K thermocouple * amplified with an AD8495 (5 mV/°C). Type K thermocouple voltages are * about linear between 0 and 800°C.