Files
InsoLab/minuteur/minuteur.ino
jearz a7dd5da698 Finalisation gestion d'icones dans l'écran de veille.
Correction fonctions de gestion des icones.
Ajout et modification des bitmaps d'icones.
Ajout fonction de changement d'icone en cours de déroulement.
2026-05-22 18:19:07 +02:00

378 lines
12 KiB
C++

/*-----------------------------------------------------------------------
Project: InsoL@b
Author : user@B0 mail@nowhere.void
File : minuteur.ino 2026-04-19
This work is copyrighted under the CERN Open Hardware Licence Version 2.
-------------------------------------------------------------------------
Serial port not available ? sudo fuser -k /dev/ttyACM0 & RST or Boot
-------------------------------------------------------------------------
* Power on: Greeting screen LOGO waits for timout and go to screen TITRE
- Show InsoL@b logo
* screen TITRE
- Show title & wait for any button to continue to Screen CHOIX
* Screen CHOIX
- displays default/curent exposure time
- minus button go to screen EXPO exposure timing sequence
- plus button go to setting screen REGLE
* Screen EXPO
- UV exposure
- display count down, minus button to stop, plus to increment time
- when done exit back to screen CHOIX
* Screen REGLE
- minus button go to screen INCRE
- plus button go to screen DUREE
- return to caller on time out
* Screen DURE
- minus decrement exposure time
- plus increment exposure time
- return to caller on time out
* Screen INCRE
- minus decrement step value
- plus increment step value
- return to caller on time out
* Sleep mode not stable, forum at :
"https://github.com/earlephilhower/arduino-pico/issues/345"
-----------------------------------------------------------------------
Mod: 2026/05/27 added 2 bitmap to sreen saver
-----------------------------------------------------------------------*/
#define BUTTONPLUS 14 // PullUp 10K I=.33 mA
#define BUTTONMINUS 15 // PullUp 10K I=.33 mA
#define RELAY 27 // Must be < 4mA
#define PIEZO 8 // Used by anyrtttl.h in bitmaps.h
/* I2C SDA & CLK PullUp 2*10K I=.66 mA
Sur le RP2040 le défaut du courant de sortie est limité à 4mA/broche IO,
C'est configurable par logiciel pour atteindre 2mA, 8mA ou 12mA.
Le courant maximal combiné que toutes les broches GPIO peuvent sourcer ou
absorber est limité à 50 mA. Au total le courant total doit être < à 50mA.
*/
//#define SENSOR_HALL
#define S_HALL 7 // Sense Hall sensor
//#define ESSAIS
enum screen_t {sLOGO,sTITRE,sCHOIX,sEXPOS,sREGLE,sDUREE,sINCRE,sSAUVE,sVEILLE,sNONE};
#ifdef ESSAIS
int16_t defaultTime=80, stepTime=5, timeOut=3; // expo & setting time
int16_t snoozeTimeOut=6;
#else
int16_t defaultTime=180, stepTime=10, timeOut=4;
int16_t snoozeTimeOut=60; //60
#endif
int16_t greetTime=2000;
// display limit to 999s => 16mn 39s
volatile uint16_t setTime=defaultTime;
volatile uint16_t downTime; // count down time
volatile uint16_t lastSetTime, lastStepTime, time2save=0;
volatile boolean plusPushed=false; volatile boolean minusPushed=false;
char sMsg[16];
screen_t screen=sNONE;
#include <EEPROM.h>
#include "displays.h" // Oled functions & led RGB
#include "pt.h" // proto threads
//#include "scroll.h" // circular buffer for displays
#define h42 0x2A
#define h43 0x2B
#define add42 254
#define add43 255
/*----------------- CPU 0 ---------------------------------*/
void die() {ledRGB(RED); for(;;); }
bool isRamSet() {
byte val1,val2;
EEPROM.begin(256);
//clearRAM();
val1 = EEPROM.read(add42);
val2 = EEPROM.read(add43);
if (val1==h42 && val2==h43) return true; // allready writed
EEPROM.write(add42, h42); // 42
EEPROM.write(add43, h43); // 43
EEPROM.put(0, setTime);
EEPROM.put(4, stepTime);
EEPROM.commit(); // WIP? if (EEPROM.commit()) { do something ? }
return false;
}
void SetTime2RAM() {
EEPROM.put(0, setTime); EEPROM.commit();
}
void StepTime2RAM() {
EEPROM.put(4, stepTime); EEPROM.commit();
}
void clearRAM() {
for(int addr = 0; addr < 256; addr++) {
EEPROM.write(addr, 0);
}
EEPROM.commit();
}
void setup() {
showInit();
sprintf(sMsg,"Value");
// read memory
if (isRamSet()) { // setting values to be found in memory
EEPROM.get(0, setTime);
EEPROM.get(4, stepTime);
#ifdef ESSAIS
char l1[16], l2[16], l3[16];
sprintf(l1,"RAM time values");
sprintf(l2,"set: %3ds",setTime);
sprintf(l3,"step: %3ds",stepTime);
showInfo(l1, l2, l3);
delay(5000);
#endif
}
// EEPROM.end();
lastSetTime=setTime;
lastStepTime=stepTime;
showLOGO(greetTime);
minusPushed=false; plusPushed=false; // in case button pushed while LOGO
screen=sTITRE;
}
void loop() { // CPU 0 dedicated to refresh display
// TODO not recall screen if values did not change
switch(screen) {
case sTITRE : showTITRE(); break;
case sCHOIX : showCHOIX(setTime); break;
case sEXPOS : showEXPOS(downTime,stepTime); break;
case sREGLE : showREGLE(); break;
case sDUREE : showDUREE(setTime); break;
case sINCRE : showINCRE(stepTime); break;
case sSAUVE : showSAUVE(time2save,sMsg); break;
case sVEILLE : delay(100); break; // snooze screen
case sNONE : delay(100); break; // nothing to change yet, waiting for next screen
default : ledRGB(RED); delay(6000); break;// Code error
}
delay(100);
}
/*----------------- CPU 1 ---------------------------------*/
// ProtoThreads local continuation structure
static pt_t pMINUS,pPLUS,pALARM,pTITRE,pCHOIX,pEXPOS,
pREGLE,pDUREE,pINCRE,pSAUVE,pVEILLE;
void setup1() { // CPU 1 to manage buttons
// ProtoThreads continuation structure is set to 0
PT_INIT(&pMINUS); PT_INIT(&pPLUS); PT_INIT(&pALARM);
PT_INIT(&pTITRE); PT_INIT(&pCHOIX); PT_INIT(&pEXPOS);
PT_INIT(&pREGLE); PT_INIT(&pINCRE); PT_INIT(&pDUREE);
PT_INIT(&pSAUVE); PT_INIT(&pVEILLE);
// IO
pinMode(BUTTONMINUS, INPUT_PULLUP); pinMode(BUTTONPLUS, INPUT_PULLUP);
pinMode(RELAY, OUTPUT); digitalWrite(RELAY, LOW);delay(500);
#ifdef SENSOR_HALL
pinMode (S_HALL, INPUT_PULLUP); // Enable pull-up as sensor output is open collector
#endif
}
static PT_THREAD(pPlus(pt_t *lc)) { // OK and avoid bounces
PT_BEGIN(lc); // lc=local continuation byte, here set to previous call value
while (1) {
PT_WAIT_UNTIL(lc, digitalRead(BUTTONPLUS) == LOW); // lc set to __LINE__
plusPushed=true;
}
PT_END(lc); // to try: exit & return flag ?
}
static PT_THREAD(pMinus(pt_t *lc)) {
PT_BEGIN(lc);
while (1) {
PT_WAIT_UNTIL(lc, digitalRead(BUTTONMINUS) == LOW);
minusPushed=true;
}
PT_END(lc);
}
static PT_THREAD(pAlarm(pt_t *lc)) { //WIP
PT_BEGIN(lc);
// PT_WAIT_UNTIL(lc, (screen==sEXPOS) );
if (digitalRead(S_HALL))
ledRGB(RED);
else
ledRGB(GREEN);
PT_DELAY(lc, 400); // reading hall sensor
// PT_WAIT_UNTIL(lc, digitalRead(S_HALL));// Pullup pin: switch <=> magnet
// digitalWrite(RELAY, LOW ); }
PT_END(lc);
}
static PT_THREAD(pTitre(pt_t *lc)) {
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sTITRE));
ledRGB(GREEN);
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed ));
minusPushed=false; plusPushed=false;
screen=sCHOIX;
PT_DELAY(lc, 100);
PT_END(lc);
}
static PT_THREAD(pChoix(pt_t *lc)) { // TODO sleep & wake up
static unsigned long ttl,to= snoozeTimeOut * 1000;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sCHOIX));
ledRGB(ORANGE);
minusPushed=false; plusPushed=false;
ttl=millis()+to;
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl) ) );
if (minusPushed) { minusPushed=false; screen=sEXPOS; }
if (plusPushed) { plusPushed=false; screen=sREGLE; }
if (millis() > ttl) screen=sVEILLE; //screen=sTITRE; //
PT_DELAY(lc, 100);
PT_END(lc);
}
static PT_THREAD(pExpos(pt_t *lc)) { // run count down UV light OK
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sEXPOS) );
ledRGB(PINK);
downTime = setTime;
playRTTTL(sCHOIX);
digitalWrite(RELAY, HIGH);
minusPushed=false; plusPushed=false;
do { // count down loop
if (plusPushed) {
plusPushed=false;
if (downTime < 1000 - stepTime) downTime += stepTime;
}
PT_DELAY(lc, 600);
downTime -=1;
if (minusPushed) { minusPushed=false; downTime = 0; }
PT_DELAY(lc, 310);
playClk(); // this take ~100ms
} while ( downTime > 0);
digitalWrite(RELAY, LOW );
screen=sCHOIX;
ledRGB(ORANGE);
playRTTTL(sEXPOS);
PT_END(lc);
}
static PT_THREAD(pRegle(pt_t *lc)) { // OK
static unsigned long ttl,to=500 + timeOut * 1000;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sREGLE) );
ledRGB(YELLOW);
minusPushed=false; plusPushed=false;
ttl=millis()+to;
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl) ) );
if (plusPushed) { plusPushed=false; screen=sDUREE; }
else if (minusPushed) { minusPushed=false; screen=sINCRE; }
if (millis() > ttl) screen=sCHOIX;
PT_DELAY(lc, 100);
PT_END(lc);
}
static PT_THREAD(pIncre(pt_t *lc)) { // OK
static unsigned long ttl, to=timeOut * 1000;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sINCRE) );
ledRGB(BLUE);
lastStepTime = stepTime;
PT_DELAY(lc, 1000);
ttl=millis()+to;
minusPushed=false; plusPushed=false;
do {
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl)) );
if (plusPushed) {
plusPushed=false;
if (stepTime < 999) stepTime += 1 ;
ttl=millis()+to;
} else
if (minusPushed) {
minusPushed=false;
if (stepTime >1) stepTime-= 1 ;
ttl=millis()+to;
}
if (millis() > ttl) screen=sNONE;
} while (screen==sINCRE);
if (lastStepTime == stepTime) screen=sREGLE;
else { sprintf(sMsg,"Step:"); screen=sSAUVE; }
PT_END(lc);
}
static PT_THREAD(pDuree(pt_t *lc)) { // OK
static unsigned long ttl, to=timeOut * 1000;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sDUREE) );
ledRGB(FUCHS);
lastSetTime = setTime;
PT_DELAY(lc, 1000);
ttl=millis()+to;
do {
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl)) );
if (plusPushed) {
plusPushed=false;
if (setTime < 1000 - stepTime) setTime += stepTime ;
ttl=millis()+to;
}
if (minusPushed) {
minusPushed=false;
if (setTime > stepTime) setTime -= stepTime ;
ttl=millis()+to;
}
if (millis() > ttl) screen=sNONE;
} while (screen==sDUREE);
if (lastSetTime == setTime) screen=sREGLE;
else { sprintf(sMsg,"Time:"); screen=sSAUVE; }
PT_END(lc);
}
static PT_THREAD(pSauve(pt_t *lc)) { //
static unsigned long ttl, to;
to = (timeOut+4) * 1000;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sSAUVE) );
if (lastSetTime != setTime) time2save=setTime; // value for screen sSAUVE
else if (lastStepTime != stepTime) time2save=stepTime;
ledRGB(ROSE);
PT_DELAY(lc, 1000);
ttl=millis()+to;
do {
PT_WAIT_UNTIL(lc, (plusPushed || minusPushed || (millis() > ttl)) );
if (plusPushed) {
if (lastSetTime != setTime) SetTime2RAM();
if (lastStepTime != stepTime) StepTime2RAM();
sprintf(sMsg,"done");
PT_DELAY(lc, 2000);
screen=sREGLE;
}
if (millis() > ttl || minusPushed) screen=sREGLE;
} while (screen==sSAUVE );
time2save=0;
PT_END(lc);
}
static PT_THREAD(pVeille(pt_t *lc)) { // OK and avoid bounces
const int nbSprites = 10;
static t_iconMvt icons[nbSprites];
static t_sprite sprite;
static uint16_t nbpass=0;
PT_BEGIN(lc);
PT_WAIT_UNTIL(lc, (screen==sVEILLE));
ledRGB(NONE);
initSprite(&sprite,nbSprites,16,16, flake_bmp, icons); // load values to sprite
do {
drawSprite(&sprite);
PT_DELAY(lc, 40);
if (!(plusPushed || minusPushed)) {
oled.display();
PT_DELAY(lc, 40);
updateSprite(&sprite); // update coordinates of each sprite
}
nbpass = changeSprite(&sprite, nbpass);
} while (!(plusPushed || minusPushed ));
minusPushed=false; plusPushed=false;
oled.clearDisplay();
PT_DELAY(lc, 200);
screen=sTITRE; // sCHOIX;//
PT_END(lc); // to try: exit & return flag ?
}
void loop1() { // CPU 1 dedicated to run threads
pMinus (&pMINUS); // process minus button
pPlus (&pPLUS); // process plus button
// pAlarm (&pALARM); // WIP
pTitre (&pTITRE); // process screen TITRE
pChoix (&pCHOIX); // process screen CHOIX
pExpos (&pEXPOS); // process screen EXPOS
pRegle (&pREGLE); // process screen REGLE
pIncre (&pINCRE); // process screen INCRE
pDuree (&pDUREE); // process screen DUREE
pSauve (&pSAUVE); // process screen SAUVE
pVeille(&pVEILLE); // process screen saver
}
/*
* code debug
Serial.begin(115200); delay(500); Serial.printf("CPU 0 on\n");
Serial.printf("CPU 1 on\n");
*/