Vous êtes sur la page 1sur 10

1 //ToDo: See if necessary to reset when MySensors gateway resets and node is

previously active
2 //////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
3 //
4 // This Ce sketch contrôle jusqu'à 4 stores dans le même Arduino Nano (et similaire)
via des interrupteurs momentanés et la radio nRF24.
5 // Les stores se déplacent vers le haut ou vers le bas d'un simple clic et peuvent
s'arrêter à n'importe quelle position en appuyant ou en envoyant à nouveau une
commande au même store.
6 // Les interrupteurs sont désactivés par logiciel.
7 // Les interrupteurs sont désactivés par logiciel. Aucun filtrage matériel
supplémentaire n'est nécessaire !
8 // Les relais sont désactivés après le délai d'activation (ACTIVATION_TIME) pour
éviter l'activation permanente des relais et les câbles sous tension dans les moteurs.
9 //
10 // Le matériel est fait juste avec les cartes chinoises bon marché typiques de triacs
et de relais et très peu d'électronique,
11 // et il peut gérer sans problème des moteurs de stores de 150 W (et même plus, mais
pas testé).
12 // L'ensemble du système coûte moins de 20€ pour les quatre stores, sans compter les
moteurs, bien sûr.
13 // Pour la configuration matérielle, contactez-moi si vous n'avez pas trouvé ce
croquis accompagné de sa description. Vous pouvez trouver le tutoriel
14 // à https://www.hackster.io/gomecin/blinds-or-any-ac-power-motor-control-27f633
15 //
16 // La communication radio sert à contrôler les stores depuis un contrôleur, dans mon
cas j'utilise Domoticz dans un Raspberry Pi.
17 // Le sketch est préparé pour fonctionner avec ou sans MySensors, il suffit de
décommenter une ligne.
18 // Avec les MySensors, cela fonctionne bien et une fois que vous avez une passerelle
MySensors fonctionnelle, c'est sans doute la meilleure option. Attention ! Ne
mélangez pas les deux systèmes, car le module radio
19 // module change la configuration de la radio et la passerelle cesse de fonctionner.
20 // Sans les MySensors, l'implémentation est très simple, elle reçoit simplement la
commande comme décrit ci-dessous, sans retour ni accusé de réception nécessaire.
21 // Elle utilise une commande console avec le nombre de stores et son action. Il
accuse réception de la commande, mais je n'utilise pas la confirmation et il n'envoie
pas le statut actuel comme vous pourriez le faire.
22 // Il n'envoie pas non plus l'état actuel comme vous pourriez le faire avec les
MySensors. Je me contente de croire que les stores s'activeront, et ils le font
toujours.)
23 // Vous pouvez envoyer la commande avec les instructions suivantes
http://hack.lenotta.com/arduino-raspberry-pi-switching-light-with-nrf24l01/
24 // Lisez-le attentivement et à la fin, il vous suffit d'exécuter la commande
"./remote -m [#blind][action]" pour faire bouger vos stores. Cela peut être
25 // délicat de le faire fonctionner, car vous devez compiler le code et configurer
correctement la radio, mais le résultat simple en vaut la peine.
26 //
27 // Détails de l'implémentation utilisant"remote":
28 // [#blind]:
29 // Les stores du rez-de-chaussée sont 0, 1, 2 y 3. Premier étage 4, 5, 6 y 7.
30 // 10 actionne tous les stores du rez-de-chaussée
31 // 20 actionne tous les stores du premier étage
32 // 30 actionne tous les stores
33 //
34 // [action]:
35 // 0: up
36 // 1: down
37 //
38 // 80 évite l'actionnement des stores, à la fois par radio et par bouton (je
l'utilise pour fermer tous les stores en cas d'intrusion et éviter de les rouvrir)
39 // 81 permet d'actionner le store, à la fois par radio et par bouton.
40 //
41 // Examples in Domoticz:
42 // script:///[REMOTE_PATH]/remote -m 21 --> descente du store au rez-de-chaussée
43 // script:///[REMOTE_PATH]/remote -m 80 --> désactive tous les stores
44 //
45 // Author: danielgomeztomas@gmail.com
46 // 24/03/2022
47 // Version:1.8
48 //
49 //////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////
50
51 /************************/
52 /* CONFIGURATION */
53 /************************/
54
55 //Commentez les lignes appropriées pour le compiler comme les stores du premier
étage, la cuisine ou le rez-de-chaussée.
56 //#define PERSIANAS_PLANTA_BAJA
57 //#define PERSIANAS_COCINA
58 #define PERSIANAS_PLANTA_1
59
60 //Commenter la ligne suivante si MySensors n'est pas utilisé
61 #define MY_SENSORS //Il s'agit d'utiliser la bibliothèque MySensors
62
63 #ifdef PERSIANAS_PLANTA_BAJA
64 #define NUMBER_OF_COVERS 3 //Les broches sont toujours configurées pour 4 stores,
mais MySensors ne présentera que le nombre spécifié ici.
65 #define SKETCH "Persianas planta baja"
66 #define MY_NODE_ID 1
67 #else
68 #ifdef PERSIANAS_COCINA
69 #define NUMBER_OF_COVERS 1
70 #define SKETCH "Persianas cocina"
71 #define MY_NODE_ID 2
72 #else
73 #define NUMBER_OF_COVERS 4
74 #define SKETCH "Persianas primera planta"
75 #define MY_NODE_ID 3
76 #endif
77 #endif
78
79 #ifdef MY_SENSORS
80 //#define MY_DEBUG
81 #define MY_REPEATER_FEATURE
82 //#define MY_TRANSPORT_SANITY_CHECK
83 #define MY_TRANSPORT_WAIT_READY_MS 5000 //Cela permet à l'esquisse de continuer
après x ms si aucune connexion à la
passerelle.

