diff --git a/ConfigAutomatismes.h b/ConfigAutomatismes.h new file mode 100644 index 0000000..539099a --- /dev/null +++ b/ConfigAutomatismes.h @@ -0,0 +1,120 @@ +// Lumieres::ConfigAutomatismes.h +// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL +// +// Ce fichier concerne la configuration d'automatismes de base selon la +// cartographie suivante (et en cela, on a une sorte de M83 plus puissant !): +// +// 00 : seq1: chenillard (séquences de tests), seq2: anti-rebond (seq1: ExB -> Sx+1 , seq2: ExH -> Sx+1) +// 01 : seq1: paparazzi (E1B -> S2 flash), seq2: néons ateliers + soudure (ExB -> Sx+1) +// 10 : signal SNCB (TBD) +// 11 : automatisme utilisateur (programmé dans ConfigLumieres.h) (mode par défaut) +// ================================================================ + +// === Prog00x === +// seq1: chenillard (séquences de tests) +// seq2: filtre anti-rebond (ExB -> Sx , seq2: ExH -> Sx+4) + +/* PROG 0 */ +DEBUTSEQ(Prog000) + MARK /* Point de retour */ + 1, 1, _SET, + 2, 1, _SET, + 4, 1, _SET, + 8, 1, _SET, + 16, 1, _SET, + 32, 1, _SET, + 64, 1, _SET, + 128, 1, _SET, + 0, 1, _WAIT, /* Eteint tout et Attend pendant 1 secondes */ + 255, 2, _SET, /* Allume tout pendant 2 secondes */ + ESTARTH,0,_WSTOP, /* Vérifie que la startPin est toujours à 1 */ + LOOP /* Retoune au point de retour */ +FINSEQ(Seq1_Prog000) + +/* PROG 1 */ +DEBUTSEQ(Prog001) + 1, E1B, _ATTACH, + 2, E2B, _ATTACH, + 4, E3B, _ATTACH, + 8, E4B, _ATTACH, + 16, E1H, _ATTACH, + 32, E2H, _ATTACH, + 64, E3H, _ATTACH, + 128, E4H, _ATTACH, + END /* fin de la séquence */ +FINSEQ(Prog001) + +// === Prog01x === +// seq1: néons neufs (S1,S3), paparazzi (E1B -> S2 flash), gyrophare (E2B -> S4 gyrophare), brasero (E3B -> S5), néon vieux (E4B -> S6, S8), soudure (S7) +// seq2: néons neufs (S1,S3), paparazzi (E1B -> S2 flash), gyrophare (E2B -> S4 gyrophare), brasero (S5), néon vieux(E4H -> S6, S8), soudure (E3B -> S7) + +/* PROG 2 */ +DEBUTSEQ(Prog010) + SETMODE(S1+S3,ETYPE_NEONNEUF) + SETMODE(S2,ETYPE_FLASH) + SETMODE(S4,ETYPE_GYROPHARE) + SETMODE(S5,ETYPE_FIRE) + SETMODE(S6+S8,ETYPE_NEONVIEUX) + SETMODE(S7,ETYPE_SOUDURE) + PERM(S1) + PERM(S3) + ATTACH(S4,E2B) + ATTACH(S5,E3B) + ATTACH(S6,E4B) + PERM(S8) + PERM(S7) + MARK /* Point de retour */ + WSTOP(E1B,1) /* Attend que l'entrée E1 passe à 0, échantillonage à la seconde */ + ALEA(S2,4) /* lance le flash configuré sur la sortie S2 aléatoirement (0..3) */ + LOOP /* Retoune au point de retour */ +FINSEQ(Prog010) + +/* PROG 3 */ +DEBUTSEQ(Prog011) + SETMODE(S1+S3,ETYPE_NEONNEUF) + SETMODE(S2,ETYPE_FLASH) + SETMODE(S4,ETYPE_GYROPHARE) + SETMODE(S5,ETYPE_FIRE) + SETMODE(S6+S8,ETYPE_NEONVIEUX) + SETMODE(S7,ETYPE_SOUDURE) + PERM(S1) + PERM(S3) + ATTACH(S4,E2B) + PERM(S5) + ATTACH(S6,E4H) + PERM(S8) + ATTACH(S7,E3B) + MARK /* Point de retour */ + WSTOP(E1B,2) /* Attend que l'entrée E1 passe à 0 pendant 2 secondes */ + ALEA(S2,4) /* lance le flash configuré sur la sortie S2 aléatoirement (0..3) */ + LOOP /* Retoune au point de retour */ +FINSEQ(Prog011) + +// === Prog10x === +// seq1: signal SNCB (TBD) + +// seq2: Passage à niveau (E1/E2 -> servo S6/S7 + clignotement S8) + +/* PROG 4 */ +DEBUTSEQ(Prog100) + MARK /* Point de retour */ + LOOP /* Retoune au point de retour */ +FINSEQ(Prog100) + +/* PROG 5 */ +DEBUTSEQ(Prog101) + SETMODE(S6,ETYPE_SERVO) /* S6 (32) ou SM1 : servo moteur de la barrière (PWM) */ + SETMODE(S7,ETYPE_SERVO) /* S7 (64) ou SM2 : servo moteur de la barrière (PWM) */ + SETMODE(S8,ETYPE_CLIGNOTANT) /* S8 (128) : feu clignotant (PWM) */ + MARK /* Point de retour */ + WSTOP(E1B,1) /* attend que E1 passe à 0 -> détection convoi en amont */ + SET(S8,1) /* lance le feu clignotant */ + PERM(S6) /* ferme la barrière 1 */ + PERM(S7) /* ferme la barrière 2 */ + WSTOP(E2B,1) /* attend que E2 passe à 0 -> détection convoi proche du PN */ + PERM(S8) /* clignotant devient fixe */ + WSTOP(E2H,1) /* attend que E2 repasse à 1 -> convoi est passé */ + UNSET(S8) /* eteint le feu clignotant */ + UNSET(S7) /* ouvre la barrière 2 */ + UNSET(S6) /* ouvre la barrière 1 */ + LOOP /* Retoune au point de retour */ +FINSEQ(Prog101) diff --git a/ConfigLumieres.h b/ConfigLumieres.h index 330fe8a..3e82198 100644 --- a/ConfigLumieres.h +++ b/ConfigLumieres.h @@ -13,89 +13,73 @@ // // Plus d'exemples dans la documention, notamment pour les fonctions les // avancées comme le poste de soudure, le flash du photographe, ... -// +// ===================================================================== + // === Ce fichier est à adapter en fonction de vos automatismes ======== // --------------------------------------------------------------------- // --- ICI COMMENCE LA CONFIGURATION EN FONCTION DE VOTRE SCENE --- -// Affectation des types d'éclairage ou de fonctions à chaque sortie -const byte ledCnf[] = { - /* D2 */ ETYPE_NEONNEUF, /* S1 (1) : bureau administratif (IO) * - /* D3 */ ETYPE_SOUDURE, /* S2 (2) : accueil (PWM) */ - /* D4 */ ETYPE_STANDARD, /* S3 (4) : bureau M. CLaude (IO) */ - /* D5 */ ETYPE_GYROPHARE, /* S4 (8) : couloir haut (PWM) */ - /* D6 */ ETYPE_FIRE, /* S5 (16) : escalier (PWM) */ - /* D7 */ ETYPE_NEONNEUF, /* S6 (32) : couloir bas (IO) */ - /* D8 */ ETYPE_NEONNEUF, /* S7 (64) : bureau M. Gaston (IO) */ - /* D9 */ ETYPE_NEONVIEUX, /* S8 (128) ou SM1 : bureau secrétaire (PWM) */ - /* D10 */ ETYPE_STANDARD, /* S9 (256) ou SM2 : bureau Mlle Pélerin (PWM) */ - /* D11 */ ETYPE_GYROPHARE /* S10 (512) : gyrophare (PWM) */ -}; +// Prog 6 : Lumières d'une fosse d'inspection +// En voici les spécifications : +// 1. fosse normalement éteinte sauf si forçage par entrée digital (M83 - bouton vert - au commun==GND) +// 2. une locomotive passe sans s’arrêter, la fosse reste éteinte sauf si le forçage est en cours +// 3. une locomotive stationne, au bout d’un temps programmable, la fosse s’allume +// 4. la fosse allumée s’éteint au bout d’un certain temps programmable, économie d’énergie oblige +// 5. une locomotive repart, la fosse allumée s’éteint au bout d’un temps programmable +// 6. entrée digital pour un forçage éteint même si des locomotives stationnent (M83 - bouton rouge - au commun==GND) -// Pour la commande d'un servo moteur sur la sortie D9 ou D10 uniquement -// LIGNE CI-APRÈS À METTRE EN COMMENTAIRE SI VOUS N'UTILISEZ AUCUN SERVO -//#include +DEBUTSEQ(myProg_Seq1) + SETMODE(S2,ETYPE_STANDARD) /* relai pour allumer les lampes */ + + ATTACH(E2B,S2) /* force l'allumage sur un lien */ + ATTACH(E3B,S2) /* force l'extinction sur un autre lien */ -// Séquence est une liste de couple (sorties, durée d'allumage en secondes, commande) -// Cf le fichier FSMLumieres.h pour la signification de chaque commande utilisée + 0,5,_MARK, + WSTOP(E1B,10) /* loco avérée pendant 10 secondes */ + UNTIL(S2,4) /* allume S2 pendant 4 minutes */ + WSTOP(E1H,10) /* loco s'en va, attend 10 secondes */ + UNSET(S2) /* au cas où S2 soit encore allumé */ + LOOP +FINSEQ(mySeq1) -// Je peux me définir des symboles pour faciliter la lecture de mon automatisme -#define Administratif S1 -#define Accueil S2 -#define Claude S3 -#define CouloirEtage S4 -#define Escalier S5 -#define CouloirRDC S6 -#define Gaston S7 -#define Secretaire S8 -#define LaMiss S9 -#define Incendie S10 +// Prog 7 : Automatismes d'un atelier -/* Séquence 1 : Miss Pélerin passe (avec ou sans M. Gaston) */ -DEBUTSEQ(mySeq1) - ATTACH(Incendie,E1B) /* déclenche le gyrophare si l'entrée 1 passe à l'état bas */ - SET(Accueil,10) /* allume l'accueil (néon neuf) pendant 10 secondes */ - SET(Accueil+CouloirRDC,10) /* laisse l'accueil allumé et allume le couloir RDC (néon neuf) pendant 10 secondes */ - SET(Escalier+CouloirRDC,10) /* éteint l'accueil et allume le couloir RDC (néon neuf) et l'escalier (néon ancien) pendant 10 secondes */ - SET(Escalier+CouloirEtage,10) /* ETC :) */ - SET(CouloirEtage+LaMiss,10) - ALEA(Gaston,2) /* parfois M. gaston accompagne la miss (50% de chance) */ - ALEA(Secretaire,2) /* parfois la secrétaire accompagne la miss (50% chance) */ - STANDBY(LaMiss,10) /* la miss reste dans son bureau un certain temps (1 à 10 minutes) */ - SET(CouloirEtage+LaMiss,2) - SET(CouloirEtage,10) - SET(CouloirEtage+Escalier,10) - SET(Escalier+CouloirRDC,10) - SET(CouloirRDC+Accueil,10) - SET(Accueil,10) /* éteint le couloir du RDC, allume l'accueil pendant 10 secondes */ - END /* fin de la séquence, tout est éteint */ -FINSEQ(mySeq1) +DEBUTSEQ(myProg_Seq2) + SETMODE(S1,ETYPE_NEONNEUF) /* S1 : lampe de l’atelier (IO) */ + SETMODE(S2,ETYPE_NEONNEUF) /* S2 : néon de l’atelier (PWM) */ + + SETMODE(S4,ETYPE_SOUDURE) /* S4 : poste de soudure de l’atelier (PWM) */ + + SETMODE(S6,ETYPE_BUZZER) /* S6 : buzzer du poste de soudure (PWM) */ + SETMODE(S7,ETYPE_SERVO) /* S7 : servomoteur de la porte (PWM) */ + SETMODE(S8,ETYPE_GYROPHARE) /* S8 : gyrophare de la porte (PWM) */ + + PERM(S1+S2) /* l’atelier se met au travail au démarrage de l’Arduino … */ + + 0,5,_MARK, /* point de retour de l’automatisme (et timeout à 5 minutes) */ + WSTOP(E1orE2B,1) /* attend la détection d’une locomotive sur la voie 1 ou voie 2 */ + UNTIL(S8,2) /* lance le gyrophare configuré sur la sortie D11 pour deux minutes */ + WAIT(5) /* attend 5 secondes */ + UNTIL(S7,2) /* envoie 90° sur la sortie D10 du servomoteur pour deux minutes */ + WSTOP(E1andE2H,1) /* attend la non détection de la locomotive sur la voie 1 ou voie 2 */ + UNSET(S7) /* envoie 0° sur la sortie D10 du servomoteur */ + WAIT(5) /* attend 5 secondes */ + UNSET(S8) /* arrête le gyrophare configuré sur la sortie D11 */ + + WSTOP(E2B,1) /* attend la détection d’une locomotive sur la voie 2 */ -/* Séquence 2 : le dépot fonctionne de nuit */ -DEBUTSEQ(mySeq2) - ATTACH(Incendie,E1B) /* déclenche le gyrophare si l'entrée 1 passe à l'état bas */ - SET(Accueil,10) - PERM(Accueil) - SET(CouloirRDC,10) - SET(CouloirRDC+Administratif,2) - SET(Administratif,2) - PERM(Administratif) - SET(Escalier,10) - SET(Escalier+CouloirEtage,10) - PERM(Secretaire) - ALEA(LaMiss,4) /* La Miss n'est pas toujours présente la nuit ! */ - ALEA(Gaston,2) - ALEA(Claude,2) - WSTOP(ESTARTB,3) - UNSET(LaMiss+Secretaire+Gaston+Claude) /* éteint les bureaux de l'étage */ - SET(Escalier,10) - UNSET(CouloirEtage+Administratif) /* eteint couloir haut et administratif */ - WAIT(10) - UNSET(CouloirRDC) /* éteint couloir bas */ - WAIT(10) - UNSET(Accueil) /* éteint accueil */ - END /* fin de la séquence */ + 0,5,_MARK, /* point de retour de l’automatisme (et timeout à 5 minutes) */ + WAIT(5) /* 5 secondes */ + SET(S4+S6,15) /* un peu de soudure sur la locomotive qui vient de rentrer pendant 15 secondes */ + UNTIL(S7,2) /* envoie 90° sur la sortie D10 du servomoteur pour deux minutes */ + + WSTOP(E2H,1) /* attend la non détection de la locomotive sur la voie 2 */ + UNSET(S4+S6) /* arrête le poste soudure, la loco est partie ! */ + UNSET(S7) /* envoie 0° sur la sortie D10 du servomoteur */ + WAIT(5) /* 5 secondes */ + + RESET /* boucle attendre la locomotive suivante */ FINSEQ(mySeq2) // --- ICI SE TERMINE LA CONFIGURATION EN FONCTION DE VOTRE SCENE --- diff --git a/ConfigNano.h b/ConfigNano.h index 08fd282..57b13f8 100644 --- a/ConfigNano.h +++ b/ConfigNano.h @@ -26,30 +26,48 @@ const byte LIGHT_FAD4 = PWM_FOR_LED/4; const byte LIGHT_FAD8 = PWM_FOR_LED/8; const byte LIGHT_OFF = 0; -// Configuration du mode de chaque sortie (Arduino Nano) -const byte outputMode[] = { +// mapping sortie logique (0..maxoutputs-1) -> sortie physique +const byte gDx[] = { + /* D2 : S1 */ 2, + /* D3 : S2 */ 3, + /* D4 : S3 */ 4, + /* D5 : S4 */ 5, + /* D6 : S5 */ 6, + /* D9 : S6 ou SM1 */ 9, + /* D10 : S7 ou SM2 */ 10, + /* D11 : S8 */ 11 +}; + +// index des servo moteurs dans la table des sorties physiques +#define Index_SM1 5 +#define Index_SM2 6 + +// mode de chaque sortie : IO standard ou PWM +const byte gMode[] = { /* D2 : S1 */ MODE_IO, /* D3 : S2 */ MODE_PWM, /* D4 : S3 */ MODE_IO, /* D5 : S4 */ MODE_PWM, /* D6 : S5 */ MODE_PWM, - /* D7 : S6 */ MODE_IO, - /* D8 : S7 */ MODE_IO, - /* D9 : S8 ou SM1 */ MODE_PWM, - /* D10 : S9 ou SM2 */ MODE_PWM, - /* D11 : S10 */ MODE_PWM, + /* D9 : S6 ou SM1 */ MODE_PWM, + /* D10 : S7 ou SM2 */ MODE_PWM, + /* D11 : S8 */ MODE_PWM }; // Nombre maximum d'éclairages dans le tableau précédent -#define maxLights sizeof(outputMode)/sizeof(byte) +#define maxOutputs sizeof(gMode) // Entrée digital D15 permettant de choisir la séquence 1 ou la séquence 2 (Pull-up) const byte seqPin = 15; -// Entrée digital D14 permettant de passer en RUN (1) ou en STOP (0) (Pull-up) -const int startPin = 14; /* ESTARTB/ESTARTH selon l'état bas (STOP) ou haut (RUN) */ +// Entrées D7 et D8 pour extraire le numéro d'automatisme, cumulés avec seqPin ! +const byte prog0Pin = 7; +const byte prog1Pin = 8; -// Entrées digitals utilisateur (Pull-Up) +// Entrée digitale D14 permettant de passer en RUN (1) ou en STOP (0) (Pull-up) +const byte startPin = 14; /* ESTARTB/ESTARTH selon l'état bas (STOP) ou haut (RUN) */ + +// Entrées digitales utilisateur (Pull-Up) const byte inputUserPin1 = 16; /* E1B / E1H selon l'état bas ou haut */ const byte inputUserPin2 = 17; /* E2B / E2H selon l'état bas ou haut */ const byte inputUserPin3 = 18; /* E3B / E3H selon l'état bas ou haut */ @@ -57,8 +75,13 @@ const byte inputUserPin4 = 19; /* E4B / E3H selon l'état bas ou haut */ // Anti-rebond optimisé pour la rétro-signalisation Marklin C / Platine Obourg v2 const byte maxInputPins = 5; /* nombre d'entrées à gérer en anti-rebond */ +const byte maxInputs = maxInputPins+3; + const byte maxFiltreH = 8; /* en millisecondes, le temps que l'entrée doit être stabilisée avant de passer de 1 -> 0 */ const byte maxFiltreB = 512; /* en millisecondes, le temps que l'entrée doit être stabilisée avant de passer de 0 -> 1 */ -// Entrée pour le seed Generator -const byte seedPin = 7; +// Entrée analogique A6 non utilisée +const byte unusedPin = A6; + +// Entrée Analogique (A7/D21) pour le seed Generator +const byte seedPin = A7; \ No newline at end of file diff --git a/ConfigTests.h b/ConfigTests.h deleted file mode 100644 index fa918ca..0000000 --- a/ConfigTests.h +++ /dev/null @@ -1,69 +0,0 @@ -// Lumieres::ConfigTests.h -// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL -// -// Ce fichier concerne la configuration de scènes de tests, à adapter -// selon votre environnement de test. -// -// --------------------------------------------------------------------- -// --- ICI COMMENCE LA CONFIGURATION EN FONCTION DE VOS TESTS --- - -// Affectation des types d'éclairage ou de fonctions à chaque sortie -const byte ledCnf[] = { - /* D2 */ ETYPE_NEONNEUF, /* S1 (1) : néon neuf sur une sortie standard (IO) * - /* D3 */ ETYPE_SOUDURE, /* S2 (2) : poste de soudure (PWM) */ - /* D4 */ ETYPE_STANDARD, /* S3 (4) : sortie standard (IO) */ - /* D5 */ ETYPE_GYROPHARE, /* S4 (8) : gyrophare (PWM) */ - /* D6 */ ETYPE_FIRE, /* S5 (16) : feu bougie ou braseo (PWM) */ - /* D7 */ ETYPE_NOTUSED, /* S6 (32) : not used (IO) */ - /* D8 */ ETYPE_NOTUSED, /* S7 (64) : not used (IO) */ - /* D9 */ ETYPE_NEONVIEUX, /* S8 (128) ou SM1 : néon vieux avec glitchs (PWM) */ - /* D10 */ ETYPE_SERVO, /* S9 (256) ou SM2 : Servo moteur (PWM) */ - /* D11 */ ETYPE_BUZZER /* S10 (512) : Buzzer (PWM) */ -}; - -// Pour la commande d'un servo moteur sur la sortie D9 ou D10 uniquement -// LIGNE CI-APRÈS À METTRE EN COMMENTAIRE SI VOUS N'UTILISEZ AUCUN SERVO -#include - -// --------------------------------------------------------------------- -// Des séquences a pour tester le programme et/ou tester les éclairages -// --------------------------------------------------------------------- - -// Séquence 1 : un simple chenillard sur les sorties D2, D4 et D9 , c'est bien ! -// Je mixe volontairement macro langage et structure de données -DEBUTSEQ(mySeq1) - MARK /* place une MARK pour le LOOP */ - PERM(S4) /* Allume D5 le gyrophare */ - 4, 10, _SET, /* Allume D4 (éclairage standard) pendant 10 secondes */ - 2, 10, _SET, /* Eteint D4 et Allume D2 (néon neuf) pendant 10 secondes */ - 128, 10, _SET, /* Eteint D2 et Allume D9 (néon ancien) pendant 10 secondes */ - 0, 5, _WAIT, /* pause pendant 5 secondes, ne touche pas au lumières allumées */ - 0, 10, _SET, /* Eteint D9 et attends 10 secondes */ - 2+4+128,10, _SET, /* Allume D3, D5 et D6 pendant 10 secondes */ - UNSET(S4) /* Arrete le gyrophare */ - LOOP /* Tout est éteint. Boucle sur le début MARK */ -FINSEQ(mySeq1) - -// Séquence 2 : un chenillard sur l'ensemble des sorties, c'est encore mieux ! -// A noter que la sortie S3 (broche D4) est reliée à l'entrée E1B, mettre cette -// entrée à 0 pour lancer le gyrophare -DEBUTSEQ(mySeq2) - 4, E1B, _ATTACH, /* utile pour tester l'anti-rebond ... */ - MARK - 1, 10, _SET, - 2, 10, _SET, - 8, 10, _SET, - 16, 10, _SET, - 32, 10, _SET, - 64, 10, _SET, - 128, 10, _SET, - 256, 10, _SET, - 512+2, 10, _SET, /* Buzzer doit etre activité avec le poste soudure sinon bug */ - 0, 10, _WAIT, /* Attend pendant 10 secondes */ - 1023-4-256, 10, _SET, /* Allume tout pendant 10 secondes, sauf le servo et la sortie attachée */ - 0,0,_WSTOP, - LOOP -FINSEQ(mySeq2) - -// --- ICI SE TERMINE LA CONFIGURATION EN FONCTION DE VOS TESTS --- -// --------------------------------------------------------------------- diff --git a/ConfigTestsFiltres.h b/ConfigTestsFiltres.h deleted file mode 100644 index 0cc653f..0000000 --- a/ConfigTestsFiltres.h +++ /dev/null @@ -1,55 +0,0 @@ -// Lumieres::ConfigTestsFiltres.h -// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL -// -// Ce fichier concerne la configuration de scènes de tests pour la -// fonctionnalité de filtrage anti-rebond -// -// --------------------------------------------------------------------- -// --- ICI COMMENCE LA CONFIGURATION EN FONCTION DE VOS TESTS --- - -// Affectation des types d'éclairage ou de fonctions à chaque sortie -const byte ledCnf[] = { - /* D2 */ ETYPE_STANDARD, /* S1 (1) : sortie standard (IO) * - /* D3 */ ETYPE_STANDARD, /* S2 (2) : sortie standard (PWM) */ - /* D4 */ ETYPE_STANDARD, /* S3 (4) : sortie standard (IO) */ - /* D5 */ ETYPE_STANDARD, /* S4 (8) : sortie standard(PWM) */ - /* D6 */ ETYPE_NOTUSED, /* S5 (16) : not used (PWM) */ - /* D7 */ ETYPE_NOTUSED, /* S6 (32) : not used (IO) */ - /* D8 */ ETYPE_NOTUSED, /* S7 (64) : not used (IO) */ - /* D9 */ ETYPE_NOTUSED, /* S8 (128) ou SM1 : not used (PWM) */ - /* D10 */ ETYPE_NOTUSED, /* S9 (256) ou SM2 : not used (PWM) */ - /* D11 */ ETYPE_NOTUSED /* S10 (512) : not used (PWM) */ -}; - -// Pour la commande d'un servo moteur sur la sortie D9 ou D10 uniquement -// LIGNE CI-APRÈS À METTRE EN COMMENTAIRE SI VOUS N'UTILISEZ AUCUN SERVO -//#include - -// --------------------------------------------------------------------- -// Des séquences a pour tester le programme et/ou tester les éclairages -// --------------------------------------------------------------------- - -// Séquence 1 : Sorties en fonction de la rétro (détection loco) -DEBUTSEQ(mySeq1) - 1, E1B, _ATTACH, /* utile pour tester l'anti-rebond ... */ - 4, E3B, _ATTACH, /* utile pour tester l'anti-rebond ... */ - 8, E4B, _ATTACH, /* utile pour tester l'anti-rebond ... */ - MARK /* point de retour de l’automatisme */ - WSTOP(E2B,1) /* attend la détection d’une locomotive sur l’entrée E2 */ - ALEA(S2,4) /* lance le flash configuré sur la sortie S2 aléatoirement (0..3) */ - LOOP /* boucle pour flasher à nouveau */ -FINSEQ(mySeq1) - -// Séquence 2 : Sorties en fonction de la rétro (non détection loco) -DEBUTSEQ(mySeq2) - 1, E1H, _ATTACH, /* utile pour tester l'anti-rebond ... */ - 4, E3H, _ATTACH, /* utile pour tester l'anti-rebond ... */ - 8, E4H, _ATTACH, /* utile pour tester l'anti-rebond ... */ - MARK /* point de retour de l’automatisme */ - WSTOP(E2H,1) /* attend la non détection d’une locomotive sur l’entrée E2 */ - ALEA(S2,4) /* lance le flash configuré sur la sortie S2 aléatoirement (0..3) */ - LOOP /* boucle pour flasher à nouveau */ -FINSEQ(mySeq2) - -// --- ICI SE TERMINE LA CONFIGURATION EN FONCTION DE VOS TESTS --- -// --------------------------------------------------------------------- diff --git a/FSMLumieres.h b/FSMLumieres.h index 857c320..a672dfa 100644 --- a/FSMLumieres.h +++ b/FSMLumieres.h @@ -18,16 +18,35 @@ const byte _WAIT = 4; /* pause d'une durée définie, ne touche à aucun écl const byte _WSTOP = 5; /* pause d'une durée indéfinie, ne touche à aucun éclairage, attends que l'entrée startPin passe à l'état LOW */ const byte _PWM = 6; /* envoie le signal sur la sortie si compatible : D3, D5, D6, D9, D10 et D11 */ const byte _ATTACH = 7; /* attache sortie(s) et entrée et gère les éclairages selon l'état de cette entrée */ -const byte _DETACH = 8; /* suppripe le lien existant entre éclairages et l'état d'une entrée */ +const byte _DETACH = 8; /* supprime le lien existant entre éclairages et l'état d'une entrée */ +const byte _SETMODE = 9; /* change le mode de configuration d'une sortie - cf ETYPE_xxx */ +const byte _UNTIL = 10; /* lance les éclairages pendant la durée définie */ const byte _END = 99; /* marqueur de fin de séquence */ const byte _LOOP = 88; /* marqueur de boucle pour redémarrer sur le MARK */ const byte _MARK = 77; /* place le marqueur pour le LOOP */ +const byte _RESET = 66; /* redémarre la FSM */ // Pointeur vers la séquence en cours, une séquence étant une suite de couple (éclairages, durée, commande) -int* gpSeq; +byte* gpSeq; + +// Timeout général sur MARK et sur WSTOP +long int gMARKTimeout; +long int gWSTOPTimeout; + +// Configuration des E/S (valeurs par défaut) +byte gCnf[maxOutputs] = { + /* D2 */ ETYPE_STANDARD, /* S1 (1) : sortie standard (IO) * + /* D3 */ ETYPE_STANDARD, /* S2 (2) : sortie standard (PWM) */ + /* D4 */ ETYPE_STANDARD, /* S3 (4) : sortie standard (IO) */ + /* D5 */ ETYPE_STANDARD, /* S4 (8) : sortie standard (PWM) */ + /* D6 */ ETYPE_STANDARD, /* S5 (16) : sortie standard (PWM) */ + /* D9 */ ETYPE_STANDARD, /* S6 (32) ou SM1 : sortie standard (PWM) */ + /* D10 */ ETYPE_STANDARD, /* S7 (64) ou SM2 : sortie standard (PWM) */ + /* D11 */ ETYPE_STANDARD /* S8 (128) : sortie standard (PWM) */ +}; // Pointeur vers la mark -int* gpMarkSeq; +byte* gpMarkSeq; // machine à état des séquences const byte START = 0; /* état initial */ @@ -43,10 +62,10 @@ bool gCurrentStateStartPin; // parametres de l'automate struct { long int duration; /* durée avant la transition */ - int leds; /* leds concernés par la transition */ + byte leds; /* leds concernés par la transition */ byte command; /* commande associée */ } gSeq; // anti rebond des entrées -byte inputState[maxInputPins]; +byte inputState[maxInputs]; byte inputCount[maxInputPins]; diff --git a/FSMeclairage.h b/FSMeclairage.h index d69c8c7..376ab8f 100644 --- a/FSMeclairage.h +++ b/FSMeclairage.h @@ -34,16 +34,16 @@ const byte estate_PWRUP = 2; /* éclairage en allumage --> ON quand la séqu const byte estate_ON = 3; /* éclairage allumé */ // blink transition pour un éclairage -typedef struct blink { +typedef struct _blink { int duration; byte intensity; } blink; -// par défaut, un éclairage n'est connecté à aucune entrée -const int LightNotLinked = 255; +// par défaut, une sortie n'est connectée à aucune entrée +const int OutputNotLinked = 255; // parametres d'un éclairage -typedef struct { +typedef struct _paramOutput { byte stateRunning; /* état (OFF, STPWRUP, PWRUP ou ON) */ byte statePwrup; /* dans l'état PWRUP, mémoriser la transition en cours */ int stateDelay; /* delay avant la prochaine transition ON OFF */ @@ -52,7 +52,8 @@ typedef struct { byte nextState; /* état une fois que la table des transitions a été parcourue */ byte param; byte link; /* si l'éclairage est lié à une entrée */ -} paramLight; + long int duration; +} paramOutput; -// Pour chaque éclairage -paramLight gLight[maxLights]; +// Pour chaque sortie +paramOutput gLight[maxOutputs]; diff --git a/Lumieres.ino b/Lumieres.ino index 9005927..a3ae226 100644 --- a/Lumieres.ino +++ b/Lumieres.ino @@ -1,7 +1,7 @@ // Lumieres -// Exemple pour le forum 3rails / Julie Dumortier / Licence GPL +// Automate pour le forum 3rails / Julie Dumortier / Licence GPL // -// La gestion d'un batiment, d'une scène, d'un ensemble d'éclairages et automatismes avec un petit Arduino Nano +// La gestion d'un batiment, d'une scène, d'un ensemble d'éclairages et autres automatismes avec un petit Arduino Nano // // Historique des versions (résumé) // v20211027 - première implémentation, mise au point, mode debug @@ -21,18 +21,24 @@ // v20211107 - Better traces + some buzzer testing + SERVO usage impact D9 (S8) & D10 (S9) pins not working with PWM // v20230913 - Ajout d'un filtre anti-rebond sur les entrées (non publié) // v20231008 - Publication sur un Pull Request Git Julaye-filter (isoler le développement) + Corrige des typos + Maj commentaires + Traces +// v20231009 - Automatismes précodés et accessibles via une configuration - cf issue https://github.com/Julaye/Lumieres/issues/10 + Various +// v20231010 - Simplification : PROG0/1 sur D7/D8 et réduction du nombre de sorties de 10 (S1 à S10) à 8 (S1 à S8) +// v20231012 - Ajoute la commande SETMODE pour modifier la configuration des sorties directement dans la séquence d'un automatisme +// v20231013 - Quelques typos + ajout de la commande UNTIL + paramètre duration sur la commande MARK +// v20231014 - Ajout de la commande RESET + Ajout des entrées calculées + Commande WSTOP teste l'entrée pendant la durée mentionnée // // Attention -// brancher des micro-leds de type 2,9 V sur GND et D2 à D11, protégée par une résistance svp ! +// brancher des micro-leds de type 2,9 V sur GND et les sorties Dx, protégée par une résistance svp ! // utilisez le calculateur de résistance svp https://www.digikey.fr/fr/resources/conversion-calculators/conversion-calculator-led-series-resistor // pas plus de 40 mA par sortie, pas plus de 200 mA au total, au risque de griller une sortie et/ou l'Arduino Nano // // l'intensité globale est réglable sur les sorties D3, D5, D6, D9, D10 et D11 (cf PWM_FOR_LED dans ConfigNano.h) // -// le mode de fonctionnement (néon ancien, néon récent, lampe à incadescence standard, ...) est configurable pour chaque sortie (cf ledCnf[]) +// le mode de fonctionnement (néon ancien, néon récent, lampe à incadescence standard, ...) est configurable pour chaque sortie (cf myLedCnf[]) // -// D14 est une entrée qui permet de choisir au démarrage entre la séquence 1 (cf seq1) et la séquence 2 (cf seq2) -// D15 est une entrée qui permet de lancer ou relancer la séquence +// D7 et D8 sont des entrées qui permettent de choisir au démarrage un automatisme encodée (Prog00x, Prog01x, Prog10x ou myProg_SeqN) +// D14 est une entrée qui permet de choisir au démarrage entre la séquence 1 (cf seq1) et la séquence 2 (cf seq2) de l'automatisme +// D15 est une entrée qui permet de lancer ou relancer la séquence (START) // // les séquences sont configurables avec une petite logique temporelle // si vous touchez un autre paramètre, c'est à vos risques et périls :) @@ -69,6 +75,9 @@ const byte PWM_FOR_BUZZER = 255; // Ce fichier concerne la machine à état fini pour gérer le batiment, la scène, ... #include "FSMLumieres.h" +// === Pour la commande d'un servo moteur sur la sortie D9 ou D10 uniquement === +#include + // --------------------------------------------------------------------- // // Système de mise au point @@ -88,74 +97,102 @@ const byte PWM_FOR_BUZZER = 255; // informations d'erreurs #define DBG_ENABLE_ERROR -// Utilisation d'automatismes de tests (cf FSMLumieres.h) -#define DBG_ENABLE_TESTS - // --------------------------------------------------------------------- -// Configuration des deux automatismes (mySeq1 et mySeq2) - -#ifdef DBG_ENABLE_TESTS -// activer un seul fichier en fonction des tests à faire -//#include "ConfigTests.h" -#include "ConfigTestsFiltres.h" -#else -// la configuration de votre automatisme se trouve dans ce fichier +// Configuration des automatismes + +#include "ConfigAutomatismes.h" #include "ConfigLumieres.h" -#endif // --------------------------------------------------------------------- // au besoin, structure pour piloter un servo moteur sur D9 ou D10 -#ifdef Servo_h -Servo gServo; -#endif +Servo gServo[2]; // --------------------------------------------------------------------- // --- initFSM() // --------------------------------------------------------------------- -void initFSM() -{ - byte seq; - - #ifdef DBG_ENABLE_VERBOSE - Serial.print("Init FSM "); - #endif - - // Initialise l'automate de chaque sortie - for (int i = 0 ; i < maxLights; i++) { - gLight[i].stateRunning = estate_OFF; - gLight[i].link = LightNotLinked; - } +void resetFSM() +{ + byte prog; // récupère la séquence pour le mode RUNNING - seq = digitalRead(seqPin); + prog += (digitalRead(prog1Pin)*4) + (digitalRead(prog0Pin)*2) + digitalRead(seqPin); #ifdef DBG_ENABLE_INFO - Serial.print("Séquence : "); - Serial.print(seq+1); + Serial.print(F("Programme : 0x")); + Serial.print(prog,HEX); #endif + #ifdef DBG_ENABLE_INFO + Serial.print(F(" Trace Info")); + #endif + #ifdef DBG_ENABLE_VERBOSE + Serial.print(F("+Verbose")); + #endif #ifdef DBG_ENABLE_DEBUG - Serial.print(" - Debug"); - #else - #ifdef DBG_ENABLE_INFO - Serial.print(" - Normal"); - #endif + Serial.print(F("+Debug")); #endif - - #ifdef DBG_ENABLE_TESTS - Serial.println(" - ConfigTests.h"); - #else - #ifdef DBG_ENABLE_INFO - Serial.println(" - ConfigLumieres.h"); - #endif + #ifdef DBG_ENABLE_ERROR + Serial.print(F("+Error")); #endif + #ifdef DBG_ENABLE_INFO + Serial.println(); + #endif + + // début de la séquence en fonction du programme + switch (prog) { + case 0: + default: + gpSeq = (byte*)&Prog000; + break; + + case 1: + gpSeq = (byte*)&Prog001; + break; + + case 2: + gpSeq = (byte*)&Prog010; + break; - (seq==LOW)?gpSeq=(int*)&mySeq1:gpSeq=(int*)&mySeq2; + case 3: + gpSeq = (byte*)&Prog011; + break; + + case 4: + gpSeq = (byte*)&Prog100; + break; + + case 5: + gpSeq = (byte*)&Prog101; + break; + + case 6: + gpSeq=(byte*)&myProg_Seq1; + break; + + case 7: + gpSeq=(byte*)&myProg_Seq2; + break; + } // mark par défaut sur le début de la séquence gpMarkSeq = gpSeq; +} + +void initFSM() +{ + #ifdef DBG_ENABLE_VERBOSE + Serial.print(F("Init FSM ")); + #endif + + // Initialise l'automate de chaque sortie + for (int i = 0 ; i < maxOutputs; i++) { + gLight[i].stateRunning = estate_OFF; + gLight[i].link = OutputNotLinked; + } + + resetFSM(); // initialise les différents états gSeqState = START; @@ -164,6 +201,8 @@ void initFSM() gSeq.duration = millis(); gSeq.leds = 0; gSeq.command = _SET; + gMARKTimeout = 0; + gWSTOPTimeout = 0; } // --------------------------------------------------------------------- @@ -180,11 +219,16 @@ void setup() { // indicateur que la séquence est vivante ! pinMode(LED_BUILTIN,OUTPUT); - // Ports digitaux programmables (PWM) : D3, D5, D6, D9, D10 et D11 - for (int i = 0 ; i < maxLights; i++) pinMode(i+2,OUTPUT); + // Ports digitaux programmables (IO/PWM) en sorties + for (int i = 0 ; i < maxOutputs; i++) { + pinMode(gDx[i],OUTPUT); + gCnf[i] = ETYPE_STANDARD; + } - // pin pour choisir la séquence + // pin pour choisir la séquence et le programme pinMode(seqPin,INPUT_PULLUP); + pinMode(prog0Pin,INPUT_PULLUP); + pinMode(prog1Pin,INPUT_PULLUP); // pin pour démarrer / stopper la FSM générale pinMode(startPin,INPUT_PULLUP); @@ -212,10 +256,10 @@ void setup() { randomSeed(analogRead(seedPin)); // Annonce la version - Serial.println("Lumieres - version 20231008 - (c) Julie Dumortier - Licence GPL"); + Serial.println(F("Lumieres - version 20231014 - (c) Julie Dumortier - Licence GPL")); // initialize la FSM - #ifdef DBG_ENABLE_DEBUG + #ifdef DBG_ENABLE_VERBOSE Serial.print("HW RESET -> INIT seed:"); Serial.println(random()); #endif @@ -242,7 +286,7 @@ void printCmd(int leds,bool timing=false,char cmd=0x00) Serial.print(" ["); Serial.print(cmd); - for (int i=0; i state OFF"); + Serial.println(F(" said --> state OFF")); #endif gLight[led].stateRunning = estate_OFF; @@ -446,7 +494,7 @@ bool linkOn(byte led) bool r; // la led est-elle liée à une entrée ? */ - if (gLight[led].link != LightNotLinked) { + if (gLight[led].link != OutputNotLinked) { // récupère le numéro de l'entrée mais aussi l'état bas/haut attendu io = gLight[led].link&0x7F; @@ -455,9 +503,9 @@ bool linkOn(byte led) r = (inputState[io] == ((gLight[led].link&0x80)?LOW:HIGH)); if (!r) { #ifdef DBG_ENABLE_INFO - Serial.print("LINK input E"); + Serial.print(F("LINK input E")); Serial.print(io); - Serial.println(" said --> state STPWRUP"); + Serial.println(F(" said --> state STPWRUP")); #endif gLight[led].stateRunning = estate_STPWRUP; @@ -470,8 +518,8 @@ bool linkOn(byte led) byte linkOut(byte typeled=ETYPE_BUZZER) { - for (int i=0; i0) { + if (gLight[led].duration0) { + if (gMARKTimeout LOOP")); + #endif + gMARKTimeout = 0; + gpSeq = gpMarkSeq; + PowerDownLeds(gSeq.leds); + } + } + // il est écoulé - #ifdef DBG_ENABLE_INFO - Serial.print("NEXT "); + #ifdef DBG_ENABLE_VERBOSE + Serial.print(F("NEXT ")); #endif // préserve les leds qu'il faudra peut être éteindre @@ -880,7 +1060,7 @@ void runningFSM() case _END: #ifdef DBG_ENABLE_INFO - Serial.println("END -> STOP"); + Serial.println(F("END -> STOP")); #endif gSeqState = STOP; @@ -890,17 +1070,20 @@ void runningFSM() case _MARK: /* place la mark pour un futur LOOP */ #ifdef DBG_ENABLE_INFO - Serial.println("MARK"); + Serial.print(F("MARK timeout ")); + Serial.print(duration); + Serial.println(F(" min")); #endif gpMarkSeq = gpSeq-3; + if (duration>0) gMARKTimeout = millis() + (duration * 60L * 1000L); PowerDownLeds(ledsoff&~io); break; case _LOOP: /* retourne sur la marque */ #ifdef DBG_ENABLE_INFO - Serial.println("LOOP"); + Serial.println(F("LOOP")); #endif gpSeq = gpMarkSeq; @@ -913,9 +1096,9 @@ void runningFSM() gSeq.duration = millis() + r*1000; #ifdef DBG_ENABLE_INFO - Serial.print("STANDBY duration:"); + Serial.print(F("STANDBY duration:")); Serial.print(r); - Serial.print(" s cmd:"); + Serial.print(F(" s cmd:")); printCmd(io); #endif @@ -928,7 +1111,7 @@ void runningFSM() case _PERM: /* permanent : jusqu'à l'arrêt de l'Arduino ou le changement de séquence ou UNSET */ #ifdef DBG_ENABLE_INFO - Serial.print("PERM cmd:"); + Serial.print(F("PERM cmd:")); printCmd(io); #endif @@ -938,9 +1121,9 @@ void runningFSM() case _PWM: #ifdef DBG_ENABLE_INFO - Serial.print("PWN duration:"); + Serial.print(F("PWM duration:")); Serial.print(duration); - Serial.print(" s cmd:"); + Serial.print(F(" s cmd:")); printCmd(io); #endif @@ -955,7 +1138,7 @@ void runningFSM() /* aléatoirement : permet de rendre aléatoire la présence d'une personne dans un bureau la nuit, aligné sur la commande STANDBY suivante ou PERM précédente */ if (random(0,duration)==0) { #ifdef DBG_ENABLE_INFO - Serial.print("ALEA cmd:"); + Serial.print(F("ALEA cmd:")); printCmd(io); #endif @@ -963,7 +1146,7 @@ void runningFSM() gSeq.leds = io; } else { #ifdef DBG_ENABLE_INFO - Serial.print("ALEA NOPE cmd: "); + Serial.print(F("ALEA NOPE cmd: ")); printCmd(io); #endif } @@ -977,15 +1160,29 @@ void runningFSM() gSeq.duration = millis() + duration*1000; #ifdef DBG_ENABLE_INFO - Serial.print("UNSET "); + Serial.print(F("UNSET ")); Serial.print(duration); - Serial.print("s cmd: "); + Serial.print(F("s cmd: ")); printCmd(io); #endif PowerDownLeds(io | ledsoff); break; + case _RESET: + gSeq.duration = millis() + duration*1000; + + #ifdef DBG_ENABLE_INFO + Serial.print(F("RESET ")); + Serial.print(duration); + Serial.print(F("s cmd: ")); + printCmd(io); + #endif + + PowerDownLeds(io | ledsoff); + resetFSM(); + break; + case _SET: if (duration<=0) { gSeq.duration = millis() + 500; /* demi seconde */ @@ -995,9 +1192,9 @@ void runningFSM() gSeq.leds = io; #ifdef DBG_ENABLE_INFO - Serial.print("SET "); + Serial.print(F("SET ")); Serial.print(duration); - Serial.print("s cmd: "); + Serial.print(F("s cmd: ")); printCmd(io); #endif @@ -1005,11 +1202,22 @@ void runningFSM() PowerDownLeds(ledsoff&~io); break; + case _UNTIL: + #ifdef DBG_ENABLE_INFO + Serial.print(F("UNTIL ")); + Serial.print(duration); + Serial.print(F("min cmd: ")); + printCmd(io); + #endif + + PowerUpLedsUntil(io,duration); + break; + case _ATTACH: #ifdef DBG_ENABLE_INFO - Serial.print("ATTACH input E"); + Serial.print(F("ATTACH input E")); Serial.print(duration,HEX); - Serial.print(" cmds:"); + Serial.print(F(" cmds:")); printCmd(io); #endif @@ -1021,7 +1229,7 @@ void runningFSM() case _DETACH: #ifdef DBG_ENABLE_INFO - Serial.print("DETACH cmds:"); + Serial.print(F("DETACH cmds:")); printCmd(io); #endif @@ -1031,6 +1239,17 @@ void runningFSM() gSeq.leds |= ledsoff; break; + case _SETMODE: + #ifdef DBG_ENABLE_INFO + Serial.print(F("SETMODE type ")); + Serial.print(duration); + Serial.print(F(" cmds:")); + printCmd(io); + #endif + + SetModeLeds(io,duration); + break; + case _WAIT: if (duration<=0) { gSeq.duration = millis() + 500; /* demi seconde */ @@ -1039,7 +1258,7 @@ void runningFSM() } #ifdef DBG_ENABLE_INFO - Serial.print("WAIT "); + Serial.print(F("WAIT ")); Serial.println(duration); #endif @@ -1048,23 +1267,32 @@ void runningFSM() break; case _WSTOP: - if (duration<=0) { - gSeq.duration = millis() + 500; /* demi seconde */ - } else { - gSeq.duration = millis() + duration*1000; + if (gWSTOPTimeout==0) { + // début du WSTOP -> fixe la durée totale + if (duration<=0) { + gWSTOPTimeout = millis() + 500; /* demi seconde */ + } else { + gWSTOPTimeout = millis() + duration*1000; + } } + // frequence de test des entrées : la seconde ! + gSeq.duration = millis() + 1000; + // test la condition d'arret du STOP r = (inputState[io&0x7F] == ((io&0x80)?LOW:HIGH)); // Un peu de blabla, c'est utile en mise au point de l'automatisme #ifdef DBG_ENABLE_INFO - Serial.print("WSTOP "); + Serial.print(F("WSTOP ")); Serial.print(duration); - Serial.print(" input E"); + Serial.print(F(" input E")); Serial.print(io,HEX); - Serial.print(" state: "); - Serial.println(r); + Serial.print(F(" state: ")); + Serial.print(r); + Serial.print(F(" Remaining: ")); + long int diff = gWSTOPTimeout-millis(); + Serial.println(diff>0?diff:0); #endif // prévoir les extinction en même temps que le stop en cours @@ -1073,6 +1301,12 @@ void runningFSM() // il faut encore attendre if (r) { gpSeq -=3; /* reste sur la commande en cours */ + gWSTOPTimeout = 0; /* relance l'attente */ + } else { + if (gWSTOPTimeout >= millis()) { + /* on a pas assez attendu -> reste sur la commande en cours */ + gpSeq -=3; /* reste sur la commande en cours */ + } } break; @@ -1101,7 +1335,7 @@ void loop() { if (rst==false) gCurrentStateStartPin=false; if (rst==true) { #ifdef DBG_ENABLE_INFO - Serial.print("SW RESET -> INIT "); + Serial.print(F("SW RESET -> INIT ")); #endif initFSM(); } @@ -1112,7 +1346,7 @@ void loop() { case START: /* Vérifie que c'est un départ sous controle de l'entrée D14 ! */ if ((inputState[0]==HIGH) && (gCurrentStateStartPin==false)) { #ifdef DBG_ENABLE_INFO - Serial.println("START"); + Serial.println(F("START")); #endif // fsmEclairage(); fait en entrée de loop() la première fois diff --git a/MacroLumieres.h b/MacroLumieres.h index d9cb603..0052597 100644 --- a/MacroLumieres.h +++ b/MacroLumieres.h @@ -6,7 +6,7 @@ // --------------------------------------------------------------------------- // DEBUT / FIN d'une séquence -#define DEBUTSEQ(_seq) const int _seq[] = { +#define DEBUTSEQ(_seq) const byte _seq[] = { #define FINSEQ(_seq) }; /* _seq[] */ // Toutes les macros instructions ont la structure suivante : @@ -25,10 +25,13 @@ #define WSTOP(IO,TIME) IO,TIME,_WSTOP, #define PWM(IO,DUTY) IO,DUTY,_PWM, #define ATTACH(IO,IN) IO,IN,_ATTACH, -#define DETACH(IO) IO,0,_DETACH +#define DETACH(IO) IO,0,_DETACH, +#define UNTIL(IO,TIME) IO,TIME,_UNTIL, #define END 0,0,_END, #define MARK 0,0,_MARK, -#define LOOP 0,0,_LOOP, +#define LOOP 0,0,_LOOP, +#define RESET 0,0,_RESET, +#define SETMODE(IO,MODE) IO,MODE,_SETMODE, // Il est aussi utile de définir les sorties et les entrées avec des noms explicites #define S1 1 @@ -39,16 +42,17 @@ #define S6 32 #define S7 64 #define S8 128 -#define S9 256 -#define S10 512 -#define SALL 1023 +#define SALL 255 // entrées à l'état Bas -#define ESTARTB 0 -#define E1B 1 -#define E2B 2 -#define E3B 3 -#define E4B 4 +#define ESTARTB 0 +#define E1B 1 +#define E2B 2 +#define E3B 3 +#define E4B 4 +#define E1andE2B 5 +#define E1orE2B 6 +#define E1xorE2B 7 // entrées à l'état Haut #define ESTARTH 0x80 @@ -56,3 +60,6 @@ #define E2H 0x82 #define E3H 0x83 #define E4H 0x84 +#define E1andE2H 0x85 +#define E1orE2H 0x86 +#define E1xorE2H 0x87 diff --git a/README.md b/README.md index 428cdee..dacdf0c 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ EN : Management of a building, a scene or a set of lighting with an Arduino Nano Objectif du projet : Le programme Lumières est une tentative pour proposer aux adeptes du modélisme un automate de gestion des éclairages d’un bâtiment, d'une scène, ou plus généralement d’un ensemble d’éclairages, qui soit facile d’accès pour un non initié à la programmation d’un Arduino, et fortement paramétrable pour couvrir les besoins les plus courants. -L'utilisateur adapte le fichier *ConfigLumieres.h* selon ses besoins et il obtient un automate opérationnel, sans écrire une seule ligne de code, seulement des données dans le fichier susmentionné. C'est une approche NO CODE - LOW CODE pour surfer sur le buzz des outils de programmation actuels. +L'utilisateur choisi un automatisme parmis ceux qui sont proposés ou bien adapte le fichier *ConfigLumieres.h* selon ses besoins et il obtient un automate opérationnel personnalisé, sans écrire une seule ligne de code, seulement des données dans le fichier susmentionné. C'est une approche NO CODE - LOW CODE pour surfer sur le buzz des outils de programmation actuels. Les types d'éclairages actuellement supportés sont : - lampe standard (allumé ou éteint) @@ -22,6 +22,15 @@ Les types d'éclairages actuellement supportés sont : - feu clignotant qui ne clignote que s’il n’est pas permanent, - (Buzzer liée au poste de soudure à l'arc. --> BOF) +Les automatismes actuellement pré-programmés sont : +- chenillard +- recopie des entrées sur les sorties, avec anti-rebond +- éclairages batiments 1 et 2 avec différentes possibilités +- signaux SNCB (TBD) +- Passage à niveau +- éclairages d'une fosse d'inspection +- éclairages d'une fosse d'inspection dans un batiment + Sur les sorties PWM (D3,D5,D6,D9,D10 et D11), l'automate gère la variation d'intensité lumineuse pour plus de réalisme. Licence : Le logiciel est sous licence GPL et peut être librement utilisé et modifié dans le cadre de notre passion de modélisme, vos éventuelles modifications doivent être reversées à la communauté. @@ -30,11 +39,11 @@ Langage de programmation : C for Arduino Nano Langue du projet : Français / French -Version pre-release supportée : v2023100x +Version beta relaase supportée : v20231014 Documentation : https://docs.google.com/document/d/1chZwYiFPMKlHFLLsJ7WHy0EHtaLVpebEK52L9wi9J30/ -La documentation proposée présente aussi dans son chapitre 9 de nombreux exemples d'automatismes qui sont faciles à réaliser avec cet automate : +La documentation proposée présente aussi dans son chapitre 10 de nombreux exemples d'automatismes qui sont faciles à réaliser avec cet automate : - Photographe paparazzi dont le flash se déclenche au passage d'un train - Gestion de la séquence d'éclairage d'une fosse d'inspection au stationnement d'une locomotive - Animation d'un poste de soudure en présence d'une locomotive dans l'atelier @@ -47,7 +56,21 @@ Forum 3rails : https://forum.3rails.fr/t/une-debutante-dans-le-decor-ep13-que-la ## Notes de version -### v2023100x +### v2023101x - modifications majeures -> beta +- Propose quelques automatismes pré-programmés (ConfigAutomatismes.h) en plus de deux automatismes programmables (ConfigLumieres.h) +- Les entrées D7 (P0), D8 (P1) et D15 (SEQ) permettent de choisir l'automatisme à lancer au démarrage de l'automate +- Corrige un problème sur le seedPin (A7/D21) pour le germe du générateur aléatoire +- Réduit l'empreinte mémoire sur la SRAM +- Réduit le nombre de sorties utilisables à 8 +- Ajoute la commande SETMODE pour modifier la configuration de sorties directement dans la séquence d'un automatisme +- Ajoute la commande UNTIL pour allumer des sorties pendant x minutes sans bloquer la séquence +- Ajoute trois entrées calculées (E1 or E2, E1 and E2, E1 xor E2) +- La commande WSTOP échantillonne à la seconde l'entrée spécifiée pendant la durée mentionnée en paramètre +- Support de deux servos moteurs sur les sorties D9 et D10 +- Rend l'automate compatible avec la *platine "Obourg" Rétro v3* +- Revisite complétement la documentation de l'automate + +### v20231008 - Anti-rebond sur les entrées (pour pouvoir utiliser des entrées de rétro-signalisation) - Fichier spécifique (ConfigTestsFiltres.h) pour tester l'anti-rebond