Enchantée. mais je ne suis pas programmeuse.
C'est une macro, c'est pour économiser la RAM.
Cf par exemple https://www.baldengineer.com/arduino-f-macro.html
Enchantée. mais je ne suis pas programmeuse.
C'est une macro, c'est pour économiser la RAM.
Cf par exemple https://www.baldengineer.com/arduino-f-macro.html
Essayons avec : toujours exécutable sur https://onlinegdb.com/BJ-ZrU8rw
Le code "utile" est à partir de la ligne 39.
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66 /****************************************************************************** Online C++ Compiler: Code, Compile, Run and Debug C++ program online. Write your code in this editor and press "Run" button to compile and execute it. *******************************************************************************/ #include <iostream> #include <cstdint> //partie simulant une bibliothèque externe, class Button //========================================================================== #include <random> #include <functional> #include <chrono> class Button { public: Button(int); ~Button(); int id(); bool is_pushed(); private: int id_; }; auto rnd= std::bind( std::uniform_int_distribution<>{false, true}, std::default_random_engine( std::chrono::system_clock::now().time_since_epoch().count() ) ); Button::Button(int pin) : id_{pin} {}; Button::~Button() {}; bool Button::is_pushed() {return rnd();} int Button::id() {return id_; }; //============================================================================ enum Switch : uint8_t {C1V1= 5, C1V2, C2V1, C2V2, C2V3, D3V3, }; enum Railway: uint8_t {G1D= 22, A1G, A1D, A2G, A2D, A3G, A3D, A4G, A4D, }; const uint8_t max_handled_railways_per_switch= 4; struct Railways_switch { Button button; Railway ways[max_handled_railways_per_switch]; }; Railways_switch rs_map [] { {Button{C1V1}, {G1D, A1G, A3D}}, {Button{C2V1}, {A1G, A1D, A3D, A4D}}, {Button{C2V3}, {A2D, A3G}}, }; int main() { std::cout<< "Attention, le Train passe..."<< '\n'; for (auto& rs: rs_map) { std::cout<< "bouton: "<< rs.button.id() << '\n'; if (rs.button.is_pushed()) { std::cout<< " actionnement des voies:"<< '\n'; for (const auto& way: rs.ways) if (way) std::cout<< " "<< way<< '\n'; } else {std::cout<< " inactif"<< '\n'; }; } std::cout<< "\n Relancez le programme pour simuler un nouveau passage."; }
tout ce qu'il faut pour un débutant !!
(pas besoin de déclarer un destructeur qui ne fait rien, il sera implicite et votre variable privée devrait être du type uint8_t pour correspondre - et si on utilisait la pin 0 dans le montage pour une commande d'aiguillage (si pas besoin du Rx de la console série) alors ça ne fonctionnerait pas)
Salut Jay M
Et, surtout, on est dans un forum Arduino où on devrait faire de "l'Arduino", concept qui a été développé pour faciliter l'approche de la programmation des microcontrôlleurs. Trop souvent les forums Arduino sont "hantés" par des "bolides" en C et autres C++, souvent en dénigrant le "concept Arduino" et qui répondent en C ou C++ sans respecter le dit concept. Personnellement, je fais, de l'Arduino, du moins je le pense car, sans cette super idée venue d'Italie du nord, je n'aurais pas fais du C, je trouvais ce langage assez rébarbatif.
PS: Jacques, excuses pour ce HS
Cordialement
jpbbricole
L'expérience est la seule chose qu'il ne faut acheter que d'occasion!
Mais Arduino, c'est bien ((C & C++) + extensions + AVR-LibC) ? Non ?
Si le compilateur accepte le C++ moderne (C++11...), pourquoi vouloir obliger les gens à s'en priver ?
Les lignes 8 à 36 ne sont utiles que pour la simulation, la demo en ligne, et dans la réalité elles seraient cachées dernière un beau "#include <superButton.h>" dont le débutant n'a que faire du contenu, ce qui ne l'empêche pas de l'utiliser.
Et donc, lorsqu'on decide d'utiliser une bibliothèque tierce, on n'est pas censé modifier son interface, donc si c'est int, c'est int.
C’est la file de Jacques qui est débutant et demande un coup de main.
Je pense que votre approche avec une classe dans le source peoposé dépasse ce qu’il est capable de digérer sans explications - d’ou ma remarque. Mais je peux me tromper.
Dans l’absolu bien sûr il ne faut pas se priver, comme je le dis ci dessous si j’avais à faire un système d’aiguillage pour moi j’utiliserai des classes.
Pour le int versus uint8_t, j’entends votre point de vue. Si c’est caché, c’est caché.
On s’éloigne du sujet de Jacques, Sorry....
Le concept a été créé pour faciliter l’accès à la programmation et au hardware en prototypage rapide (Proto = un truc jetable). Quand on veut faire du non jetable ou un truc qui est amené à se développer, un truc qui doit rester actif des heures ou des jours, il faut à mon avis un peu de rigueur. Massimo Banzi est aussi un éducateur et il y a une dimension apprentissage à prendre en compte. Exposer des alternatives rentre pour moi dans cette approche. Je pense que Massimo Banzi a retenu le C et C++ simplement parce que c'est le langage de choix quand on est proche du matériel (manipulation de registre, contraintes de temps etc) - donc j'y vois aussi une volonté de conserver la porte ouverte aux évolutions et à la programmation plus évoluée.
ça se confirme avec le logo "PROFESSIONAL" d'ailleurs maintenant sur le site web Arduino, il y a bien une orientation aussi vers ce monde là de nos jours (et ils vendent des produits bien loin du UNO comme le Portenta H7 ou le Arduino MKR Vidor 4000 etc). Un forum arduino est donc aussi pour discuter de trucs plus complexes, il faut juste essayer de s'adapter à la demande / au post en cours. Ici Jacques se dit débutant, c'est pour cela que j'avais choisi de ne pas prendre de Classe par exemple et de rester au niveau fonctions + struct / tableaux.
Ensuite vous ne pouvez pas demander à quelqu’un qui sait programmer de "coder avec les pieds" juste parce que c’est arduino. Je vois cela dans l’autre sens, c’est OK de lire du code qu’on trouverait pas top, c’est pas grave du moment que ca fonctionne et répond au cahier des charges / besoin (par exemple je n’ai pas relevé votre usage de String au lieu d’un const char * parce que même si c’est sous optimal au niveau mémoire ça rentre sans souci sur une MEGA et pour ce genre d’usage il n’y aura pas de morcellement. String est plus facilement compréhensible et manipulable par les débutants, même si c'est pas une super idée sur petit micro-controleur de faire de l'allocation dynamique. Mais vous ne me verrez pas en utiliser pour ce type de code)
enfin il y a la réalité. jouer avec des courants, des tensions (y compris souvent des mélanges de 3.3V et 5V) et des composants électroniques requiert un minimum d'exploration et d'acquisition de compétences en électronique de base (mettre une résistance de limitation de courant sur les LEDs) et en programmation en C ou C++. L'idée est d'y aller à son rythme, mais si on veut faire des projets ambitieux on ne peut pas se contenter de bidouiller à mon avis.
Bonjour Jacques
Une explication ici (traduction) et un peu ici.
PS:J'ai presque terminé, pour le sport, la version multi boutons avec bibliothèque JC_Button, si tu est intéressé?
Cordialement
jpbbricole
L'expérience est la seule chose qu'il ne faut acheter que d'occasion!
Bonjour
En effet, c'est concis! Ce qui est dans int main(), pour moi c'est du chinois!
Question: avec les enum Switch et Railway, qu'arrive-t-il si l'ont doit, pour des raisons techniques changer un port de place ou que les ports ne sont pas en suivant?
Cordialement
jpbbricole
L'expérience est la seule chose qu'il ne faut acheter que d'occasion!
Salut,
Il n'y a rien dans le main().
Juste std::cout qui est l'équivalent d'un print() et un range-for loop (C++11...) qui protège de potentielles erreurs d'indexation. C'est tout.
https://fr.cppreference.com/w/cpp/language/range-for
https://en.cppreference.com/w/cpp/language/range-for
Pour l’énumération, ce n'est que des constantes. Tu définis une valeur là où les numérateurs ne se suivent plus:
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 enum Switch : uint8_t {C1V1= 5, C1V2, C2V1=9, C2V2, C2V3, D3V3=C1V2, }; est équivalent à enum Switch : uint8_t {C1V1= 5, C1V2=6, C2V1=9, C2V2=10, C2V3=11, D3V3=6, };
dans un enum vous pouvez donnez des valeurs à certains mots clé et ça démarre la numérotation à cet endroit. par exemple vous pouvez faire celaEnvoyé par jpbbricole;11621241
Question: avec les enum [B
les premiers auront comme valeur 22,23 et 24 ensuite on passe à 34,35,36 puis 42,43,44
Code : Sélectionner tout - Visualiser dans une fenêtre à part enum Railway: uint8_t {G1D= 22, A1G, A1D, A2G=34, A2D, A3G, A3D=42, A4G, A4D, };
son code dans main() est le suivant:Ce qui est dans int main(), pour moi c'est du chinois!la forme for (const auto& rs: rs_map) c'est ce qu'on appelle un 'Range-based for loop'. Pour faire simple vous dites je veux une variable rs dont le type sera défini automatiquement en fonction de ce qui se trouve dans le tableau rs_map (type Railways_switch) et cette variable va parcourir tout le tableau. On passe donc le tableau en revue sans s'embêter avec des indices.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6 for (const auto& rs: rs_map) { std::cout<< "boutton: "<< rs.button << '\n'; for (const auto& way: rs.ways) if (way) std::cout<< " voie: "<< way<< '\n'; }
Voici un petit exemple pour tester
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 const char * liste[] = {"P1", "P2", "P3", "P4"}; void setup() { Serial.begin(115200); for (const auto& v : liste) Serial.println(v); // la variable v va parcourir la liste. Son type sera const char * puisque c'est ce qui est dans le tableau } void loop() {}
donc rs est une structure de type Railways_switchet donc possède un attribut button et un tableau ways de Railway.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 struct Railways_switch { Button button; Railway ways[max_handled_railways_per_switch]; };
les << est en C++ un opérateur qui sert à différentes choses, ici comme on l'applique sur un stream (un flux - la sortie standard std::cout = l'écran) . c'est ce qu'on appelle l'insertion operator (et on peut les enchaîner car ça retourne le flux)
donc quand on écrit dans la première boucleon écrit pour chaque élément du tableau sur l'écran le texte "boutton:" suivi de l'attribut button de la variable rs suivi d'un passage à la ligne.
Code : Sélectionner tout - Visualiser dans une fenêtre à part std::cout<< "boutton: "<< rs.button << '\n';
Sur un Arduino on aurait faitEnsuite elle fait un autre "Range-based for loop" pour parcourir le tableau des ways associés à rs. avec une variable automatique qui s'appelle way
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 Serial.print("boutton"); Serial.println(rs.button);Comme le tableau est une variable globale à qui on a donné une taille fixe, quand on le remplit à la main les valeurs se mettent à la suite les unes des autres, mais si on ne met pas assez de valeurs alors le compilateur va mettre des 0 dans les autres cases. C'est pour cela qu'elle teste
Code : Sélectionner tout - Visualiser dans une fenêtre à part for (const auto& way: rs.ways)ça veut dire si la case a été remplie alors j'affiche le N° sinon c'est que ce n'était pas une case utilisée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part if (way)...
C'est pour cela que j'ai fait la remarque que l'on ne pouvait pas utiliser la pin 0. Dans mon code j'avais définicar je ne connais pas d'Arduino avec une pin N° 255 donc c'est une meilleure valeur pour dire qu'on n'utilise pas cette entrée, mais c'est plus verbeux car il faut l'écrire pour chaque entrée.
Code : Sélectionner tout - Visualiser dans une fenêtre à part const byte entreeInutile = 255;
ça aide ?
Bonjour kaitlyn
Si on reprend cet exemple qui reprend les paramètres de cette discussion, en l'occurrence une liste de ports qui se suivent, l'enum fonctionne. Si je dois changer un port pour une raison technique, d'après ton explication je dois changer la valeur dans l'enum comme
C1V2, C2V1=39, C2V2.
Qui donne
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 enum Switch : uint8_t {C1V1= 5, C1V2, C2V1, C2V2, C2V3, D3V3, }; enum SwitchB : uint8_t {C1V1B= 5, C1V2B, C2V1B=39, C2V2B, C2V3B, D3V3B, }; void setup() { Serial.begin(115200); Serial.println("Switch"); Serial.println("C1V1 = \t" + String(C1V1)); Serial.println("C1V2 = \t" + String(C1V2)); Serial.println("C2V1 = \t" + String(C2V1)); Serial.println("C2V2 = \t" + String(C2V2)); Serial.println("C2V3 = \t" + String(C2V3)); Serial.println("D3V3 = \t" + String(D3V3)); Serial.println("\nSwitchB"); Serial.println("C1V1B = \t" + String(C1V1B)); Serial.println("C1V2B = \t" + String(C1V2B)); Serial.println("C2V1B = \t" + String(C2V1B)); Serial.println("C2V2B = \t" + String(C2V2B)); Serial.println("C2V3B = \t" + String(C2V3B)); Serial.println("D3V3B = \t" + String(D3V3B)); } void loop() { }
Le problème est que tout le reste est décalé depuis 39+1!!!!
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 Switch C1V1 = 5 C1V2 = 6 C2V1 = 7 C2V2 = 8 C2V3 = 9 D3V3 = 10 SwitchB C1V1B = 5 C1V2B = 6 C2V1B = 39 C2V2B = 40 C2V3B = 41 D3V3B = 42
Tu ne trouves pas que cela fait un peu château de cartes!!!
Je pourrais faire un C2V2=8, quelle gymnastique!!! Le simple tableau est nettement plus aisé et plus souple d'emploi?
Ne pas oublier qu'on est dans un forum où une grande partie des lecteurs/acteurs sont des débutants.
Jay M, que je remercie pour sa patience, a mis 30 ou 40 lignes, pour expliquer ce rien! Mais c'est un peu trop pour mes vieux neurones, merci quand même.
Ca sous entend que ceux qui ne font "que de l'Arduino" codent avec les pieds, je ne comprends pas la signification!
Je pense que quelqu'un qui sait vraiment programmer sait, aussi, se mettre à la hauteur de ceux qui débutent, ce qui est très souvent le cas dans ce forum.
Cordialement
jpbbricole
L'expérience est la seule chose qu'il ne faut acheter que d'occasion!
J'essaye en plus court:
les << ne sont pas super utilisés sur Arduino mais si vous lisez les exemples de la bibliothèque SDFat, l'auteur aime bien. donc c'est bien de savoir que ce n'est pas que du bit shifting, ça peut vouloir dire print()
le 'Range-based for loop' c'est pour avoir une variable qui parcourt un tableau sans avoir à gérer un indice ni se demander combien d'éléments sont dans le tableau
je pense que ce petit exemple illustre le principeavec un indice on écrirait
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 const char * liste[] = {"P1", "P2", "P3", "P4"}; void setup() { Serial.begin(115200); for (const auto& v : liste) Serial.println(v); // la variable v va parcourir la liste. Son type sera const char * puisque c'est ce qui est dans le tableau } void loop() {}pour mon indice j'ai dû indiquer qu'il y avait 4 valeurs à traiter.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 const char * liste[] = {"P1", "P2", "P3", "P4"}; void setup() { Serial.begin(115200); for (byte i=0; i < 4; i++) Serial.println(liste[i]); } void loop() {}
le 'Range-based for loop' permet d'être un peu plus compact donc, on laisse le boulot au compilateur pour savoir quel est le type de la variable à utiliser et combien d'éléments il y a dans le tableau.
Bonjour,
Si je comprends bien ce ne sont pas des moteurs rotatifs mais des barres aimantées glissant dans un solénoïde dans un sens ou l'autre selon le sens du courant. Une extrémité solidaire de l'aiguillage le commande directement. C'est simple et efficace.
Comment sont ils commandés ? Par un pont en H en circuit intégré ?
Salutations
Ever tried. Ever failed. No matter. Try Again. Fail again. Fail better. (Samuel Beckett)
Bonjour jpbbricole,
L'illustration montrait le mode de fonctionnement de l'énumération, c'est-à-dire qu'un énumérateur a pour valeur celle du précédent + 1, et si le premier n'est pas explicitement initialisé, sa valeur sera de 0.
À partir de là, peuvent se présenter 3 cas possibles, normalisés sous forme de conventions de codage.
1: L'énumération est une suite (de +1) et elle commence à 0.
On laisse le compilateur faire l'initialisation.
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2 enum Etage {RDC, PREMIER, DEUXIEME, TROISIEME, QUATRIEME, DERNIER}; enum {OUVERT, FERME};
2: L'énumération est une suite (de +1) mais ne commence pas par 0.
On initialise manuellement le premier énumérateur, le compilateur fera le reste.
3: L'énumération nest pas complètement une suite.
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part enum Jour {LUNDI= 1, MARDI, MERCREDI, JEUDI, VENDREDI, SAMEDI, DIMANCHE};
On initialise explicitement tous les énumérateurs.
Code C++ : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 enum Capteur { TEMPERATURE = 7, VITESSE = 8, PRESENCE = 32, PRESSION = 9, LUMIERE = 10, NIVEAU = 42, }
L'énumération n'a pas pour objectif de remplacer le tableau, c'est un autre genre d'outil, ou plutôt l'énumération est un set d'outils car elle a de nombreuses applications possibles. Et quand elle est bien utilisée, elle peut apporter de la clarté et de la robustesse au code. Essaie d'en apprendre d'avantage à son sujet, tu décideras après si oui ou non elle a sa place dans ta caisse à outils.
Pour terminer, il faut savoir que je ne code pratiquement jamais. Là j'ai eu une occasion de m'exercer un peu, et je me suis contrainte à produire quelque chose d'accessible, dans le sens où tant qu'à le faire, si ça peut être utile, c'est mieux. L'accessibilité se jauge avec le niveau mais aussi la volonté, de ce point de vue, si tu fais abstraction des std::cout (car édition en ligne avec les moyens du bord) et du gestionnaire de bouton factice class Button, le reste ne t'est pas insurmontable. Aussi, le deuxième code apportait une réponse à ton interrogation sur l'intégration d'un objet dans un tableau.
Ainsi mes messages ne sont pas forcément destinés à l'auteur du sujet, parfois c'est plus une piste de réflexion, et en toute modestie, pour les intervenants. Le reste n'est qu'une question de choix, et de ce côté là je respecte chacun.
Désolée d'avoir semé le trouble dans votre discussion
un 4ème cas pour être un peu plus précis: on n'est pas obligé de donner une valeur à tous les éléments, la règle du +1 par rapport au précédent s'applique alors pour les éléments non initialisés
si on fait tourner celale moniteur série dira
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13 enum : byte {a = 3, b, c, d = 22, e, f}; void setup() { Serial.begin(115200); Serial.println(a); Serial.println(b); Serial.println(c); Serial.println(d); Serial.println(e); Serial.println(f); } void loop() {}
3
4
5
22
23
24
On voit que b et c ont pris les valeurs suivant celle donnée à a (3) alors que e et f ont pris les valeurs suivant celle donnée à d (22)
à noter que l'on peut aussi utiliser les éléments précédents dans des calculs pour définir une nouvelle valeur. Par exemple on peut écrire
Code : Sélectionner tout - Visualiser dans une fenêtre à part enum : byte {a = 3, b, c, d = b+c, e, f};
Salut,
Non, il n'y a pas de 4ème cas.
Le bout de code que tu exposes, jpbbricole le connaît déjà et l'a expérimenté, Cf son message précédent. D'ailleurs il l'y qualifie judicieusement de <<gymnastique>>, et en ce sens il n'avait pas tort. Ce que j'ai conforté et souligné en parlant de normes et de conventions, comprendre par là des standards institutionnels qui interdisent effectivement cette pratique, car elle est source d'erreurs. Donc il y a bien 3 cas, + une exception que je n'avais pas estimée utile d'aborder au moment de ma réponse.
Ça reste une 4ème possibilité techniquement dans la spécification du langage.cetait mon point et toujours bon de savoir que ça existe.
Les meilleurs pratiques sont souvent à géométrie variable. Merci de donner un lien vers vos standards institutionnels...
(même si j'y souscris sur le fond, la possibilité offerte par cette capacité peut rendre service spécifiquement quand on travaille sur petit micro-controlleurs avec peu de mémoire et ou parfois il faut faire de la gymnastique pour que ça rentre).
Être vieux, c'est être jeune depuis plus longtemps que les autres !
Bonjour Jacques
Ah!!! avoir remis le doigt de l'engrenage du train et de la programmation!!!, la dernière fois doit dater de plus de 30 ans!. Il faut dire que c'est super ce que l'on peut faire avec ces Arduino, entre autre.
Je te "présente" la version multi-boutons, bibliothèque JC_Button.h. Cette version gère, également, les LED.
Avec 8 boutons et 9 auguilles ça fait 8 + (9x4) = 44 entrées. Il ne reste plus beaucoup de place pour une extension, il faudra, rapidement, penser à multiplexer avec des MCP23017, les entrée comme je suggère au post #11. Ceci pourra être assez facilement implémenté plus tard si nécessaire.
Dans cette version, j'ai quelque peu remanié les structures aiguilles et boutons poussoir, pour aider aux développements futur comme l'allumage des secteurs entre 2 aiguilles ou le blocage d'un secteur si l'aiguille n'est pas en position. Les commandes des aiguilles ou des boutons (comme dans gareInitialisation()) se fait, dorénavent en invoquant le nom de l'objet, par exemple bpCommande("C2_V1"); ou aigCommande("B1_G");.
Ainsi, dans le futur, on pourra envoyer des commandes depuis la ligne de commande du moniteur série de l'IDE Arduino ou depuis un émulateur série, mais, là, je m'égare.
Pour adapter le programme à ta configuration, les points importants sont:
Le nombre d'aiguilles (aigNombreMax) et le nombre de boutons (bpNombreMax), se calculent automatiquement en fonction du nombre d'éléments dans leur tableau respectif.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4 #define aigMotEtatOn HIGH // Etat pour moteur ON #define aigMotEtatOnTemps 50 // Moteur, temps de l'impulsiom ON const int aigLedEtatOn = LOW; // Etat du port pour allumer la LED
Le programme ARDDEV_AiguillagesBled.ino
J'ai, également travaillé le programme avec des LED Neopixel, c'est superbe! Le GROS avantage d'implémenter ces LED, c'est que ça n'utilises qu'un port sur ton Arduino quelque soit le nombre d'aiguilles, contre 18 actuellement, donc plus qu'un fil (+2 pour l'alim.) qui "court" sous ton pupitre.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307 /****************************************************************************** Name: Commande d'aiguillages et de leurs LED Created: 26.09.2020 Author: jpbbricole Remarques: Version avec LED '****************************************************************************** */ #include <JC_Button.h> // https://github.com/JChristensen/JC_Button //===================================== Aiguilles #define aigMotEtatOn HIGH // Etat pour moteur ON #define aigMotEtatOnTemps 50 // Moteur, temps de l'impulsiom ON enum aiguillesPositionIndex {aigPosGauche, aigPosDroite, aigPosNull}; // Pour indexer le tableau aiguilles[].motGDport[] String aigPosLabelSh[] ={"G", "D"}; const int aigLedEtatOn = LOW; // Etat du port pour allumer la LED //------------------------------------- Structure de l'objet aiguille struct aiguilleDefinition {String nom; byte position; int motGDport[2]; int ledGDport[2];}; aiguilleDefinition aiguilles[] = { // Position donne la position de l'aiguille au demarrage du programme //Nom, Position, Moteur G, Moteur D, Led G, LED D 255 = port inutilise {"G1", aigPosDroite, 255, 22, 255, 41}, {"A1", aigPosGauche, 23, 24, 42, 43}, {"A2", aigPosDroite, 25, 26, 44, 45}, {"A3", aigPosGauche, 27, 28, 46, 47}, {"A4", aigPosDroite, 29, 30, 48, 49}, {"B1", aigPosDroite, 31, 32, 50, 51}, {"B2", aigPosDroite, 33, 34, 52, 53}, {"B3", aigPosDroite, 35, 36, A8, A9}, {"B4", aigPosDroite, 37, 38, A10, A11} }; const int aigNombreMax = sizeof(aiguilles)/sizeof(aiguilles[0]); //------------------------------------- Structure de l'objet aiguille en utilisation struct aigInUseDef {int index; byte motPosition; String motPosLabel; String motPosLabelSh;}; aigInUseDef aigIu; // Aiguille en utilisation //===================================== Boutons #define bpMotNombreMax 4 // Nombre de moteurs max par bouton const boolean bpEtatPresseLOW = true; // Etat lu du bouton presse //------------------------------------- Structure de l'objet bouton d'aiguuille (bpAig) struct bpAigDefinition {String nom; byte port; boolean bpOn; String aig_Dir[bpMotNombreMax];}; /* remplissage de la structure des boutons bp[0] a bp[bpNombreMax-1] */ bpAigDefinition bpAig[] = { // Nom, Port, presse, aigCmd1, aigCmd2, aigCmd2, aigCmd2 {"C1_V1", 5, false, "G1_D", "A1_G", "A3_D", ""}, {"C1_V2", 6, false, "G1_D", "A1_D", "A4_D", ""}, {"C2_V1", 7, false, "B1_G", "B3_D", "A2_G", "A3_G"}, {"C2_V2", 8, false, "B1_G", "B3_D", "A2_D", "A4_G"}, {"C2_V3", 9, false, "B1_D", "B4_D", "", ""}, {"C3_V1", 10, false, "B2_G", "B3_G", "A2_G", "A3_G"}, {"C3_V2", 11, false, "B2_G", "B3_G", "A2_D", "A4_G"}, {"C3_V3", 12, false, "B2_G", "B4_G", "", ""} }; const int bpNombreMax = sizeof(bpAig)/sizeof(bpAig[0]); Button *bpRead[bpNombreMax]; // JC_Button.h void setup() { Serial.begin(115200); bpInitialisation(); aigInitialisation(); aigIu.index = -1; // Pas d'aiguille selectionnee gareInitialisation(); } void loop() { if (bpScanStatus()) // S'il y a un bouton presse { delay(250); // Attendre d'eventuelles autres bp bpScanStatus(); bpPressedAction(); } } //===================================== Aiguilles (aig) void aigInitialisation() { for (int aig = 0; aig < aigNombreMax; aig ++) { for (int gd = 0; gd < 2; gd ++) { // Initialisation des moteurs d'aiguilles pinMode(aiguilles[aig].motGDport[gd], OUTPUT); digitalWrite(aiguilles[aig].motGDport[gd], !aigMotEtatOn); // Moteur a l'arrêt // Initialisation des LED pinMode(aiguilles[aig].ledGDport[gd], OUTPUT); digitalWrite(aiguilles[aig].ledGDport[gd], !aigLedEtatOn); // LED eteinte } // Mise en position des aiguilles en fonction de aiguilles[x].position String initCmd = aiguilles[aig].nom + "_" + aigPosLabelSh[aiguilles[aig].position]; aigCommande(aiguilles[aig].nom + "_" + aigPosLabelSh[aiguilles[aig].position], false); } } /*------------------------------------- Commande d'aiguille G1_D A1_G A3_D 00_0 Äiguille G1 a droite Äiguille A1 a gauche Inutilise */ void aigCommande(String aigCmd, boolean aigCmdEcho) { aigCmdSelection(aigCmd); // Selection des parametres de l'aiguille en fonction de la commande // dans la structure aigIu (aiguille in use) if (aigIu.index != -1) // Si aiguille trouvee { aigMouvement(aigIu, aigCmdEcho); aigLedOnOff(aigIu, aigCmdEcho); } else { Serial.print(F("Commande; >> ")); Serial.print(aigCmd); Serial.println(F(" << Inconnue!!!")); } } /*------------------------------------- Index de l'aiguille Selectionne une aiguille en fonction de la commande aiguille_parametre G1 ou G1_D, recherche G1 dans le tableau aiguilles.nom[n] retourne true si trouvee et renseigne aigIu.index (-1 si pas trouvee) et aigIu.motPosition (aigPosGauche , aigPosDroite ou aigPosNull) */ void aigCmdSelection(String aigCmd) { String aigName = ""; String aigParam = ""; // Ce qui est apres le separateur _ aigIu.index = -1; aigCmd.toUpperCase(); // En majuscules byte sepPos = aigCmd.indexOf("_"); // Position du separateur _ if (sepPos) { aigName = aigCmd.substring(0, sepPos); // On retire le _ et le parametre pour garder le nom aigParam = aigCmd; aigParam.replace(aigName + "_", ""); // On retire le nom et _ pour garder le parametre } for (int aig = 0; aig < aigNombreMax; aig ++) // Recherche si l'aiguille existe { if (aiguilles[aig].nom == aigName) { aigIu.index = aig; break; } } if (aigParam == "G") { aigIu.motPosLabelSh = "G"; aigIu.motPosLabel = "Gauche"; aigIu.motPosition = aigPosGauche; } else if (aigParam == "D") { aigIu.motPosLabelSh = "D"; aigIu.motPosLabel = "Droite"; aigIu.motPosition = aigPosDroite; } else { aigIu.motPosition = aigPosNull;} } /*------------------------------------- Aiguille mouvement parametres dans structure aigIu */ void aigMouvement(aigInUseDef aigMouv, boolean echoCmd) { byte motAigPort = aiguilles[aigMouv.index].motGDport[aigMouv.motPosition]; digitalWrite(motAigPort, aigMotEtatOn); // Moteur ON delay(aigMotEtatOnTemps); digitalWrite(motAigPort, !aigMotEtatOn); // Moteur NOT ON delay(aigMotEtatOnTemps); if (echoCmd) { Serial.print(F("\tAiguille ")); Serial.println(aiguilles[aigMouv.index].nom + " " + aigMouv.motPosLabel); } } //------------------------------------- Aiguille led On/Off void aigLedOnOff(aigInUseDef aigMouv, boolean echoCmd) { int ledOnPort = aiguilles[aigIu.index].ledGDport[aigIu.motPosition]; // Led a allumer int ledOffPort = 0; if (aigIu.motPosition == aigPosDroite) // Quelle LED eteindre { ledOffPort = aiguilles[aigIu.index].ledGDport[aigPosGauche]; } else { ledOffPort = aiguilles[aigIu.index].ledGDport[aigPosDroite]; } digitalWrite(ledOnPort, aigLedEtatOn); // LED eteinte digitalWrite(ledOffPort, !aigLedEtatOn); // LED eteinte if (echoCmd) { Serial.print(F("\t\tLED ")); Serial.println(String(ledOnPort) + "\t On"); Serial.print(F("\t\tLED ")); Serial.println(String(ledOffPort) + "\t Off"); } } //===================================== Boutons poussoir (bp) void bpInitialisation() { //--------------------------------- Initialisation des bp for (int b = 0; b < bpNombreMax; b ++) { bpRead[b] = new Button(bpAig[b].port, 25, true, bpEtatPresseLOW); // Port Antirebonds PULL_UP actif a LOW bpRead[b]->begin(); } } /*------------------------------------- Commande de bp C1_V1 ou C2_V3.... le syntaxe se trouve dans la structure bpAig[bpIndex].nom */ void bpCommande(String bpCmd) { bpCmd.toUpperCase(); Serial.print(F("Commande bp ")); Serial.println(bpCmd); for (int b = 0; b < bpNombreMax; b ++) // Balayage des bp { if (bpAig[b].nom == bpCmd) // Si le nom du bp correspond { bpMotAction(b); } } } //------------------------------------- Lecture de l'etat des bp bool bpScanStatus() { boolean bpEvent = false; for (int b = 0; b < bpNombreMax; b ++) // Balayage des bp { bpRead[b]->read(); if (bpRead[b]->wasPressed()) { bpAig[b].bpOn = true; bpEvent = true; } } return bpEvent; } //------------------------------------- Si bp est presse, action void bpPressedAction() { Serial.println(F("\t>>> Aiguillage <<<")); for (int b = 0; b < bpNombreMax; b ++) // Lister les boutons presses { if (bpAig[b].bpOn) // Si ce bouton est presse { Serial.println(bpAig[b].nom); bpMotAction(b); bpAig[b].bpOn = false; // tache bp b terminee } } Serial.println(""); } //------------------------------------- Mise en action des aiguilles/moteur du bouton void bpMotAction(int bpIndex) { for (int mot = 0; mot < bpMotNombreMax; mot ++) // Lister les commandes d'aiguilles concernes { if (bpAig[bpIndex].aig_Dir[mot] != "") { aigCommande(bpAig[bpIndex].aig_Dir[mot], true); // Encoi de la commande d'aiguillage } } } //===================================== Divers //------------------------------------- Initialisation de la gare void gareInitialisation() { Serial.println(F("\n\t>>> Initialisation de la gare <<<")); bpCommande("C2_V1"); bpCommande("C2_V2"); bpCommande("C2_V3"); Serial.println(F("")); }
J'ai comme l'impression de prendre ton développement à mon compte!!, si tu en as marre de mes élucubrations ou tu trouves que je vais trop loin, ne te gène pas de me le faire savoir.
A ta disposition
Cordialement
jpbbricole
L'expérience est la seule chose qu'il ne faut acheter que d'occasion!
Vous avez un bloqueur de publicités installé.
Le Club Developpez.com n'affiche que des publicités IT, discrètes et non intrusives.
Afin que nous puissions continuer à vous fournir gratuitement du contenu de qualité, merci de nous soutenir en désactivant votre bloqueur de publicités sur Developpez.com.
Partager