Transférer les fichiers vers ''
Fichier pour la tête de dragon à Xano.
This commit is contained in:
parent
469d82e032
commit
b47fe06fc6
62
avrTinyThreads.h
Normal file
62
avrTinyThreads.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/* Projet: AVR tiny Threads */
|
||||||
|
/* File : avrTinyThreads.h */
|
||||||
|
/* Author: user@W500 greatly inpired by Adam Dunkels 08/28/20 */
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
#ifndef __avrTinyThreads_h__
|
||||||
|
#define __avrTinyThreads_h__
|
||||||
|
typedef struct AT {
|
||||||
|
unsigned short c;
|
||||||
|
} S_at ;
|
||||||
|
#define AT_ST_WAIT 0
|
||||||
|
#define AT_ST_QUIT 1
|
||||||
|
#define AT_ST_STOP 2
|
||||||
|
#define AT_SET(AT) (AT)->c = 0 ;
|
||||||
|
#define AT_BODY(params) char params // BODY
|
||||||
|
#define AT_START(AT) { \
|
||||||
|
char AT_YIELD_FLAG = 1; \
|
||||||
|
switch((AT)->c) { case 0: // START
|
||||||
|
#define AT_STOP(AT) } ; \
|
||||||
|
AT_YIELD_FLAG = 0; \
|
||||||
|
AT_SET(AT); \
|
||||||
|
return AT_ST_STOP; } // STOP
|
||||||
|
#define AT_QUIT(AT) \
|
||||||
|
do { \
|
||||||
|
AT_SET(AT); \
|
||||||
|
return AT_ST_QUIT; \
|
||||||
|
} while(0) // QUIT
|
||||||
|
#define AT_RESET(AT) \
|
||||||
|
do { \
|
||||||
|
AT_SET(AT); \
|
||||||
|
return AT_ST_WAIT; \
|
||||||
|
} while(0) // RESET
|
||||||
|
|
||||||
|
#define AT_WAIT_UNTIL(AT, exp) \
|
||||||
|
do { \
|
||||||
|
(AT)->c = __LINE__; \
|
||||||
|
case __LINE__: \
|
||||||
|
if(!(exp)) { \
|
||||||
|
return AT_ST_WAIT; \
|
||||||
|
} \
|
||||||
|
} while(0) // UNTIL
|
||||||
|
#define AT_WAIT_WHILE(AT, expr) \
|
||||||
|
AT_WAIT_UNTIL((AT), !(expr)) // WHILE
|
||||||
|
#define AT_RUN(fct) \
|
||||||
|
((fct) < AT_ST_QUIT) // RUN
|
||||||
|
#define AT_WAIT_THREAD(AT, thread) \
|
||||||
|
AT_WAIT_WHILE((AT), AT_RUN(thread)) // WAIT_THREAD
|
||||||
|
|
||||||
|
// checked for n calls in a thread : seems OK
|
||||||
|
#define AT_DELAY(AT, ms) \
|
||||||
|
do { \
|
||||||
|
static unsigned long _AT_ttl ; \
|
||||||
|
_AT_ttl = millis() + (unsigned int)(ms); \
|
||||||
|
AT_WAIT_UNTIL(AT, (millis() > _AT_ttl )); \
|
||||||
|
} while(0) // DELAY
|
||||||
|
// AT_WAIT_UNTIL(sat, millis() - started > cycleTime );
|
||||||
|
#define AT_SYN(AT, origin, ms) \
|
||||||
|
do { \ \
|
||||||
|
AT_WAIT_UNTIL(AT, (millis() - (origin) > (ms) )); \
|
||||||
|
} while(0) // DELAY
|
||||||
|
|
||||||
|
#endif // __avrTinyThreads_h__
|
205
firedrake.ino
Normal file
205
firedrake.ino
Normal file
@ -0,0 +1,205 @@
|
|||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/* 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
|
||||||
|
}
|
||||||
|
/*------------------------------------------------------------------*/
|
103
serialTrace.h
Normal file
103
serialTrace.h
Normal file
@ -0,0 +1,103 @@
|
|||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
/* Projet: Dev Tools */
|
||||||
|
/* File : serialTrace.h */
|
||||||
|
/* Author: user@W500 08/28/20 */
|
||||||
|
/*------------------------------------------------------------------*/
|
||||||
|
// RCS CI/CO : Cx v v, terminate log : CcCc, view log : Cx v l
|
||||||
|
// TODO: all this should be in a class or a singleton class
|
||||||
|
// TODO: strings should be in Flash 32kb code
|
||||||
|
// #include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
#ifndef __SERIALTRACE_H__
|
||||||
|
#define __SERIALTRACE_H__
|
||||||
|
extern char *__brkval;
|
||||||
|
unsigned long freeMemory() {
|
||||||
|
char top;
|
||||||
|
return &top - (__brkval ? __brkval : __malloc_heap_start);
|
||||||
|
}
|
||||||
|
|
||||||
|
void retard(unsigned long ms, int mini) {
|
||||||
|
#ifndef TEST
|
||||||
|
delay(ms);
|
||||||
|
#else
|
||||||
|
delay(mini);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
// functions used for I/O using serial monitor
|
||||||
|
#ifndef IHM // if IHM undefined then just empty functions.
|
||||||
|
// So users don't need to change code, just define/undefine IHM.
|
||||||
|
// A bit of a waste, but main purpose is testing.
|
||||||
|
bool ttyAskN ( String prompt ) {}
|
||||||
|
bool ttyAskY ( String prompt ) {}
|
||||||
|
char ttyGetChar ( String prompt ) {}
|
||||||
|
int ttyGetInt ( String prompt ) {}
|
||||||
|
void ttyPutInt ( String prompt, int num ) {}
|
||||||
|
void ttyPutMem ( ) {}
|
||||||
|
void ttyPutStr ( String txt ) {}
|
||||||
|
void ttyPutUin ( String prompt, unsigned int num ) {}
|
||||||
|
void ttyPutFloat ( String prompt, float num ) {}
|
||||||
|
void ttySetIHM ( long baud ) {}
|
||||||
|
void ttyWipe ( short lines ) {}
|
||||||
|
|
||||||
|
#else
|
||||||
|
void ttySetIHM(long baud) {
|
||||||
|
Serial.begin(baud); // WIP check if baud in correct values ?
|
||||||
|
for (int i=0;i<10;i++) Serial.print("\n\n\n") ;
|
||||||
|
}
|
||||||
|
void ttyPutStr(String txt) { Serial.println(txt);
|
||||||
|
}
|
||||||
|
void ttyPutMem() {
|
||||||
|
char buf[32];
|
||||||
|
unsigned long octets = freeMemory();
|
||||||
|
int k = octets / 1024 ; int o = octets % 1024;
|
||||||
|
sprintf(buf, "SRAM: %dKo%d free",k,o);
|
||||||
|
Serial.println (buf) ;
|
||||||
|
}
|
||||||
|
void ttyPutInt(String prompt, int num ) {
|
||||||
|
char buf[64];
|
||||||
|
sprintf(buf, "%s %d", prompt.c_str(), num ) ;
|
||||||
|
Serial.println (buf) ;
|
||||||
|
}
|
||||||
|
void ttyPutUin(String prompt, unsigned int num ) {
|
||||||
|
char buf[64];
|
||||||
|
sprintf(buf, "%s %d", prompt.c_str(), num ) ;
|
||||||
|
Serial.println(buf) ;
|
||||||
|
}
|
||||||
|
int ttyGetInt(String prompt) {
|
||||||
|
Serial.println(prompt);
|
||||||
|
while (Serial.available()==0) {} //Wait for user input
|
||||||
|
String val=Serial.readString();
|
||||||
|
return val.toInt();
|
||||||
|
}
|
||||||
|
void ttyPutFloat ( String prompt, float num ) {
|
||||||
|
Serial.print(prompt);
|
||||||
|
Serial.println (num) ;
|
||||||
|
}
|
||||||
|
void ttyPutFloatRound ( String prompt, float num ) {
|
||||||
|
char buf[64];
|
||||||
|
sprintf(buf, "%s %d", prompt.c_str(), int(num) ) ;
|
||||||
|
Serial.println (buf) ;
|
||||||
|
}
|
||||||
|
char ttyGetChar(String prompt) {
|
||||||
|
Serial.println(prompt);
|
||||||
|
while (Serial.available()==0) {} //Wait for user input
|
||||||
|
return Serial.read();
|
||||||
|
}
|
||||||
|
bool ttyAskY(String prompt){
|
||||||
|
byte R = 223 & (byte)ttyGetChar(prompt);
|
||||||
|
if ('Y' == R ) return true;
|
||||||
|
else return false ;
|
||||||
|
}
|
||||||
|
bool ttyAskN(String prompt){
|
||||||
|
byte R = 223 & (byte)ttyGetChar(prompt);
|
||||||
|
if ('N' == R ) return true;
|
||||||
|
return false ;
|
||||||
|
}
|
||||||
|
void ttyWipe (short lines) {
|
||||||
|
//const short ESC=27 ; KO in Arduino serial monitor, works with others tty
|
||||||
|
// Serial.write(ESC); Serial.print("[2J"); // cls
|
||||||
|
// Serial.write(ESC); Serial.print("[H"); // cursor to home
|
||||||
|
while (lines--) Serial.print("\n") ; // somehow overkill !
|
||||||
|
}
|
||||||
|
#endif // IHM
|
||||||
|
#endif // __SERIALTRACE_H__
|
138
therm100K.h
Normal file
138
therm100K.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/* Projet: Firedrake */
|
||||||
|
/* File : therm100K.h */
|
||||||
|
/* Author: user@W500 09/20/20 */
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
/*
|
||||||
|
BRIDGE PULL UP MOUNTING (Pulldown is opposite)
|
||||||
|
|
||||||
|
TH_VCC Analog In: TH_PIN TH_GND
|
||||||
|
| | |
|
||||||
|
x----/\/\/\/\/\/\/\/\/\/\/\/\/\-----x----/\/\/\/\/\/\/\/\/\/\/\/\/\--------x
|
||||||
|
Serie Resistor: TH_SERIE_R Thermistor: TH_R0, TH_T0, TH_BETA
|
||||||
|
*/
|
||||||
|
/*----------------------------------------------------------------------------*/
|
||||||
|
// Tested on Uno board.
|
||||||
|
// Using direct computing of simplyfied Seinhart-Hart takes 330µs.
|
||||||
|
// Using 30 values look up table is 3 time less time, 100µs & error less than 1°.
|
||||||
|
// For the time being we do the math for each call, choice should be fixed
|
||||||
|
// at setup and Th_Get_Degre() should take it in account.
|
||||||
|
// TODO: all this should be in a class in a library
|
||||||
|
|
||||||
|
#ifndef __THERM100K_H__
|
||||||
|
#define __THERM100K_H__
|
||||||
|
|
||||||
|
#define TH_VCC 2 // digital output for bridge supply
|
||||||
|
#define TH_GND 6 // digital output for bridge ground
|
||||||
|
#define TH_PIN 5 // adc pin to bridge middle pont
|
||||||
|
#define TH_ADCSTEPS 1023 // analog max value 2^(adc digits)-1
|
||||||
|
|
||||||
|
// WIP: we use standard values for this kind of thermistor,
|
||||||
|
// but this yield a température 4° too high
|
||||||
|
// #define TH_R0 119.4 // nominal resistance in KOhm at T0°C => 4° too much at 18°
|
||||||
|
#define TH_R0 103.9 // nominal resistance in KOhm at T0°C => -.2°/+.6° at 18,5°
|
||||||
|
#define TH_T0 27.2 // temp at nominal resistance (mostly 25°C)
|
||||||
|
#define TH_BETA 3.58 // thermistor beta coeff [3-4] Kelvin
|
||||||
|
#define TH_SERIE_R 4.7 // Serie resistor
|
||||||
|
#define TH_MOUNT_R PullUp // Serie mounting in "PullUp" or "PullDown"
|
||||||
|
#define TH_KILO 1000.0
|
||||||
|
|
||||||
|
enum T_SeriePull { PullUp, PullDown }; // discriminate serie resistor mounting
|
||||||
|
float Th_Compute_Therm_R(int raw, float rSerie, T_SeriePull rPull);
|
||||||
|
float Th_Compute_Simple_SH(float r_therm);
|
||||||
|
|
||||||
|
#define LUT_NB 30 // Look up table count, 30 values takes 10ms to build
|
||||||
|
struct {
|
||||||
|
int adc; float deg;
|
||||||
|
} Th_Lut[LUT_NB]; // Look up table
|
||||||
|
void Th_PrLookUp() {
|
||||||
|
#ifdef IHM
|
||||||
|
for (int i=0; i < LUT_NB; i++) { Serial.print("LUT adc "); Serial.print(Th_Lut[i].adc);
|
||||||
|
Serial.print(" => "); Serial.print(Th_Lut[i].deg); Serial.println("°C");}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
/* This takes 9880 µseconds for 30 values on an UNO board. */
|
||||||
|
void Th_MkLookUp(){ // builds a look up table adc <=> deg
|
||||||
|
float r_therm = 0; int adcVal = 1, astep = floor(float(TH_ADCSTEPS) /(LUT_NB-1));
|
||||||
|
for (int i=0; i < LUT_NB; i++) {
|
||||||
|
Th_Lut[i].adc = adcVal;
|
||||||
|
r_therm = Th_Compute_Therm_R(adcVal, TH_SERIE_R, TH_MOUNT_R);
|
||||||
|
Th_Lut[i].deg = Th_Compute_Simple_SH(r_therm) ;
|
||||||
|
adcVal += astep ;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float Th_LookUpFind(int raw){
|
||||||
|
float result=0, t ; int last = LUT_NB -1, idx_out=-1; // index for out array
|
||||||
|
if (raw <= Th_Lut[0].adc) idx_out = 0;
|
||||||
|
else if (raw >= Th_Lut[last].adc) idx_out = last;
|
||||||
|
|
||||||
|
if (idx_out >= 0) {
|
||||||
|
result = float(Th_Lut[idx_out].deg) ; // out of bounds: first or last
|
||||||
|
#ifdef IHM
|
||||||
|
Serial.print("LUT: out of bounds at = "); Serial.println(idx_out);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
int pos = 1; // [0] allready tested
|
||||||
|
while(raw > Th_Lut[pos].adc) pos++; // looking for upper bound
|
||||||
|
if (raw == Th_Lut[pos].adc) result = float(Th_Lut[pos].deg); // exact match
|
||||||
|
else { // interpolate between pos-1 & pos
|
||||||
|
float part = 0;
|
||||||
|
part = float(raw - Th_Lut[pos-1].adc);
|
||||||
|
part /= float(Th_Lut[pos].adc - Th_Lut[pos-1].adc);
|
||||||
|
result = Th_Lut[pos-1].deg + part * (Th_Lut[pos].deg - Th_Lut[pos-1].deg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
void Th_Setup() {
|
||||||
|
pinMode(TH_VCC, OUTPUT);
|
||||||
|
pinMode(TH_GND, OUTPUT);
|
||||||
|
digitalWrite(TH_VCC, LOW);
|
||||||
|
digitalWrite(TH_GND, LOW);
|
||||||
|
analogReference(DEFAULT);
|
||||||
|
}
|
||||||
|
int Th_ReadRaw() {
|
||||||
|
int raw = 0;
|
||||||
|
digitalWrite(TH_VCC, HIGH);
|
||||||
|
delay(500); // WIP: give some time to reach 5V ?
|
||||||
|
raw = analogRead(TH_PIN);
|
||||||
|
digitalWrite(TH_VCC, LOW);
|
||||||
|
return raw;
|
||||||
|
}
|
||||||
|
/* This takes 80 µseconds on an UNO board. */
|
||||||
|
float Th_Compute_Therm_R(int raw, float rSerie, T_SeriePull rPull) {
|
||||||
|
float val = 0 ;
|
||||||
|
switch (rPull) {
|
||||||
|
case(PullUp): val = rSerie * TH_KILO / ((float(TH_ADCSTEPS) / raw) - 1);
|
||||||
|
break;
|
||||||
|
case(PullDown): val = rSerie * TH_KILO * ((float(TH_ADCSTEPS) / raw) - 1);
|
||||||
|
break;
|
||||||
|
#ifdef IHM
|
||||||
|
default: Serial.println(); Serial.println( "BUG in Th_Compute_Therm_R" );
|
||||||
|
Serial.println();
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return val;
|
||||||
|
}
|
||||||
|
/* This is computed using the simplified Steinhart-Hart formula
|
||||||
|
and takes 250 to 270 µseconds on an UNO board.
|
||||||
|
If more speed is needed, you may load a look up table and
|
||||||
|
interpolate the ADC reading.
|
||||||
|
*/
|
||||||
|
float Th_Compute_Simple_SH(float r_therm) {
|
||||||
|
float s_h = 0;
|
||||||
|
s_h = r_therm / (TH_R0 * TH_KILO); // R/R0
|
||||||
|
s_h = log(s_h); // ln(R/R0 )
|
||||||
|
s_h /= TH_BETA * 1000.0; // 1/B * ln(R/R0 )
|
||||||
|
s_h += 1.0 / (25.0 + 273.15 ); // + 1/T0 in Kelvin
|
||||||
|
s_h = 1.0 / s_h ; // invert
|
||||||
|
s_h = s_h - 273.15; // in Celsius
|
||||||
|
return s_h;
|
||||||
|
}
|
||||||
|
float Th_Get_Degre () {
|
||||||
|
int raw = Th_ReadRaw();
|
||||||
|
float r_therm = Th_Compute_Therm_R(raw, TH_SERIE_R, TH_MOUNT_R);
|
||||||
|
return Th_Compute_Simple_SH(r_therm);
|
||||||
|
}
|
||||||
|
#endif // __THERM100K_H__
|
Loading…
Reference in New Issue
Block a user