Dragonhead/firedrake.ino

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
}
/*------------------------------------------------------------------*/