diff --git a/lambda-test/.cproject b/lambda-test/.cproject index 668c34f..1974a71 100644 --- a/lambda-test/.cproject +++ b/lambda-test/.cproject @@ -98,7 +98,6 @@ @@ -124,7 +123,9 @@ - + + + diff --git a/lambda-test/avrjunit.h b/lambda-test/avrjunit.h index 6d7a838..ecd18fb 100644 --- a/lambda-test/avrjunit.h +++ b/lambda-test/avrjunit.h @@ -24,6 +24,8 @@ * DISCLAIMER: I'm experienced with Java and I like C, but I'm new here. */ +#include + #ifndef AVRJUNIT_H_ #define AVRJUNIT_H_ @@ -34,7 +36,7 @@ typedef struct { char* class; char* name; - uint8_t (*test)(void); + bool (*test)(void); } test; /** diff --git a/lambda-test/lambda-test.c b/lambda-test/lambda-test.c index c0ad4a2..7c346ba 100644 --- a/lambda-test/lambda-test.c +++ b/lambda-test/lambda-test.c @@ -31,7 +31,9 @@ * http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/LCD-Ansteuerung */ +#include #include +#include #include #include #include @@ -49,18 +51,21 @@ /* Module adc */ -uint8_t testSetupADC(void) { +bool testSetupADC(void) { setupADC(); // AVCC is set as AREF - return (ADMUX & (1 << REFS0)) == (1 << REFS0); - // ADC clock prescaler/16 - return (ADCSRA & (1 << ADPS2)) == (1 << ADPS2); + if (! (ADMUX & (1 << REFS0)) == (1 << REFS0)) return false; + // ADC clock prescaler/8 + uint8_t prescalerBy8 = (1 << ADPS1) | (1 << ADPS0); + if (! (ADCSRA & prescalerBy8) == prescalerBy8) return false; // ADC enabled - return (ADCSRA & (1 << ADEN)) == (1 << ADEN); + if (! (ADCSRA & (1 << ADEN)) == (1 << ADEN)) return false; + + return true; } -uint8_t testSetupSleepMode(void) { +bool testSetupSleepMode(void) { setupSleepMode(); // don't know how to verify these @@ -71,7 +76,7 @@ return (ADCSRA & (1 << ADIE)) == (1 << ADIE); } -uint8_t testGetVoltage(void) { +bool testGetVoltage(void) { setupADC(); setupSleepMode(); @@ -92,129 +97,159 @@ /* Module integers */ -uint8_t testDivRoundNearest(void) { +bool testMeasure(void) { + setupADC(); + setupSleepMode(); + + // enable pull-up resistor so the measured voltage + // should be (close to?) AREF + PORTC |= ((1 << PC5) | (1 << PC0) | (1 << PC2)); + + _delay_ms(10); + + // do many measurements so the averaged voltages are near the measured + // voltages (close to AREF) + measurement meas; + for (uint8_t i = 0; i < 64; i++) { + meas = measure(); + } + + if (meas.tempIVoltage < 4900) return false; + if (meas.tempOVoltage < 4900) return false; + // lambdaVoltage is divided by the OP amplification factor 11 + if (meas.lambdaVoltage < (4900 / 11)) return false; + + // verify that temperatures and lambda are calculated correctly + if (meas.tempI != toTempI(meas.tempIVoltage)) return false; + if (meas.tempO != toTempO(meas.tempOVoltage)) return false; + if (meas.lambda != toLambda(meas.lambdaVoltage)) return false; + + return true; +} + +bool testDivRoundNearest(void) { int32_t round = 0; round = divRoundNearest(4, 2); - if (round != 2) return 0; + if (round != 2) return false; round = divRoundNearest(5, 2); - if (round != 3) return 0; + if (round != 3) return false; round = divRoundNearest(10, 3); - if (round != 3) return 0; + if (round != 3) return false; - return 1; + return true; } -uint8_t testDivRoundNearestNumNeg(void) { +bool testDivRoundNearestNumNeg(void) { int32_t round = 0; round = divRoundNearest(-4, 2); - if (round != -2) return 0; + if (round != -2) return false; round = divRoundNearest(-5, 2); - if (round != -3) return 0; + if (round != -3) return false; round = divRoundNearest(-10, 3); - if (round != -3) return 0; + if (round != -3) return false; - return 1; + return true; } -uint8_t testDivRoundNearestDenNeg(void) { +bool testDivRoundNearestDenNeg(void) { int32_t round = 0; round = divRoundNearest(4, -2); - if (round != -2) return 0; + if (round != -2) return false; round = divRoundNearest(5, -2); - if (round != -3) return 0; + if (round != -3) return false; round = divRoundNearest(10, -3); - if (round != -3) return 0; + if (round != -3) return false; - return 1; + return true; } -uint8_t testDivRoundNearestBothNeg(void) { +bool testDivRoundNearestBothNeg(void) { int32_t round = 0; round = divRoundNearest(-4, -2); - if (round != 2) return 0; + if (round != 2) return false; round = divRoundNearest(-5, -2); - if (round != 3) return 0; + if (round != 3) return false; round = divRoundNearest(-10, -3); - if (round != 3) return 0; + if (round != 3) return false; - return 1; + return true; } -uint8_t testDivRoundUp(void) { +bool testDivRoundUp(void) { int32_t round = 0; round = divRoundUp(4, 2); - if (round != 2) return 0; + if (round != 2) return false; round = divRoundUp(5, 2); - if (round != 3) return 0; + if (round != 3) return false; round = divRoundUp(10, 3); - if (round != 4) return 0; + if (round != 4) return false; - return 1; + return true; } -uint8_t testDivRoundUpNumNeg(void) { +bool testDivRoundUpNumNeg(void) { int32_t round = 0; round = divRoundUp(-4, 2); - if (round != -2) return 0; + if (round != -2) return false; round = divRoundUp(-5, 2); - if (round != -3) return 0; + if (round != -3) return false; round = divRoundUp(-10, 3); - if (round != -4) return 0; + if (round != -4) return false; - return 1; + return true; } -uint8_t testDivRoundUpDenNeg(void) { +bool testDivRoundUpDenNeg(void) { int32_t round = 0; round = divRoundUp(4, -2); - if (round != -2) return 0; + if (round != -2) return false; round = divRoundUp(5, -2); - if (round != -3) return 0; + if (round != -3) return false; round = divRoundUp(10, -3); - if (round != -4) return 0; + if (round != -4) return false; - return 1; + return true; } -uint8_t testDivRoundUpBothNeg(void) { +bool testDivRoundUpBothNeg(void) { int32_t round = 0; round = divRoundUp(-4, -2); - if (round != 2) return 0; + if (round != 2) return false; round = divRoundUp(-5, -2); - if (round != 3) return 0; + if (round != 3) return false; round = divRoundUp(-10, -3); - if (round != 4) return 0; + if (round != 4) return false; - return 1; + return true; } /* Module sensors */ -uint8_t testAverageUp(void) { +bool testAverageUp(void) { int32_t value = 10; int32_t avg = 0; for (uint8_t i = 0; i < 14; i++) { @@ -224,7 +259,7 @@ return divRoundNearest(avg, 16) == value; } -uint8_t testAverageDown(void) { +bool testAverageDown(void) { int32_t value = 0; int32_t avg = (10 << 4); for (uint8_t i = 0; i < 14; i++) { @@ -234,73 +269,91 @@ return divRoundNearest(avg, 16) == value; } -uint8_t testAverageDoesNotWrap(void) { +bool testAverageDoesNotWrap(void) { int32_t value = 5000; int32_t avg = (value << 4); - avg = average((value << 4), avg, 8); + avg = average((value << 4), avg, 16); return divRoundNearest(avg, 16) == value; } -uint8_t testToLambdaValue(void) { +bool testToLambdaValue(void) { int16_t lambda = toLambda(12); return lambda == 1500; } -uint8_t testToLambdaInter(void) { +bool testToLambdaInter(void) { int16_t lambda = toLambda(50); return lambda == 1073; } -uint8_t testToTempI(void) { +bool testToTempI(void) { int16_t temp = toTempI(100); return temp == 20; } -uint8_t testToTempOValue(void) { +bool testToTempOValue(void) { int16_t temp = toTempO(454); return temp == 0; } -uint8_t testToTempOInter(void) { +bool testToTempOInter(void) { int16_t temp = toTempO(929); return temp == 50; } -uint8_t testLookupLinInterBelow(void) { +bool testLookupLinInterBelow(void) { int16_t value = lookupLinInter(-5, testTable, 2); return value == 0; } -uint8_t testLookupLinInterAbove(void) { +bool testLookupLinInterAbove(void) { int16_t value = lookupLinInter(15, testTable, 2); return value == 10; } -uint8_t testLookupLinInterValue(void) { +bool testLookupLinInterValue(void) { int16_t value = lookupLinInter(10, testTable, 2); return value == 10; } -uint8_t testLookupLinInterInter(void) { +bool testLookupLinInterInter(void) { int16_t value = lookupLinInter(3, testTable, 2); return value == 3; } +bool testToInfoLean(void) { + const char* info = toInfo(1600); + + return ! strcmp(info, LEAN); +} + +bool testToInfoIdeal(void) { + const char* info = toInfo(1400); + + return ! strcmp(info, IDEAL); +} + +bool testToInfoRich(void) { + const char* info = toInfo(1200); + + return ! strcmp(info, RICH); +} + // these long function names passed along as strings use a lot of memory test tests[] = { {"adc", "testSetupADC", testSetupADC}, - {"adc", "testGetVoltage", testGetVoltage}, {"adc", "testSetupSleepMode", testSetupSleepMode}, + {"adc", "testGetVoltage", testGetVoltage}, {"integers", "testDivRoundNearest", testDivRoundNearest}, {"integers", "testDivRoundNearestNumNeg", testDivRoundNearestNumNeg}, {"integers", "testDivRoundNearestDenNeg", testDivRoundNearestDenNeg}, @@ -309,6 +362,7 @@ {"integers", "testDivRoundUpNumNeg", testDivRoundUpNumNeg}, {"integers", "testDivRoundUpDenNeg", testDivRoundUpDenNeg}, {"integers", "testDivRoundUpBothNeg", testDivRoundUpBothNeg}, + {"sensors", "testMeasure", testMeasure}, {"sensors", "testAverageUp", testAverageUp}, {"sensors", "testAverageDown", testAverageDown}, {"sensors", "testAverageDoesNotWrap", testAverageDoesNotWrap}, @@ -320,7 +374,10 @@ {"sensors", "testLookupLinInterValue", testLookupLinInterValue}, {"sensors", "testLookupLinInterInter", testLookupLinInterInter}, {"sensors", "testLookupLinInterBelow", testLookupLinInterBelow}, - {"sensors", "testLookupLinInterAbove", testLookupLinInterAbove} + {"sensors", "testLookupLinInterAbove", testLookupLinInterAbove}, + {"sensors", "testToInfoLean", testToInfoLean}, + {"sensors", "testToInfoIdeal", testToInfoIdeal}, + {"sensors", "testToInfoRich", testToInfoRich} }; int main(void) { diff --git a/lambda/.cproject b/lambda/.cproject index 53d0420..2e6c620 100644 --- a/lambda/.cproject +++ b/lambda/.cproject @@ -63,7 +63,9 @@ - + + + @@ -85,7 +87,7 @@ @@ -93,9 +95,7 @@ + diff --git a/lambda/adc.c b/lambda/adc.c index b11adb7..913a6a4 100644 --- a/lambda/adc.c +++ b/lambda/adc.c @@ -34,10 +34,8 @@ void setupADC(void) { // use AVCC as reference voltage ADMUX |= (1 << REFS0); - // ADC clock prescaler/64 - // ADCSRA |= (1 << ADPS1) | (1 << ADPS2); - // ADC clock prescaler/16 - ADCSRA |= (1 << ADPS2); + // ADC clock prescaler/8 + ADCSRA |= (1 << ADPS1) | (1 << ADPS0); // enable ADC ADCSRA |= (1 << ADEN); } diff --git a/lambda/lambda.c b/lambda/lambda.c index 1e121fe..064d218 100644 --- a/lambda/lambda.c +++ b/lambda/lambda.c @@ -59,7 +59,8 @@ // main loop while (1) { - measure(); + measurement meas = measure(); + display(meas); _delay_ms(1000); } diff --git a/lambda/sensors.c b/lambda/sensors.c index a43375b..33383aa 100644 --- a/lambda/sensors.c +++ b/lambda/sensors.c @@ -82,49 +82,54 @@ /** * Measures the "input" and "output" temperatures and the lambda value * and displays the measured values. - * TODO tests, with local implementation of getVoltage()? */ -void measure(void) { - int16_t tempIVoltage = getVoltage(PC5); +measurement measure(void) { + int32_t tempIVoltage = getVoltage(PC5); tempIVoltageAvg = average((tempIVoltage << 4), tempIVoltageAvg, 4); - int16_t tempOVoltage = getVoltage(PC0); + int32_t tempOVoltage = getVoltage(PC0); tempOVoltageAvg = average((tempOVoltage << 4), tempOVoltageAvg, 4); // OP factor is 11 - int16_t lambdaVoltage = divRoundNearest(getVoltage(PC2), 11); + int32_t lambdaVoltage = divRoundNearest(getVoltage(PC2), 11); lambdaVoltageAvg = average((lambdaVoltage << 4), lambdaVoltageAvg, 4); - int16_t tempIVoltageAvgDiv = divRoundNearest(tempIVoltageAvg, 16); - int16_t tempOVoltageAvgDiv = divRoundNearest(tempOVoltageAvg, 16); - int16_t lambdaVoltageAvgDiv = divRoundNearest(lambdaVoltageAvg, 16); + // TODO just for testing, remove at some point + char log[64]; + snprintf(log, sizeof(log), + "Ti %3d C %4ld - To %3d C %4ld - L %4ld\r\n", + toTempI(tempIVoltage), tempIVoltage, + toTempO(tempOVoltage), tempOVoltage, + lambdaVoltage); + // printString(log); - int16_t tempI = toTempI(tempIVoltageAvgDiv); - int16_t tempO = toTempO(tempOVoltageAvgDiv); - int16_t lambda = toLambda(lambdaVoltageAvgDiv); + measurement meas; + meas.tempIVoltage = divRoundNearest(tempIVoltageAvg, 16); + meas.tempOVoltage = divRoundNearest(tempOVoltageAvg, 16); + meas.lambdaVoltage = divRoundNearest(lambdaVoltageAvg, 16); - display(tempIVoltageAvgDiv, tempI, - tempOVoltageAvgDiv, tempO, - lambdaVoltageAvgDiv, lambda); + meas.tempI = toTempI(meas.tempIVoltage); + meas.tempO = toTempO(meas.tempOVoltage); + meas.lambda = toLambda(meas.lambdaVoltage); + + return meas; } -void display( - int16_t tempIVoltage, int16_t tempI, - int16_t tempOVoltage, int16_t tempO, - int16_t lambdaVoltage, int16_t lambda) { - div_t lambdaT = div(lambda, 1000); +void display(measurement meas) { + div_t lambdaT = div(meas.lambda, 1000); char log[64]; - snprintf(log, sizeof(log), "Ti %3d C %4d - To %3d C %4d - L %d.%03d %4d\r\n", - tempI, tempIVoltage, tempO, tempOVoltage, - lambdaT.quot, abs(lambdaT.rem), lambdaVoltage); + snprintf(log, sizeof(log), + "Ti %3d C %4d - To %3d C %4d - L %d.%03d %4d\r\n", + meas.tempI, meas.tempIVoltage, meas.tempO, meas.tempOVoltage, + lambdaT.quot, abs(lambdaT.rem), meas.lambdaVoltage); printString(log); char line0[17]; char line1[17]; - snprintf(line0, sizeof(line0), "Ti %3dC To %3dC", tempI, tempO); - snprintf(line1, sizeof(line1), "L %d.%03d %s", - lambdaT.quot, abs(lambdaT.rem), toInfo(lambda)); + snprintf(line0, sizeof(line0), "Ti %3dC To %3dC ", meas.tempI, meas.tempO); + snprintf(line1, sizeof(line1), "L %d.%03d %s ", + lambdaT.quot, abs(lambdaT.rem), toInfo(meas.lambda)); lcd_setcursor(0, 1); lcd_string(line0); lcd_setcursor(0, 2); @@ -171,8 +176,8 @@ int16_t diffVoltage = table[i + 1].mV - table[i].mV; int16_t diffValue = table[i + 1].value - table[i].value; - int16_t value = table[i].value + - divRoundNearest((int32_t)(mV - table[i].mV) * diffValue, diffVoltage); + int16_t value = table[i].value + divRoundNearest( + (int32_t)(mV - table[i].mV) * diffValue, diffVoltage); return value; } diff --git a/lambda/sensors.h b/lambda/sensors.h index 84fc027..a14991e 100644 --- a/lambda/sensors.h +++ b/lambda/sensors.h @@ -29,8 +29,8 @@ // TODO put in Makefile? #define LEAN "Mager" -#define IDEAL "Ideal"; -#define RICH "Fett!"; +#define IDEAL "Ideal" +#define RICH "Fett!" /** * Entry for the lookup tables. @@ -41,19 +41,28 @@ } tableEntry; /** + * Measured values. + */ +typedef struct { + int16_t tempIVoltage; + int16_t tempI; + int16_t tempOVoltage; + int16_t tempO; + int16_t lambdaVoltage; + int16_t lambda; +} measurement; + +/** * Measures the "input" and "output" temperatures and the lambda value * and displays the measured values. */ -void measure(void); +measurement measure(void); /** * Formats the given values, displays them on an 16x2 LCD * and prints them over USART. */ -void display( - int16_t tempIVoltage, int16_t tempI, - int16_t tempOVoltage, int16_t tempO, - int16_t lambdaVoltage, int16_t lambda); +void display(measurement); /** * Creates an exponential moving average of the given value and