s if no gateway communication!
84 #define MY_RF24_PA_LEVEL RF24_PA_MAX
85 #define MY_RADIO_NRF24
86 #include <MySensors.h>
87 #else
88 #include <SPI.h>
89 //#include "nRF24L01.h"
90 #include "RF24.h"
91 #define V_UP 0 //Dans MySensors est équivalent à 29, 30, 31, juste pour info,
rien à changer. Ces constantes sont déjà définies dans MySensors.h.
92 #define V_DOWN 1
93 #define V_STOP 2
94 RF24 radio(9,10);
95 const uint64_t pipes[2] = { 0xF0F0F0F0E1LL, 0xF0F0F0F0D2LL };
96 #endif
97
98 #define VERSION "1.8"
99
100 /************************/
101 /* CONSTANTS */
102 /************************/
103
104 #define LED 13
105 #define COMMON 4
106 #define INPUT1 5
107 #define INPUT2 6
108 #define INPUT3 7
109 #define INPUT4 8
110 #define TRIAC1 A0
111 #define TRIAC2 A1
112 #define TRIAC3 A2
113 #define TRIAC4 A3
114 #define RELAY1 A4
115 #define RELAY2 A5
116 #define RELAY3 2
117 #define RELAY4 3
118
119 const unsigned long RELAY_CONMUTATION_TIME = 150;
120 const unsigned long TRIAC_TIME = 100;
121 const unsigned long DEBOUNCE_TIME = 120;
122 const unsigned long ACTIVATION_TIME = 30000; //ms. Le temps de finir l'action.
Doit être supérieur au temps que met le store le plus lent à s'ouvrir.
123 const unsigned long HEARTBEAT_TIME = 900000; //ms. Temps d'envoi des battements de
cœur à la passerelle MySensors
124
125 #define ENABLER 8
126 #define GROUND_FLOOR 10
127 #define FIRST_FLOOR 20
128 #define ALL 30
129
130 /*****************************/
131 /* IMPORTS & DEFINITIONS */
132 /*****************************/
133 #define EI_NOTINT0 //N'utilisez pas d'interruptions externes dans les broches 0
et 1, les bibliothèques EnableInterrupt et MySensors entrent en conflit.
134 #define EI_NOTINT1
135 #include <EnableInterrupt.h>
136 #include "Timer.h" //Timer-maître
http://srmonk.blogspot.com/2012/01/arduino-timer-library.html voir aussi
https://github.com/JChristensen/Timer
137 #include <avr/wdt.h>
138
139 Timer t;
140
141 static bool actionEnabled = true;
142 volatile uint8_t pinChangeInterruptFlag = 0;
143 static int idEventR1 = 0;
144 static int idEventR2 = 0;
145 static int idEventR3 = 0;
146 static int idEventR4 = 0;
147 static int idEventT1 = 0;
148 static int idEventT2 = 0;
149 static int idEventT3 = 0;
150 static int idEventT4 = 0;
151 unsigned long lastHeartbeatTime = 0;
152
153 /*********************/
154 /* FUNCTIONS */
155 /*********************/
156
157 bool my_debounce(unsigned long debounceTime) {
158 unsigned long now = millis();
159 while ((millis() - now) < debounceTime) {
160 //Si toutes les entrées sont hautes, alors stop, ce n'est pas une entrée valide.
161 if (digitalRead(INPUT1) and digitalRead(INPUT2) and digitalRead(INPUT3) and
digitalRead(INPUT4)) {
162 return false;
163 }
164 }
165 return true;
166 }
167
168 void my_blink(int times) {
169 while (times > 0) {
170 digitalWrite(LED, HIGH);
171 delay(250);
172 digitalWrite(LED, LOW);
173 delay(250);
174 times--;
175 }
176 }
177
178 uint32_t lastInterruptTime = 0;
179 #ifdef ARDUINO_328
180 void isr_handler() {
181 uint32_t interruptTime = millis();
182
183 if (interruptTime - lastInterruptTime > DEBOUNCE_TIME) {
184 pinChangeInterruptFlag=1;
185 }
186 lastInterruptTime = interruptTime;
187 }
188
189 void interruptFunction () {
190 pinChangeInterruptFlag=1;
191 }
192
193 #define disable_pc_interrupt(x) \
194 disableInterrupt( x | PINCHANGEINTERRUPT)
195
196 #define setup_interrupt(x) \
197 pinMode( x, INPUT_PULLUP); \
198 enableInterrupt( x, interruptFunction, FALLING)
199 #else
200 #error This sketch supports 328-based Arduinos only.
201 #endif
202
203 //Avec la définition suivante, il sera compilé dans une fonction par store avec les
variables
204 //globales adéquates comme arguments.
205 #define accionar_persiana(x, accion) \
206 if (actionEnabled) accionar(x, accion, TRIAC ##x, RELAY ##x, idEventT ##x, idEventR
##x)
207 //Si la commande arrive par le biais d'un bouton ou d'un script à distance, elle
s'arrêtera si elle se déplaçait précédemment,
208 //quelle que soit la direction.
209 void accionar(uint8_t id, uint8_t action, byte triac, byte relay, int &idEventT, int &
idEventR) {
210 //Les relais sont activés en position basse, les triacs en position haute.
211 //S'il était déjà actif, le désactiver et ne plus rien faire.
212 if (digitalRead(triac) or !digitalRead(relay) or (action == V_STOP))
213 {
214 digitalWrite(triac, LOW);
215 if (!digitalRead(relay)) {
216 //wait is from MySensors
217 wait(TRIAC_TIME);
218 //delay(TRIAC_TIME);
219 digitalWrite(relay, HIGH);
220 }
221 t.stop(idEventR);
222 idEventR = 0;
223 t.stop(idEventT);
224 idEventT = 0;
225
226 #ifdef MY_SENSORS
227 MyMessage msg(id, V_STOP);
228 send(msg);
229 #endif
230 } else {
231 if (action == V_DOWN) {
232 idEventR = t.pulseImmediate(relay, ACTIVATION_TIME + RELAY_CONMUTATION_TIME +
TRIAC_TIME, LOW);
233 wait(RELAY_CONMUTATION_TIME);
234 //delay(RELAY_CONMUTATION_TIME);
235
236 #ifdef MY_SENSORS
237 MyMessage msg(id, V_DOWN);
238 send(msg);
239 } else {
240 MyMessage msg(id, V_UP);
241 send(msg);
242 #endif
243 }
244 idEventT = t.pulseImmediate(triac, ACTIVATION_TIME, HIGH);
245 }
246 }
247
248 //En utilisant MySensors, nous distinguons si la commande provient du bouton ou de la
radio.
249 #ifdef MY_SENSORS
250 #define accionar_persiana_my_sensors(x, accion) \
251 if (actionEnabled) accionar_my_sensors(x, accion, TRIAC ##x, RELAY ##x, idEventT
##x, idEventR ##x)
252 //S'il vient par radio, pour l'arrêter il faut explicitement la commande V_STOP,
253 //sinon il continue l'action ou l'inverse en conséquence.
254 void accionar_my_sensors(uint8_t id, uint8_t action, byte triac, byte relay, int &
idEventT, int &idEventR) {
255 //Les relais sont activés en position basse, les triacs en position haute.
256 if (action == V_STOP) {
257 digitalWrite(triac, LOW);
258 if (!digitalRead(relay)) {
259 wait(TRIAC_TIME);
260 digitalWrite(relay, HIGH);
261 }
262 t.stop(idEventR);
263 idEventR = 0;
264 t.stop(idEventT);
265 idEventT = 0;
266 MyMessage msg(id, V_STOP);
267 send(msg);
268 } else {
269 if (action == V_DOWN) {
270 if (!digitalRead(triac) and digitalRead(relay)) { //Le précédent
store est attêté
271 idEventR = t.pulseImmediate(relay, ACTIVATION_TIME + RELAY_CONMUTATION_TIME +
TRIAC_TIME, LOW);
272 wait(RELAY_CONMUTATION_TIME);
273 } else if (digitalRead(triac) and digitalRead(relay)) { //Les stores qui
montaient auparavant
274 digitalWrite(triac, LOW);
275 t.stop(idEventR);
276 idEventR = 0;
277 t.stop(idEventT);
278 idEventT = 0;
279 wait(2000); //Puisque le moteur
va changer de direction, attendons 2 s.
280 idEventR = t.pulseImmediate(relay, ACTIVATION_TIME + RELAY_CONMUTATION_TIME +
TRIAC_TIME, LOW);
281 wait(RELAY_CONMUTATION_TIME);
282 } else if (digitalRead(triac) and !digitalRead(relay)) { //Puisque le moteur
va changer de direction, attendons 2 s.
283 //Ne rien faire, c'est déjà dans la bonne direction.
284 }
285 MyMessage msg(id, V_DOWN);
286 send(msg);
287 } else if (action == V_UP) {
288 if (!digitalRead(triac) and digitalRead(relay)) { //Store
précédemment arrêté
289 //Do nothing, later the triac will be activated anyway
290 } else if (digitalRead(triac) and digitalRead(relay)) { //Stores qui
montaient auparavant
291 //Do nothing, it's already going in the right direction
292 } else if (digitalRead(triac) and !digitalRead(relay)) { //store
précédemment descendu
293 digitalWrite(triac, LOW);
294 wait(TRIAC_TIME);
295 digitalWrite(relay, HIGH);
296 t.stop(idEventR);
297 idEventR = 0;
298 t.stop(idEventT);
299 idEventT = 0;
300 wait(2000); //Puisque le moteur
va changer de direction, attendons 2 s.
301 }
302 MyMessage msg(id, V_UP);
303 send(msg);
304 }
305 idEventT = t.pulseImmediate(triac, ACTIVATION_TIME, HIGH); //Enfin, activez le
triac
306 }
307 }
308 #endif
309
310 #ifndef MY_SENSORS
311 char * convert_number_into_array(unsigned short number, unsigned short length) {

312 char * arr = (char *) malloc(length * sizeof(char)), * curr = arr;


313 do {
314 *curr++ = number % 10;
315 number /= 10;
316 } while (number != 0);
317 return arr;
318 }
319
320 unsigned short get_id(char * rawMessage, unsigned short length) {
321 unsigned short i = 0;
322 unsigned short id = 0;
323 for( i=1; i< length; i++) {
324 id += rawMessage[i]*pow( 10, i-1 );
325 }
326 return id;
327 }
328
329 unsigned short get_message( char * rawMessage) {
330 unsigned short message = rawMessage[0];
331 return (unsigned short)message;
332 }
333
334 unsigned short get_length( unsigned int rawMessage) {
335 unsigned short length = (unsigned short)(log10((float)rawMessage)) + 1;
336 return length;
337 }
338
339 void send_callback(unsigned short callback) {
340 // D'abord, arrêtez d'écouter pour que nous puissions parler
341 radio.stopListening();
342 // Renvoyez le dernier.
343 radio.write( &callback, sizeof(callback) );
344 // NReprenez l'écoute pour attraper les prochains paquets..
345 radio.startListening();
346 }
347
348 //Action provenant d'un script distant
349 //rawMessage doit avoir la forme <blind number><action>.
350 void perform_action(unsigned short rawMessage) {
351 unsigned short accion, persiana, length, callback;
352 char * castedMessage;
353
354 length = get_length(rawMessage);
355 castedMessage = convert_number_into_array(rawMessage, length);
356 accion = get_message(castedMessage);
357 persiana = get_id(castedMessage, length);
358
359 switch (persiana) {
360 #ifdef PERSIANAS_COCINA
361 case 0:
362 accionar_persiana(4, accion); //Cuisine
363 break;
364 case GROUND_FLOOR:
365 accionar_persiana(4, accion); //Cuisine
366 break;
367 #else
368 #ifdef PERSIANAS_PLANTA_BAJA
369 case 1:
370 accionar_persiana(1, accion); //Le salon
371 break;
372 case 2:
373 accionar_persiana(2, accion); //Le salon
374 break;
375 case 3:
376 accionar_persiana(3, accion); //Le salon
377 break;
378 case GROUND_FLOOR: //RDC_ÉTAGE = 10
379 accionar_persiana(1, accion);
380 accionar_persiana(2, accion);
381 accionar_persiana(3, accion);
382 accionar_persiana(4, accion);
383 break;
384 #else
385 case 4:
386 accionar_persiana(1, accion); //Parents
387 break;
388 case 5:
389 accionar_persiana(2, accion); //Invités
390 break;
391 case 6:
392 accionar_persiana(3, accion); //Enfant 1
393 break;
394 case 7:
395 accionar_persiana(4, accion); //Enfant 2
396 break;
397 case FIRST_FLOOR: // PREMIER_ÉTAGE = 20
398 accionar_persiana(1, accion);
399 accionar_persiana(2, accion);
400 accionar_persiana(3, accion);
401 accionar_persiana(4, accion);
402 break;
403 #endif
404 #endif
405
406 case ENABLER: // ENABLER = 8
407 actionEnabled = (bool)accion; // activer/désactiver les stores
408 break;
409 case ALL: // TOUT = 30
410 accionar_persiana(1, accion);
411 accionar_persiana(2, accion);
412 accionar_persiana(3, accion);
413 accionar_persiana(4, accion);
414 default:
415 break;
416 }
417 send_callback(accion);
418 }
419 #endif
420
421 #ifdef MY_SENSORS
422 void receive(const MyMessage &message) {
423 if (actionEnabled || (message.sensor == ENABLER)) {
424 //Définition de MySensors S_COVER
425 //S_COVER 5 Couvre-fenêtres ou stores V_UP, V_DOWN, V_STOP, V_PERCENTAGE
426 //En 2017, Domoticz n'avait pas correctement implémenté V_PERCENTAGE
427 switch (message.sensor) {
428 case ENABLER: // ENABLER = 8
429 actionEnabled = !(bool)message.getBool(); // activer/désactiver les
stores
430 break;
431 case 1:
432 accionar_persiana_my_sensors(1, message.type);
433 break;
434 case 2:
435 accionar_persiana_my_sensors(2, message.type);
436 break;
437 case 3:
438 accionar_persiana_my_sensors(3, message.type);
439 break;
440 case 4:
441 accionar_persiana_my_sensors(4, message.type);
442 break;
443 default:
444 break;
445 }
446 }
447 }
448 #endif
449
450 /*******************/
451 /* SETUP */
452 /*******************/
453
454 //La configuration dépendra de MySensors, si elle est définie, une partie de la
configuration doit être dans la fonction avant ()
455 #ifdef MY_SENSORS
456 void before() {
457 #else
458 void setup() {
459 #endif
460 wdt_disable();
461 pinMode(COMMON, INPUT_PULLUP);
462 pinMode(TRIAC1, OUTPUT);
463 pinMode(TRIAC2, OUTPUT);
464 pinMode(TRIAC3, OUTPUT);
465 pinMode(TRIAC4, OUTPUT);
466 pinMode(RELAY1, OUTPUT);
467 pinMode(RELAY2, OUTPUT);
468 pinMode(RELAY3, OUTPUT);
469 pinMode(RELAY4, OUTPUT);
470 digitalWrite(RELAY1, HIGH);
471 digitalWrite(RELAY2, HIGH);
472 digitalWrite(RELAY3, HIGH);
473 digitalWrite(RELAY4, HIGH);
474 digitalWrite(TRIAC1, LOW);
475 digitalWrite(TRIAC2, LOW);
476 digitalWrite(TRIAC3, LOW);
477 digitalWrite(TRIAC4, LOW);
478 //3 LED clignotent juste pour vérifier que l'Arduino démarre
479 pinMode(LED, OUTPUT);
480 my_blink(3);
481 #ifdef MY_SENSORS
482 }
483
484 void setup() {
485 #else
486 /*------------------*/
487 /* Radio setup! */ //Il doit correspondre à la configuration de
votre expéditeur !!
488 /*------------------*/
489 radio.begin();
490 //radio.setAutoAck(1); // AutoACK n'a pas besoin d'être activé
491 radio.setRetries(15,15);
492 radio.setChannel(0x70);
493 radio.setDataRate(RF24_250KBPS);
494 radio.setPALevel(RF24_PA_MAX);
495 radio.openWritingPipe(pipes[1]);
496 radio.openReadingPipe(1,pipes[0]);
497 radio.startListening();
498 radio.printDetails();
499 #endif
500
501 //Attention, si vous utilisez les broches 2 ou 3 comme entrées, elles devront
peut-être être ExInterrupt et les broches 0 et 1 sont occupées si elles sont
utilisées pour la série
502 setup_interrupt(INPUT1);
503 setup_interrupt(INPUT2);
504 setup_interrupt(INPUT3);
505 setup_interrupt(INPUT4);
506 wdt_enable(WDTO_2S);
507 }
508
509 //MySensors doit également présenter les capteurs
510 #ifdef MY_SENSORS
511 void presentation() {
512 //Envoyer les informations de version d'esquisse à la passerelle et au contrôleur
513 sendSketchInfo(SKETCH, VERSION);
514 #ifdef PERSIANAS_COCINA
515 present(4, S_COVER); //La cuisine est connectée comme le 4ème store. Je ne
veux pas du Enabler ici
516 #else
517 for (int sensorId=1; sensorId<=NUMBER_OF_COVERS; sensorId++) {
518 //Enregistrez tous les capteurs sur la passerelle (ils seront créés en tant
qu'appareils enfants)
519 present(sensorId, S_COVER);
520 }
521 present(ENABLER, S_LOCK);
522 #endif
523 }
524 #endif
525
526 /**********************/
527 /* LOOP */
528 /**********************/
529
530 void loop() {
531 wdt_reset();
532 t.update();
533
534 //Action par boutons physiques
535 if (pinChangeInterruptFlag) {
536 //Désactiver les interruptions afin qu'elles ne dérangent pas pendant l'exécution
de ce bloc
537 /*disableInterrupt(INPUT1);
538 disableInterrupt(INPUT2);
539 disableInterrupt(INPUT3);
540 disableInterrupt(INPUT4);
541 */
542 //Si my_debounce = true, traitez-le, sinon entrée non valide
543 if (my_debounce(DEBOUNCE_TIME)) {
544 uint8_t command;
545 //Afin d'économiser les broches et les fils, il existe une ligne commune qui
définit la direction.
546 //Tous les interrupteurs aveugles vers le bas poussent cette ligne à 0V.
547 //Par exemple, en appuyant sur le store 1 vers le bas, INPUT1 et COMMON passent
à 0V,
548 //tandis qu'en appuyant sur le store 1 vers le haut, seul INPUT1 passe à 0V.
549 digitalRead(COMMON)?command=V_UP:command = V_DOWN;
550 if (!digitalRead(INPUT1)) {
551 accionar_persiana(1, command);
552 }
553 if (!digitalRead(INPUT2)) {
554 accionar_persiana(2, command);
555 }
556 if (!digitalRead(INPUT3)) {
557 accionar_persiana(3, command);
558 }
559 if (!digitalRead(INPUT4)) {
560 accionar_persiana(4, command);
561 }
562 }
563 /*
564 //Activer à nouveau les interruptions
565 setup_interrupt(INPUT1);
566 setup_interrupt(INPUT2);
567 setup_interrupt(INPUT3);
568 setup_interrupt(INPUT4);
569 */
570 //Réinitialiser le drapeau d'interruption afin de ne pas l'exécuter à nouveau
jusqu'à ce qu'une autre touche soit enfoncée
571 pinChangeInterruptFlag=0;
572 }
573
574 //Action par radio si pas d'utilisation de MySensors
575 #ifndef MY_SENSORS
576 if ( radio.available() ) {
577 unsigned short rawMessage;
578 radio.read( &rawMessage, sizeof(rawMessage) );
579 perform_action(rawMessage);
580 }
581 #else
582 //Si le battement de cœur n'est pas reconnu, alors réinitialisez
583 if ((millis() - lastHeartbeatTime) > HEARTBEAT_TIME) {
584 lastHeartbeatTime = millis();
585 if (!sendHeartbeat()) {
586 asm("jmp 0x0000"); //Reset
587 }
588 }
589 #endif
590
591 }

Vous aimerez peut-être aussi