206 lines
7.7 KiB
C++
206 lines
7.7 KiB
C++
/*------------------------------------------------------------------*/
|
|
/* 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
|
|
}
|
|
/*------------------------------------------------------------------*/
|