Académique Documents
Professionnel Documents
Culture Documents
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) {