/*------------------------------------------------------------------*/ /* Projet: Firedrake 2020-09-03 */ /* File : firedrake.c */ /* Author: user@W500 */ /*------------------------------------------------------------------*/ // MODIFIED 10/28/21 user@khp: 2 pump & independant eyes // Computed température in therm100K.h is 4° too hight #include "avrTinyThreads.h" // pseudo threads for avr //#define TEST // if uncommented then test #define IHM // uncommented = log on serial monitor #ifdef TEST #define MAXHEAT 7 // WIP TEST in seconds => ~ 4 cycles ??? #define MAXTEMP 80.0 // WIP TEST in degree #else #define MAXHEAT 240 // seconds => 4mn => 120 cycles of 2s #define MAXTEMP 150.0 // degree #endif #define MIMTEMP -270.0 // thermistor not present or broken #define R_PUMP 13 // pump (BC337) yellow led, must move to pin 8 #define HEATER 12 // heater relay, blue test led #define R_EYE 11 // ~ Eye red led #define L_EYE 10 // ~ Eye red led #define GAUGE 9 // ~ Gauge green led #define KNOCK 8 // button (must move to another pin) #include "serialTrace.h" // infos / trace to serial monitor #include "therm100K.h" // Function for ntc thermistor 100K // threads; Knock Eye Heat Pump Gauge Alert Vigil static S_at atK, atE, atH, atP, atG, atA, atV ; uint16_t th=2000, tp=3000, toff=2000 ; // heatTime=0, eyes open, stay, close, wait knock uint32_t started=0, cycleTime = ( 255 * 6 ) + 3000 + ( 255 * 12 ) + toff; bool unSafe = false, tooHot =false, failedTherm=false, notEmpty=true, cycle=false; void initIO() { pinMode(KNOCK, INPUT_PULLUP); pinMode(R_EYE, OUTPUT); pinMode(L_EYE, OUTPUT); analogWrite(R_EYE, 0); analogWrite(L_EYE, 0); // Eyes unlighted pinMode(HEATER, OUTPUT); pinMode(R_PUMP, OUTPUT); digitalWrite(HEATER, LOW); digitalWrite(R_PUMP, LOW) ; pinMode(GAUGE, OUTPUT); analogWrite(GAUGE, 254); // gauge at max Th_Setup() ; // thermistor I/O setup } void setup() { ttySetIHM(9600); ttyPutMem(); // IHM & show free mem initIO(); // Setup: set LEDs & button AT_SET(&atK); AT_SET(&atE); AT_SET(&atH); AT_SET(&atP); AT_SET(&atA); AT_SET(&atG); AT_SET(&atV); ttyPutUin("CycleTime = ", cycleTime); int raw = Th_ReadRaw(); ttyPutInt("Raw temperature = ",raw); float r_therm = Th_Compute_Therm_R(raw, TH_SERIE_R, PullUp); ttyPutFloat("Thermistor bridge Ohm = ", r_therm); float deg = Th_Compute_Simple_SH(r_therm); // uses Steinhart-Hart formula ttyPutFloat("Th_Compute_Simple_SH = ", deg); deg = Th_Get_Degre() ; ttyPutFloat("Th_Get_Degre = ",deg); } /*------------------------------------------------------------------*/ void ledPWM(uint8_t led, uint8_t ratio) { int val=constrain(ratio,0,254); // limit to values [0..254] analogWrite(led, val); } bool getButton() { // haste hack to deflect bounces int nb=0; for (int i=0;i<10;i++) { delay(10); // TODO ? : move in a thread ? nb+= digitalRead(KNOCK); // Pullup pin: HIGH <=> button off } // & LOW <=> button on return (nb<5) ; } /*------------------------------------------------------------------*/ // Thread to brighten or darken eyes gradatory // Use PWM from start to aim lasting a period, inc is >0 for up & <0 for down static AT_BODY(atEye(S_at *sat, int start, int aim, int inc, int period)) { static int i=0 ; AT_START(sat); ledPWM(R_EYE, start) ; ledPWM(L_EYE, start) ; do { AT_DELAY(sat, period); i=i+inc; ledPWM(R_EYE, i) ; ledPWM(L_EYE, i) ; } while (i != aim ); AT_STOP(sat); } /*------------------------------------------------------------------*/ // Thread checking knocks static AT_BODY(atKnock(S_at *sat)) { AT_START(sat); while (1) { AT_WAIT_UNTIL(sat, getButton() ); cycle=true; started=millis(); AT_WAIT_THREAD(sat, atEye(&atE,0,254,1,6)); // Opening AT_DELAY(sat, tp); AT_WAIT_THREAD(sat, atEye(&atE,254,0,-1,12)); // Closing cycle=false; AT_WAIT_UNTIL(sat, millis() - started > cycleTime ); // end time } AT_STOP(sat); } /*------------------------------------------------------------------*/ uint16_t addElapsed(uint16_t period) { static uint32_t heatTime; heatTime += period; return (uint16_t) ( heatTime / 1000 ) ; } // Thread actuating heating static AT_BODY(atHeater(S_at *sat, uint16_t offset, uint16_t period )) { static uint32_t former = 0; int burnt = 0; AT_START(sat); while( notEmpty && cycle ) { // cycle started if not empty AT_DELAY(sat, period); // offset time ttyPutStr("heat on"); former = millis(); digitalWrite(HEATER, HIGH); AT_WAIT_UNTIL(sat, (millis() - former > period ) || unSafe ); // heating time digitalWrite(HEATER, LOW); burnt = addElapsed(period) ; ttyPutUin("Burning time: ", burnt); notEmpty = (burnt <= MAXHEAT); // check if enough for next cycle AT_WAIT_UNTIL(sat, millis() - started > cycleTime ); // end cycle time } AT_STOP(sat); } // Thread actuating pumping static AT_BODY(atPump(S_at *sat, uint16_t offset, uint16_t period )) { AT_START(sat); while( notEmpty && cycle ) { AT_DELAY(sat, offset); //ttyPutStr("pump on"); digitalWrite(R_PUMP, HIGH); AT_DELAY(sat, period); digitalWrite(R_PUMP, LOW); // ttyPutStr("pump off"); AT_WAIT_UNTIL(sat, (millis() - started > cycleTime) || unSafe ); // end time } AT_STOP(sat); } /*------------------------------------------------------------------*/ // Thread to flash green led when action needed static AT_BODY(atAlert(S_at *sat, int blink_temp, int blink_fail, int blink_empty)) { AT_START(sat); while ( ! notEmpty || unSafe ) { if ( tooHot ) AT_DELAY(sat, blink_temp); else if ( failedTherm ) AT_DELAY(sat, blink_fail); else AT_DELAY(sat, blink_empty); digitalWrite(GAUGE, !digitalRead(GAUGE)); } AT_STOP(sat); } // Thread liquid monitoring static AT_BODY(atGauge(S_at *sat)) { static uint16_t elapsed = 0, ratio = 0; AT_START(sat); while ( notEmpty && cycle ) { ratio = map(addElapsed(0), 0, MAXHEAT, 254, 0); ledPWM(GAUGE, ratio); AT_WAIT_UNTIL(sat, millis() - started > cycleTime ); // end time } AT_STOP(sat); } // Thread temperature security static AT_BODY(atVigil( S_at *sat, int watch )) { static float deg=0; static int ioMonitor = 0; AT_START(sat); deg = Th_Get_Degre(); // do the Steinhart-Hart formula for each call while (deg < MAXTEMP && deg > MIMTEMP) { AT_DELAY(sat, watch); ioMonitor++; if (ioMonitor > 40) { // wait 40 * watch ms to print Temperature deg = Th_Get_Degre() ; ttyPutFloat("Temperature = ",deg); ioMonitor = 0; // delay(1000); //TEST } } ttyPutFloat("RISKY Temperature = ",deg); // Prevent heating as temperature is out of safe range, & set alert unSafe = true ; // impeach heater & pump if (deg < MIMTEMP ) failedTherm = true ; // for gauge blinking if (deg > MAXTEMP ) tooHot = true ; // for gauge blinking fast AT_STOP(sat); } /*------------------------------------------------------------------*/ void loop() { atVigil(&atV,200); // heat watch of 200ms atKnock(&atK); // check for knock atHeater(&atH,1500,th); // offset & duration for heater atPump(&atP,1500,tp); // offset & duration for pump atAlert(&atA,50,200,400); // set alerts to Gauge Led atGauge(&atG); // monitor heat time } /*------------------------------------------------------------------*/