diff --git a/lambda-test/rules-test.c b/lambda-test/rules-test.c index e12da95..cf428f1 100644 --- a/lambda-test/rules-test.c +++ b/lambda-test/rules-test.c @@ -23,60 +23,56 @@ static bool testAirgate50(void) { - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertFalse(rules[0].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[0].fired); - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertFalse(rules[0].fired); - resetRules(); + resetRules(true); dir = burning; reason(meas); assertFalse(rules[0].fired); - resetRules(); - dir = warm_start; - reason(meas); - assertFalse(rules[0].fired); + meas.tempI = TEMP_AIRGATE_50; + meas.lambda = LAMBDA_TOO_LEAN; - meas.tempI = 500; - meas.lambda = 1500; - - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertFalse(rules[0].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[0].fired); - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertTrue(rules[0].fired); assertTrue(50 == airgate); - resetRules(); - dir = burning; + // should not fire if airgate == 50 + resetRules(false); + dir = firing_up; reason(meas); - assertTrue(rules[0].fired); + assertFalse(rules[0].fired); assertTrue(50 == airgate); - resetRules(); - dir = warm_start; + resetRules(true); + dir = burning; reason(meas); assertTrue(rules[0].fired); assertTrue(50 == airgate); @@ -88,57 +84,47 @@ static bool testAirgate25(void) { - Measurement meas = {999, 0, 0}; + Measurement meas = {999, 0, 0, 0}; - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertFalse(rules[1].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[1].fired); - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertFalse(rules[1].fired); - resetRules(); + resetRules(true); dir = burning; reason(meas); assertFalse(rules[1].fired); - resetRules(); - dir = warm_start; - reason(meas); - assertFalse(rules[1].fired); + meas.tempI = TEMP_AIRGATE_25 - 1; + meas.lambda = LAMBDA_TOO_LEAN; - meas.tempI = 699; - meas.lambda = 1500; - - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertFalse(rules[1].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[1].fired); - resetRules(); + resetRules(true); dir = burning; reason(meas); assertFalse(rules[1].fired); - resetRules(); - dir = warm_start; - reason(meas); - assertFalse(rules[1].fired); - - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertTrue(rules[1].fired); @@ -151,57 +137,47 @@ static bool testAirgateClose(void) { - Measurement meas = {999, 0, 0}; + Measurement meas = {999, 0, 0, 0}; - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertFalse(rules[2].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[2].fired); - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertFalse(rules[2].fired); - resetRules(); + resetRules(true); dir = burning; reason(meas); assertFalse(rules[2].fired); - resetRules(); - dir = warm_start; - reason(meas); - assertFalse(rules[2].fired); + meas.tempI = TEMP_AIRGATE_0 - 1; + meas.lambda = LAMBDA_MAX; - meas.tempI = 399; - meas.lambda = 1500; - - resetRules(); + resetRules(true); dir = firing_up; reason(meas); assertFalse(rules[2].fired); - resetRules(); + resetRules(true); dir = none; reason(meas); assertFalse(rules[2].fired); - resetRules(); + resetRules(true); dir = burning; reason(meas); assertFalse(rules[2].fired); - resetRules(); - dir = warm_start; - reason(meas); - assertFalse(rules[2].fired); - - resetRules(); + resetRules(true); dir = burning_down; reason(meas); assertTrue(rules[2].fired); @@ -214,50 +190,45 @@ static bool testTooRich(void) { - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; dir = none; setHeaterState(heaterStateReady); - meas.tempI = 100; - meas.lambda = 2000; - resetRules(); + meas.tempI = TEMP_FIRE_OUT; + meas.lambda = LAMBDA_MAX; + resetRules(true); reason(meas); assertFalse(rules[3].fired); - meas.tempI = 101; - meas.lambda = 2000; - resetRules(); + meas.tempI = TEMP_FIRE_OUT + 1; + meas.lambda = LAMBDA_MAX; + resetRules(true); reason(meas); assertFalse(rules[3].fired); - meas.tempI = 100; - meas.lambda = 1199; - resetRules(); + meas.tempI = TEMP_FIRE_OUT; + meas.lambda = LAMBDA_TOO_RICH - 1; + resetRules(true); reason(meas); assertFalse(rules[3].fired); - meas.tempI = 101; - meas.lambda = 1199; - resetRules(); + meas.tempI = TEMP_FIRE_OUT + 1; + meas.lambda = LAMBDA_TOO_RICH - 1; + resetRules(true); airgate = 100; reason(meas); assertFalse(rules[3].fired); assertTrue(100 == airgate); - meas.tempI = 101; - meas.lambda = 1199; - resetRules(); + meas.tempI = TEMP_FIRE_OUT + 1; + meas.lambda = LAMBDA_TOO_RICH - 1; + resetRules(true); airgate = 50; reason(meas); assertTrue(rules[3].fired); assertTrue(100 == airgate); - meas.lambda = 1400; - age = 0; - reason(meas); - assertFalse(rules[3].fired); - cancelAlert(false); return true; @@ -265,44 +236,39 @@ static bool testTooLean(void) { - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; dir = none; setHeaterState(heaterStateReady); - meas.tempI = 500; - meas.lambda = 1501; - resetRules(); + meas.tempI = TEMP_AIRGATE_50; + meas.lambda = LAMBDA_TOO_LEAN + 1; + resetRules(true); reason(meas); assertFalse(rules[4].fired); - meas.tempI = 501; + meas.tempI = TEMP_AIRGATE_50 + 1; meas.lambda = 1300; - resetRules(); + resetRules(true); reason(meas); assertFalse(rules[4].fired); - meas.tempI = 501; - meas.lambda = 1501; - resetRules(); + meas.tempI = TEMP_AIRGATE_50 + 1; + meas.lambda = LAMBDA_TOO_LEAN + 1; + resetRules(true); airgate = 50; reason(meas); assertFalse(rules[4].fired); assertTrue(50 == airgate); - meas.tempI = 501; - meas.lambda = 1501; - resetRules(); + meas.tempI = TEMP_AIRGATE_50 + 1; + meas.lambda = LAMBDA_TOO_LEAN + 1; + resetRules(true); airgate = 100; reason(meas); assertTrue(rules[4].fired); assertTrue(50 == airgate); - meas.lambda = 1400; - age = 0; - reason(meas); - assertFalse(rules[4].fired); - cancelAlert(false); return true; @@ -310,8 +276,8 @@ static bool testFireOut(void) { - resetRules(); - Measurement meas = {0, 0, 0}; + resetRules(true); + Measurement meas = {0, 0, 0, 0}; dir = firing_up; meas.tempI = 50; @@ -319,22 +285,22 @@ reason(meas); assertFalse(rules[5].fired); - meas.tempI = 100; + meas.tempI = TEMP_FIRE_OUT; age = 0; reason(meas); assertFalse(rules[5].fired); - meas.tempI = 125; + meas.tempI = TEMP_FIRE_OUT_RESET; age = 0; reason(meas); assertFalse(rules[5].fired); - meas.tempI = 99; + meas.tempI = TEMP_FIRE_OUT - 1; age = 0; reason(meas); assertTrue(rules[5].fired); - meas.tempI = 125; + meas.tempI = TEMP_FIRE_OUT_RESET; age = 0; reason(meas); assertFalse(rules[5].fired); @@ -344,15 +310,42 @@ return true; } -static bool testHeaterReady(void) { +static bool testWarmStart(void) { - resetRules(); - resetTime(); - Measurement meas = {0, 0, 0}; + resetRules(true); + Measurement meas = {0, 0, 0, 0}; + + age = 0; + airgate = 50; + + setHeaterOn(false); + reason(meas); + assertTrue(50 == airgate); + assertTrue(heaterStateOff == getHeaterState()); + assertFalse(rules[6].fired); + + age = 0; dir = firing_up; setHeaterOn(false); - meas.current = 1300; + reason(meas); + assertTrue(100 == airgate); + assertTrue(heaterStateUp == getHeaterState()); + assertTrue(rules[6].fired); + + cancelAlert(false); + + return true; +} + +static bool testHeaterReady(void) { + + resetRules(true); + resetTime(); + Measurement meas = {0, 0, 0, 0}; + + setHeaterOn(false); + meas.current = milliAmpsReady; reason(meas); assertTrue(heaterStateOff == getHeaterState()); @@ -362,7 +355,7 @@ assertTrue(heaterStateUp == getHeaterState()); setHeaterOn(true); - meas.current = 1300; + meas.current = milliAmpsReady; reason(meas); assertTrue(heaterStateReady == getHeaterState()); @@ -373,9 +366,9 @@ static bool testHeaterFaultNoconn(void) { - resetRules(); + resetRules(true); resetTime(); - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; dir = firing_up; setHeaterOn(true); @@ -390,9 +383,9 @@ static bool testHeaterFaultShort(void) { - resetRules(); + resetRules(true); resetTime(); - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; dir = firing_up; setHeaterOn(true); @@ -407,9 +400,9 @@ static bool testHeaterFaultNoheat(void) { - resetRules(); + resetRules(true); resetTime(); - Measurement meas = {0, 0, 0}; + Measurement meas = {0, 0, 0, 0}; dir = firing_up; setHeaterOn(true); @@ -426,20 +419,42 @@ return true; } -static bool testHeaterTimeout(void) { +static bool testHeaterTimeout0(void) { - resetRules(); + resetRules(true); resetTime(); - Measurement meas = {0, 0, 0}; - dir = firing_up; + Measurement meas = {0, 0, 0, 0}; setHeaterOn(true); - // more than 3 hours below 400°C + // equal or more than 30 mins below TEMP_FIRE_OUT + addTime(1800); + + meas.tempI = TEMP_FIRE_OUT - 1; + meas.lambda = LAMBDA_MAX; + meas.current = milliAmpsReady; + reason(meas); + assertTrue(heaterStateOff == getHeaterState()); + + cancelAlert(false); + + return true; +} + +static bool testHeaterTimeout1(void) { + + resetRules(true); + resetTime(); + Measurement meas = {0, 0, 0, 0}; + + setHeaterOn(true); + + // equal or more than 3 hours below TEMP_AIRGATE_0 addTime(10800UL); - meas.tempI = 300; - meas.current = 1300; + meas.tempI = TEMP_AIRGATE_0 - 1; + meas.lambda = LAMBDA_MAX; + meas.current = milliAmpsReady; reason(meas); assertTrue(heaterStateOff == getHeaterState()); @@ -450,45 +465,45 @@ static bool testReasonDirBurnUp(void) { - resetRules(); - Measurement meas = {0, 0, 2000}; + resetRules(true); + Measurement meas = {0, 0, 2000, 0}; age = 0; reason(meas); assertTrue(dir == none); meas.tempI = 9; - meas.lambda = 2000; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == none); - meas.tempI = 100; - meas.lambda = 2000; + meas.tempI = TEMP_FIRE_OUT; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == firing_up); - meas.tempI = 699; - meas.lambda = 2000; + meas.tempI = TEMP_AIRGATE_25 - 1; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == firing_up); - meas.tempI = 699; - meas.lambda = 2000; + meas.tempI = TEMP_AIRGATE_25 - 1; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == none); - meas.tempI = 700; - meas.lambda = 1899; + meas.tempI = TEMP_AIRGATE_25; + meas.lambda = LAMBDA_BURNING - 1; age = 180; reason(meas); assertTrue(dir == burning); - meas.tempI = 701; - meas.lambda = 1900; + meas.tempI = TEMP_AIRGATE_25 + 1; + meas.lambda = LAMBDA_BURNING; age = 180; reason(meas); assertTrue(dir == burning); @@ -500,39 +515,39 @@ static bool testReasonDirBurnDown(void) { - resetRules(); - Measurement meas = {999, 0, 1999}; + resetRules(true); + Measurement meas = {999, 0, 1999, 0}; age = 0; reason(meas); assertTrue(dir == none); meas.tempI = 800; - meas.lambda = 1899; + meas.lambda = LAMBDA_BURNING - 1; age = 180; reason(meas); assertTrue(dir == burning); - meas.tempI = 700; - meas.lambda = 2000; + meas.tempI = TEMP_AIRGATE_25; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == burning); - meas.tempI = 699; - meas.lambda = 1899; + meas.tempI = TEMP_AIRGATE_25 - 1; + meas.lambda = LAMBDA_BURNING - 1; age = 180; reason(meas); assertTrue(dir == burning); - meas.tempI = 699; - meas.lambda = 2000; + meas.tempI = TEMP_AIRGATE_25 - 1; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == none); - meas.tempI = 100; - meas.lambda = 2000; + meas.tempI = TEMP_FIRE_OUT; + meas.lambda = LAMBDA_MAX; age = 180; reason(meas); assertTrue(dir == burning_down); @@ -542,40 +557,6 @@ return true; } -static bool testReasonDirWarmStart(void) { - - resetRules(); - Measurement meas = {999, 0, 1999}; - - age = 0; - reason(meas); - assertTrue(dir == none); - - meas.tempI = 699; - meas.lambda = 2000; - age = 180; - reason(meas); - assertTrue(dir == burning_down); - - meas.tempI = 100; - meas.lambda = 2000; - age = 180; - reason(meas); - assertTrue(dir == burning_down); - - meas.tempI = 120; - meas.lambda = 2000; - age = 180; - reason(meas); - assertTrue(dir == warm_start); - assertTrue(heaterStateUp == getHeaterState()); - assertTrue(airgate == 100); - - cancelAlert(false); - - return true; -} - /* Test "class" */ static const char class[] PROGMEM = "rules"; @@ -586,14 +567,15 @@ static const char testTooRich_P[] PROGMEM = "testTooRich"; static const char testTooLean_P[] PROGMEM = "testTooLean"; static const char testFireOut_P[] PROGMEM = "testFireOut"; +static const char testWarmStart_P[] PROGMEM = "testWarmStart"; static const char testHeaterReady_P[] PROGMEM = "testHeaterReady"; static const char testHeaterFaultNoconn_P[] PROGMEM = "testHeaterFaultNoconn"; static const char testHeaterFaultShort_P[] PROGMEM = "testHeaterFaultShort"; static const char testHeaterFaultNoheat_P[] PROGMEM = "testHeaterFaultNoheat"; -static const char testHeaterTimeout_P[] PROGMEM = "testHeaterTimeout"; +static const char testHeaterTimeout0_P[] PROGMEM = "testHeaterTimeout0"; +static const char testHeaterTimeout1_P[] PROGMEM = "testHeaterTimeout1"; static const char testReasonDirBurnUp_P[] PROGMEM = "testReasonDirBurnUp"; static const char testReasonDirBurnDown_P[] PROGMEM = "testReasonDirBurnDown"; -static const char testReasonDirWarmStart_P[] PROGMEM = "testReasonDirWarmStart"; /* Tests */ static TestCase const tests[] = { @@ -603,14 +585,15 @@ {class, testTooRich_P, testTooRich}, {class, testTooLean_P, testTooLean}, {class, testFireOut_P, testFireOut}, + {class, testWarmStart_P, testWarmStart}, {class, testHeaterReady_P, testHeaterReady}, {class, testHeaterFaultNoconn_P, testHeaterFaultNoconn}, {class, testHeaterFaultShort_P, testHeaterFaultShort}, {class, testHeaterFaultNoheat_P, testHeaterFaultNoheat}, - {class, testHeaterTimeout_P, testHeaterTimeout}, + {class, testHeaterTimeout0_P, testHeaterTimeout0}, + {class, testHeaterTimeout1_P, testHeaterTimeout1}, {class, testReasonDirBurnUp_P, testReasonDirBurnUp}, - {class, testReasonDirBurnDown_P, testReasonDirBurnDown}, - {class, testReasonDirWarmStart_P, testReasonDirWarmStart} + {class, testReasonDirBurnDown_P, testReasonDirBurnDown} }; TestClass rulesClass = {tests, sizeof(tests) / sizeof(tests[0])}; diff --git a/lambda/command.c b/lambda/command.c index 4df94b6..5392ec2 100644 --- a/lambda/command.c +++ b/lambda/command.c @@ -42,7 +42,7 @@ simulation = true; resetTime(); resetDisplay(); - resetRules(); + resetRules(true); setHeaterOn(true); beep(1, 1, 31); } @@ -50,7 +50,7 @@ // simulation disable resetTime(); resetDisplay(); - resetRules(); + resetRules(true); simulation = false; beep(1, 1, 31); } diff --git a/lambda/display.c b/lambda/display.c index f23e049..6d1ad5f 100644 --- a/lambda/display.c +++ b/lambda/display.c @@ -136,7 +136,6 @@ case firing_up: hint = " >"; break; case burning: hint = " ^"; break; case burning_down: hint = " <"; break; - case warm_start: hint = " +"; break; default: hint = " -"; break; } displayMeas(measLatest, hint); diff --git a/lambda/rules.c b/lambda/rules.c index 23bd95a..18291f0 100644 --- a/lambda/rules.c +++ b/lambda/rules.c @@ -13,6 +13,8 @@ #include "rules.h" #include "messages.h" +#include "usart.h" + uint8_t age = 0; FireDir dir = none; uint8_t airgate = 100; @@ -27,9 +29,9 @@ */ static void airgate50(bool* const fired, int8_t const dir, Measurement const meas) { - if (! *fired && (dir == firing_up || dir == burning || dir == warm_start) && + if ((dir == firing_up || dir == burning) && meas.tempI >= TEMP_AIRGATE_50 && meas.lambda >= LAMBDA_TOO_LEAN && - airgate > 50) { + airgate != 50) { airgate = 50; alert_P(BEEPS, LENGTH, TONE, PSTR(MSG_AIRGATE_50_0), PSTR(""), false); *fired = true; @@ -42,7 +44,7 @@ */ static void airgate25(bool* const fired, int8_t const dir, Measurement const meas) { - if (! *fired && dir == burning_down && meas.tempI < TEMP_AIRGATE_25 && + if (dir == burning_down && meas.tempI < TEMP_AIRGATE_25 && meas.lambda >= LAMBDA_TOO_LEAN && airgate > 25) { airgate = 25; alert_P(BEEPS, LENGTH, TONE, PSTR(MSG_AIRGATE_25_0), PSTR(""), false); @@ -56,8 +58,8 @@ */ static void airgateClose(bool* const fired, int8_t const dir, Measurement const meas) { - if (! *fired && dir == burning_down && meas.tempI < TEMP_AIRGATE_0 && - meas.lambda >= LAMBDA_TOO_LEAN && airgate > 0) { + if (dir == burning_down && meas.tempI < TEMP_AIRGATE_0 && + meas.lambda >= LAMBDA_MAX && airgate > 0) { setHeaterOn(false); airgate = 0; alert_P(BEEPS, LENGTH, TONE, @@ -71,7 +73,7 @@ */ static void tooRich(bool* const fired, int8_t const dir, Measurement const meas) { - if (! *fired && meas.tempI > TEMP_FIRE_OUT && + if (meas.tempI > TEMP_FIRE_OUT && meas.lambda < LAMBDA_TOO_RICH && getHeaterState() == heaterStateReady && airgate < 100) { airgate = 100; @@ -79,9 +81,6 @@ PSTR(MSG_TOO_RICH_0), PSTR(MSG_TOO_RICH_1), false); *fired = true; } - if (meas.lambda >= LAMBDA_TOO_RICH_RESET) { - *fired = false; - } } /** @@ -89,16 +88,13 @@ */ static void tooLean(bool* const fired, int8_t const dir, Measurement const meas) { - if (! *fired && meas.tempI > TEMP_AIRGATE_50 && + if (meas.tempI > TEMP_AIRGATE_50 && meas.lambda > LAMBDA_TOO_LEAN && getHeaterState() == heaterStateReady && airgate > 50) { airgate = 50; alert_P(BEEPS, LENGTH, TONE, PSTR(MSG_AIRGATE_50_0), PSTR(""), false); *fired = true; } - if (meas.lambda <= LAMBDA_TOO_LEAN_RESET) { - *fired = false; - } } /** @@ -117,6 +113,26 @@ } /** + * Resets rules and some state and switches on the heating if it seems that + * wood was added or the oven was fired up without resetting. + */ +static void warmStart(bool* const fired, int8_t const dir, + Measurement const meas) { + if (dir == firing_up && ! isHeaterOn() && + getHeaterState() != heaterStateFault) { + // it seems wood has been added or - probably more likely - oven + // was fired up without resetting. Should probably work that way + // anyway, making manual reset unnecessary? + // TODO make a complete reset including time? + resetRules(false); + airgate = 100; + rulesMeasMax.tempI = meas.tempI; + setHeaterOn(true); + *fired = true; + } +} + +/** * Notifies that the heater is ready and sets the corresponding state. */ static void heaterReady(bool* const fired, int8_t const dir, @@ -160,30 +176,25 @@ return; } uint32_t heaterUptime = getHeaterUptime(); - if (heaterUptime >= 1800 && meas.tempI < TEMP_FIRE_OUT) { + if (heaterUptime >= 1800 && meas.tempI < TEMP_FIRE_OUT && + meas.lambda >= LAMBDA_MAX) { setHeaterOn(false); alert_P(BEEPS, LENGTH, TONE, PSTR(MSG_FIRE_OUT_0), PSTR(""), false); } - if (heaterUptime >= 10800 && meas.tempI < TEMP_AIRGATE_0) { + if (heaterUptime >= 10800 && meas.tempI < TEMP_AIRGATE_0 && + meas.lambda >= LAMBDA_MAX) { setHeaterOn(false); - alert_P(3, 5, TONE, PSTR(MSG_HEATER_OFF_0), - PSTR(MSG_HEATER_OFF_1), false); + if (airgate > 0) { + alert_P(BEEPS, LENGTH, TONE, PSTR(MSG_AIRGATE_CLOSE_0), PSTR(""), + false); + } else { + alert_P(3, 5, TONE, PSTR(MSG_HEATER_OFF_0), PSTR(MSG_HEATER_OFF_1), + false); + } } } /** - * Rules applied to every nth averaged measurement. - */ -Rule rules[] = { - {false, airgate50}, - {false, airgate25}, - {false, airgateClose}, - {false, tooRich}, - {false, tooLean}, - {false, fireOut} -}; - -/** * Heater rules applied to each not averaged measured heater current value. */ Rule heaterRules[] = { @@ -192,6 +203,19 @@ {false, heaterTimeout} }; +/** + * Rules applied to every nth averaged measurement. + */ +Rule rules[] = { + {false, airgate50}, + {false, airgate25}, + {false, airgateClose}, + {false, tooRich}, + {false, tooLean}, + {false, fireOut}, + {false, warmStart} +}; + int8_t getDir(void) { return dir; } @@ -199,6 +223,12 @@ // called about every second void reason(Measurement const meas) { + // rules applied to each measurement + size_t heaterRulesSize = sizeof(heaterRules) / sizeof(heaterRules[0]); + for (size_t i = 0; i < heaterRulesSize; i++) { + heaterRules[i].cond(&(heaterRules[i].fired), dir, meas); + } + // rules applied to every 10th measurement if (age % 10 == 0) { size_t rulesSize = sizeof(rules) / sizeof(rules[0]); @@ -207,12 +237,6 @@ } } - // rules applied to each measurement - size_t heaterRulesSize = sizeof(heaterRules) / sizeof(heaterRules[0]); - for (size_t i = 0; i < heaterRulesSize; i++) { - heaterRules[i].cond(&(heaterRules[i].fired), dir, meas); - } - age++; // init previous measurements with current measurements @@ -226,34 +250,17 @@ if (age >= AGE_MEAS_PREV) { dir = none; if ((meas.tempI - rulesMeasPrev.tempI) >= TEMP_DELTA_UP && - rulesMeasMax.tempI < TEMP_MIN && meas.lambda >= LAMBDA_MAX) { + meas.tempI < TEMP_MIN && meas.lambda >= LAMBDA_BURNING) { dir = firing_up; } - if (meas.tempI >= TEMP_MIN || meas.lambda < LAMBDA_MAX) { + if (meas.tempI >= TEMP_MIN || meas.lambda < LAMBDA_BURNING) { dir = burning; } if ((rulesMeasPrev.tempI - meas.tempI) >= TEMP_DELTA_DOWN && - meas.tempI < TEMP_MIN && rulesMeasMax.tempI >= TEMP_MIN && - meas.lambda >= LAMBDA_MAX) { + meas.tempI < TEMP_MIN && meas.lambda >= LAMBDA_BURNING && + rulesMeasMax.tempI >= TEMP_AIRGATE_50) { dir = burning_down; } - if ((meas.tempI - rulesMeasPrev.tempI) >= TEMP_DELTA_UP && - meas.tempI < TEMP_MIN && rulesMeasMax.tempI >= TEMP_MIN) { - // it seems wood has been added or - probably more likely - oven - // was fired up without resetting. Should probably work that way - // anyway, making manual reset unnecessary? - // TODO make a complete reset including time? - dir = warm_start; - rulesMeasMax.tempI = meas.tempI; - size_t rulesSize = sizeof(rules) / sizeof(rules[0]); - for (size_t i = 0; i < rulesSize; i++) { - rules[i].fired = false; - } - if (! isHeaterOn() && getHeaterState() != heaterStateFault) { - setHeaterOn(true); - } - airgate = 100; - } rulesMeasPrev = meas; age = 0; @@ -262,13 +269,15 @@ rulesMeasMax.tempI = MAX(rulesMeasMax.tempI, meas.tempI); } -void resetRules(void) { - prevInit = false; - rulesMeasMax.tempI = 0; +void resetRules(bool const state) { + if (state) { + prevInit = false; + rulesMeasMax.tempI = 0; - age = 0; - dir = none; - airgate = 100; + age = 0; + dir = none; + airgate = 100; + } size_t rulesSize = sizeof(rules) / sizeof(rules[0]); for (size_t i = 0; i < rulesSize; i++) { diff --git a/lambda/rules.h b/lambda/rules.h index 50026fa..c0b78c4 100644 --- a/lambda/rules.h +++ b/lambda/rules.h @@ -36,22 +36,22 @@ #define TEMP_FIRE_OUT 100 /** Min. temperature at which to consider the fire to fire up again */ #define TEMP_FIRE_OUT_RESET 125 +/** Max. lambda value that can be measured */ +#define LAMBDA_MAX 2000 /** Fire is considered fully burning if lambda is below this value */ -#define LAMBDA_MAX 1900 +#define LAMBDA_BURNING 1900 /** Combustion is considered too rich if lambda is below this value */ #define LAMBDA_TOO_RICH 1200 -/** Combustion is considered lean enough again if lambda is above this value */ -#define LAMBDA_TOO_RICH_RESET 1400 -/** Combustion is considered too lean if lambda is above this value */ -#define LAMBDA_TOO_LEAN 1500 -/** Combustion is considered rich enough again if lambda is below this value */ -#define LAMBDA_TOO_LEAN_RESET 1400 +/** + * Combustion is considered too lean if lambda is above this value + * Too lean here rather means lean enough so the air gate can be set to 50% + */ +#define LAMBDA_TOO_LEAN 1400 typedef enum { none = 0, firing_up = 1, burning = 2, - warm_start = 3, burning_down = -1 } FireDir; @@ -77,6 +77,6 @@ /** * Resets all rules and internal state. */ -void resetRules(void); +void resetRules(bool state); #endif /* RULES_H_ */