1 /*
2 ceci est basé sur le programme master de sylvain
3 le module est en mode OTAA
4 il est configuré pour émettre avec 20dbm
5
6 la lecture des capteur est demandée une fois au setup pour les balances puis dans le loop selon uint32_t appTxDutyCycle = 15000;
7 elle appelée avec prepareTxFrame( appPort );
8 puis les données sont envoyées avec LoRaWAN.send();
9 le format est l'octet dont le nombre est non limité à priori
10 des exemples sont disponibles via l'IDE arduino quand on a installé la bibliothèque de la carte cubcell HTCC-AB02 plus
11
12 la balance et les sondes
13 largement commenté dans static void prepareTxFrame( uint8_t port )
14
15 alimentation des capteurs
16 on utilise la sortie VEXT : HIGH pas de tension LOW tension sur VEXT
17 */
18 #include "LoRaWan_APP.h" //https://github.com/mcci-catena/arduino-lorawan/
19 #include <Arduino.h>
20 #include <Adafruit_Sensor.h>
21
22 //les température humidité
23 #include <DHT.h>
24 #include <DHT_U.h>
25 #define DHTPIN GPIO5 // Changer le pin sur lequel est branché le DHT
26 #define DHTTYPE DHT22
27 DHT dht(DHTPIN, DHTTYPE);
28
29 float humidite;
30 float temperature;
31
32 //les températures sonde DS18B20 EXterne au boitier
33 #include "OneWire.h"
34 #include "DallasTemperature.h"
35 OneWire oneWire(ADC3);
36 DallasTemperature ds(&oneWire);
37
38
39 //la balance.
40 //le module LORA a une sortie Vext sur laquelle on peut mettre l'alimentation des capteurs
41 //on met Vext à LOW pour alimenter et à HIGH pour couper l'alimentation
42 //par rapport au master de Sylvain, j'ai donc effacé la gestion de l'alimentation via une PIN spécialement dédiée
43 #include "HX711.h"
44 HX711 Hx711_N1;
45
46 #define PIN_HX711_N1_DATA_OUT GPIO6 // connexion au DATA
47 #define PIN_HX711_N1_SCK_AND_POWER_DOWN GPIO7// connexion à l'horloge SCK
48
49 float offset_HX711_N1_ChannelA;// pour Patrick et Sébastien on utilisera que le canal A+-
50
51 const unsigned int Weight_sensitivity = 4 ;
52
53 // Header byte = 1st Byte transmitted int he Sigox Tram ( SIGFOX #01 )
54 // Bit 7 = Sigfog Debug Mode, =1 for SIGFOX DEBUG MODE
55 // Bit 6 = Solar Panel Luminosity, measured during software excution ( =0 Voltage solar panel < Voltage Battery, =1 >
56 // Bit 5 = FUll Charging Battery status , measured during software excution
57 // Bit 4 = Charging on going, measured during software excution
58 // Bit 0 to 3 = Software version : 0000 = Debug Software, then 0001 = V1 ...
59 // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
60
61 // DEBUG_MODE mettre à zéro en mode normal pour moins consommer*************************
62 boolean DEBUG_MODE =1; // =1 or debug , then ALLOW BLINKING LED and statement on Serial Monitor throught SERIAL RX/TX UART0
63 /*
64 //ceci est la partie qui règle les conditions d'émission radio du module. J'ai augmenté à 20db la puissance
65 //////////////////////////////////////Radio.SetTxConfig dans le SETUP////////////
66 #define TX_OUTPUT_POWER 20 ///14 // pour 20dBm
67
68 #define LORA_BANDWIDTH 0 // [0: 125 kHz,
69 // 1: 250 kHz,
70 // 2: 500 kHz,
71 // 3: Reserved]
72 #define LORA_SPREADING_FACTOR 9 // [SF7..SF12]
73 #define LORA_CODINGRATE 1 // [1: 4/5,
74 // 2: 4/6,
75 // 3: 4/7,
76 // 4: 4/8]
77 #define LORA_PREAMBLE_LENGTH 8 // Same for Tx and Rx
78 #define LORA_SYMBOL_TIMEOUT 0 // Symbols
79 #define LORA_FIX_LENGTH_PAYLOAD_ON false
80 #define LORA_IQ_INVERSION_ON false
81 /////////////////////////////////////////////////////////////////////////////////
82 */
83 /* OTAA para c'est ce OTAA paramêtre qui est utilisé */
84
85 uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
86
87 /*décommenter les modules à programmer */
88
89 //lora-01
90 //uint8_t devEui[] = { 0x70, 0xB3, xxxxxxx };
91 //uint8_t appKey[] = { 0x43, 0x26, xxxxxxxx };
92
93
94
95 /* ABP para*/
96 uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda,0x85 };
97 uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef,0x67 };
98 uint32_t devAddr = ( uint32_t )0x260B37FC;
99
100 /*LoraWan channelsmask, default channels 0-7*/
101 uint16_t userChannelsMask[6]={ 0x00FF,0x0000,0x0000,0x0000,0x0000,0x0000 };
102
103 /*LoraWan region, select in arduino IDE tools*/
104 LoRaMacRegion_t loraWanRegion = ACTIVE_REGION;//jjjjjjj essai git
105
106 /*LoraWan Class, Class A and Class C are supported*/
107 DeviceClass_t loraWanClass = LORAWAN_CLASS;
108
109 /*the application data transmission duty cycle. value in [ms].*//////////////////////////////////////
110 uint32_t appTxDutyCycle = 60000; //15000 donc 15sec; 900000 donc 15mn
111
112 /*OTAA or ABP*/
113 bool overTheAirActivation = LORAWAN_NETMODE;
114
115 /*ADR enable*/
116 bool loraWanAdr = LORAWAN_ADR;
117
118 /* set LORAWAN_Net_Reserve ON, the node could save the network info to flash, when node reset not need to join again */
119 bool keepNet = LORAWAN_NET_RESERVE;
120
121 /* Indicates if the node is sending confirmed or unconfirmed messages */
122 bool isTxConfirmed = LORAWAN_UPLINKMODE;
123
124 /* Application port */
125 uint8_t appPort = 2;
126 /*!
127 * Number of trials to transmit the frame, if the LoRaMAC layer did not
128 * receive an acknowledgment. The MAC performs a datarate adaptation,
129 * according to the LoRaWAN Specification V1.0.2, chapter 18.4, according
130 * to the following table:
131 *
132 * Transmission nb | Data Rate
133 * ----------------|-----------
134 * 1 (first) | DR
135 * 2 | DR
136 * 3 | max(DR-1,0)
137 * 4 | max(DR-1,0)
138 * 5 | max(DR-2,0)
139 * 6 | max(DR-2,0)
140 * 7 | max(DR-3,0)
141 * 8 | max(DR-3,0)
142 *
143 * Note, that if NbTrials is set to 1 or 2, the MAC will not decrease
144 * the datarate, in case the LoRaMAC layer did not receive an acknowledgment
145 */
146 uint8_t confirmedNbTrials = 4;
147
148 //*****************************
149 static void prepareTxFrame( uint8_t port )
150 {
151 pinMode(Vext, OUTPUT);
152 digitalWrite(Vext, LOW);//LOW pour alimenter la sortie Vext 3V3 pour les capteur. Sur l'établi, j'alimente pour l'instant en continu pour les essais
153
154 if (DEBUG_MODE) {
155 Serial.println("CODE prepareTxFrame s'exécute ");
156 }
157
158 //on traite d'abord la tension batterie
159 uint16_t batteryVoltage = getBatteryVoltage();
160 batteryVoltage = batteryVoltage;// la tension est mesurée en miliVolts
161
162 if (DEBUG_MODE) {
163 Serial.print("tension batterie en mili voltes ");
164 Serial.println(batteryVoltage);
165 }
166 /*
167 température sur sur node red on fait le calcul inverse
168
169 var temp_octet0 = msg.payload.uplink_message.decoded_payload.bytes[2];
170 var temp_octet1 = msg.payload.uplink_message.decoded_payload.bytes[3];
171 var temp = ((temp_octet0 * 256 + temp_octet1)) / 2 -35;
172 var newMsg = { payload: temp };
173 return newMsg;
174
175 on reçoit le payload en HEX
176 on multiplie le poids fort (octet 0) par 256 et on ajoute le poids faible (octet 1)
177 qui n'a pas besoin d'être converti puisque l'HEX est égal au DEC
178 **************************************
179 humidité sur node red
180
181 var hum_octet0 = msg.payload.uplink_message.decoded_payload.bytes[4];
182 var hum_octet1 = msg.payload.uplink_message.decoded_payload.bytes[5];
183 var hum = (hum_octet0 * 256 + hum_octet1) / 2;
184 var newMsg = { payload: hum };
185 return newMsg;
186 **************************************
187 1ère balance sur node red
188
189 var balance_octet0 = msg.payload.uplink_message.decoded_payload.bytes[6];
190 var balance_octet1 = msg.payload.uplink_message.decoded_payload.bytes[7];
191 var balance = (balance_octet0 * 256 + balance_octet1) * 11.6;
192
193 var newMsg = { payload: balance };
194 return newMsg;
195
196 */
197 // Reading temperature or humidity takes about 250 milliseconds!
198 // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
199
200
201 Serial.println("DHTxx test!");
202
203 delay(1000);
204 dht.begin();
205
206 delay(1000);//pour laisser le temps de montée de la sonde
207 float h = dht.readHumidity();
208 delay(1000);
209 // Read temperature as Celsius
210 float t = dht.readTemperature();
211 int8_t t_byte = (t + 35 )*2; // à mieux commenter
212 uint8_t h_byte = h*2; // à mieux commenter
213
214 if (DEBUG_MODE) {
215 Serial.print("Temperature: ");
216 Serial.print(t);
217 Serial.print(" *C lora #03: ");
218 Serial.print(t_byte,HEX);
219 Serial.print(" Byte ");
220 Serial.print("Humidity : ");
221 Serial.print(h);
222 Serial.print(" %\t lora #04: ");
223 Serial.print(h_byte,HEX);
224 Serial.println(" Byte ");
225 }
226
227 //sonde dc18b20 en externe******************************
228
229 Serial.println("ds18b20 test!");
230
231 delay(1000);
232 ds.begin(); // sonde activée
233
234 delay(1000);
235 ds.requestTemperatures();
236 int tDs = ds.getTempCByIndex(0);
237 int8_t tDs_byte = (tDs + 35 )*2;
238
239 if (DEBUG_MODE){
240 Serial.print(tDs);
241 Serial.println( " C");
242 Serial.print(tDs_byte,HEX);
243 Serial.println(" Byte ");
244
245 }
246
247 //les balances*******************************************************
248
249
250 float Sample_weight;
251
252 Hx711_N1.begin(PIN_HX711_N1_DATA_OUT,PIN_HX711_N1_SCK_AND_POWER_DOWN,64 );
253 Sample_weight = Hx711_N1.get_units(); // For nothing library problem...
254 Sample_weight = (offset_HX711_N1_ChannelA - Hx711_N1.get_units())/256*Weight_sensitivity;
255
256 if (Sample_weight < 0) {
257 Sample_weight =0;
258 }
259 else {
260 if (Sample_weight > 65535) {
261 Sample_weight = 65535;
262 }
263 }
264
265 unsigned int Weight_HX711_N1_Channel_A = Sample_weight;
266
267 if (DEBUG_MODE) {
268 Serial.print("Weight N1 Channel A : ");
269 Serial.print(Weight_HX711_N1_Channel_A,DEC);
270 Serial.print(" ");
271 Serial.print(Weight_HX711_N1_Channel_A,HEX);
272 Serial.print(" ");
273 Serial.print(Weight_HX711_N1_Channel_A,BIN);
274 Serial.print(" ");
275 Serial.println();
276 }
277
278
279
280 //en miliVolts
281
282 //appData[0] = (uint8_t)(batteryVoltage >> 8);//décalage de 8 bit vers la droite,
283 //4803 donne 0001001011000011 sur 16bit donc reste les 8 1ers bits 00010010 soit 12 hex
284 //Serial.println(appData[4]);
285
286 //appData[1] = (uint8_t)batteryVoltage;
287 //4803 donne 0001001011000011 donc si uint_8 on prend donc 8bit de droite 11000011 soit C3 hex
288 // quand on concatène 12C3 hex dans un convertisseur hexa vers décimal, cela donne 4803 mV au décodage de la trame LORA
289 //Serial.println(appData[5]);
290
291 //calcul pour la température
292 //sur lorawan on obtient 00 74 hex
293 //on concatène 00 et 74 , on convertit hexa vers décimal et on obtient 116 décimal
294 //on reprend la formule de Sylvain t_byte = (t + 35 )*2 donc partie entière de t=116/2 moins 35 degrés soit 23 degrés
295
296 //calcul pour l'humidité
297 //sur lorawan on obtient 00 7F hex
298 //on concatène 00 et 7F , on convertit hexa vers décimal et on obtient 127 décimal
299 //on reprend la formule de Sylvain h_byte = h*2 donc partie entière de h=127/2 soit 63%
300
301 //calcul pour la pesée
302 //sur lorawan on obtient 04 9B hex pour une donnée de 1179 correspondant à un poids de 13800gr
303 //ou 1C E0 pour 7392 correspondant à 85700gr
304 //le rapport entre 85700gr et 7392 est un multiplicateur de 11,6
305 //quand on multiplie par 11,6 une mesure convertie en décimal, on obtient le poids réel en grammes
306
307 appDataSize = 10;// nombre total d'octets de la trame envoyée
308 //et à changer selon le nombre de balances et capteurs
309
310 appData[0] = (uint8_t)(batteryVoltage>>8);
311 appData[1] = (uint8_t)batteryVoltage;
312
313
314 appData[2] = (uint8_t)(t_byte>>8);
315 appData[3] = (uint8_t)t_byte;
316
317
318 appData[4] = (uint8_t)(h_byte>>8);
319 appData[5] = (uint8_t)h_byte;
320
321 appData[6] = (uint8_t)(tDs_byte>>8);
322 appData[7] = (uint8_t)tDs_byte;
323
324
325 appData[8] = (uint8_t)(Weight_HX711_N1_Channel_A>>8);
326 appData[9] = (uint8_t)Weight_HX711_N1_Channel_A;
327
328 digitalWrite(Vext, HIGH);//HIGH une fois les mesures faites, couper alimentation sortie Vext 3V3 par économie de mA
329
330 }
331
332 void setup()
333 {
334
335 Serial.begin(9600);
336
337 pinMode(Vext, OUTPUT);
338 digitalWrite(Vext, LOW);//alimentation de la sonde est valide pour permettre initialisation de la sonde
339 delay(1000);//on laisse un temps de montée pour la sonde
340
341
342 if (DEBUG_MODE) {
343 Serial.print("SETUP DONE");
344 Serial.println();
345
346 }
347 Serial.print("cycle d'envoi des données en ms ");
348 Serial.print(appTxDutyCycle);
349 Serial.println();
350 Serial.print("LORA master 1bal dht22 et ds18b20.cpp ");
351 Serial.println();
352
353 #if(AT_SUPPORT)//ne pas oublier ce module???
354 enableAt();
355 #endif
356 deviceState = DEVICE_STATE_INIT;
357 LoRaWAN.ifskipjoin();
358
359
360
361 //initialisation et détection des balances
362
363 //////////dans le SETUP on calcule une bonne fois l'offset en mesurant la balance à VIDE après un RESET
364
365 //pinMode(PIN_HX711_N1_DATA_OUT, OUTPUT); // connexion au DATA
366 //pinMode(PIN_HX711_N1_SCK_AND_POWER_DOWN, OUTPUT);// connexion à l'horloge SCK
367
368 delay(1000);
369
370 float Sample_weight;
371
372 Hx711_N1.begin(PIN_HX711_N1_DATA_OUT,PIN_HX711_N1_SCK_AND_POWER_DOWN,64 );
373 Sample_weight = Hx711_N1.get_units();
374 offset_HX711_N1_ChannelA = Hx711_N1.get_units();
375
376 if (DEBUG_MODE) {
377 Serial.print("Offset N1 Channel A : ");
378 Serial.print(offset_HX711_N1_ChannelA);
379 Serial.println();
380 Serial.flush() ;
381 }
382
383 ////////////////////////////////////////////////////////////////////////////////////
384 /*
385 paramêtres de puissance émission à 20db PW maxi 110mA via constructeur voir #define TX_OUTPUT_POWER
386
387
388 Radio.SetTxConfig( MODEM_LORA, TX_OUTPUT_POWER, 0, LORA_BANDWIDTH,
389 LORA_SPREADING_FACTOR, LORA_CODINGRATE,
390 LORA_PREAMBLE_LENGTH, LORA_FIX_LENGTH_PAYLOAD_ON,
391 true, 0, 0, LORA_IQ_INVERSION_ON, 3000 );
392
393 /////////////////////////////////////////////////////////////////////////////////////
394 */
395 Serial.print("attente 10 secondes pour mise en place d'un poids éventuel ");
396 delay(10000);
397 Serial.println();
398 Serial.flush() ;
399
400 prepareTxFrame( appPort );
401
402 digitalWrite(Vext, HIGH);
403 }
404
405 void loop()
406 {
407
408 switch( deviceState )
409 {
410 case DEVICE_STATE_INIT:
411 {
412 #if(LORAWAN_DEVEUI_AUTO)
413 LoRaWAN.generateDeveuiByChipID();
414 #endif
415 #if(AT_SUPPORT)
416 getDevParam();
417 #endif
418 printDevParam();
419 LoRaWAN.init(loraWanClass,loraWanRegion);
420 deviceState = DEVICE_STATE_JOIN;
421 break;
422 }
423 case DEVICE_STATE_JOIN:
424 {
425 LoRaWAN.join();
426 break;
427 }
428 case DEVICE_STATE_SEND:
429 {
430 prepareTxFrame( appPort );
431 LoRaWAN.send();
432
433 deviceState = DEVICE_STATE_CYCLE;
434 break;
435 }
436 case DEVICE_STATE_CYCLE:
437 {
438 // Schedule next packet transmission
439 txDutyCycleTime = appTxDutyCycle + randr( 0, APP_TX_DUTYCYCLE_RND );
440 LoRaWAN.cycle(txDutyCycleTime);
441 deviceState = DEVICE_STATE_SLEEP;
442 break;
443 }
444 case DEVICE_STATE_SLEEP:
445 {
446 LoRaWAN.sleep();
447 break;
448 }
449 default:
450 {
451 deviceState = DEVICE_STATE_INIT;
452 break;
453 }
454 }
455
456
457
458
459 }
1 ; PlatformIO Project Configuration File
2 ;
3 ; Build options: build flags, source filter
4 ; Upload options: custom upload port, speed and extra flags
5 ; Library options: dependencies, extra library storages
6 ; Advanced options: extra scripting
7 ;
8 ; Please visit documentation for the other options and examples
9 ; https://docs.platformio.org/page/projectconf.html
10
11 [env:cubecell_board_plus]
12 platform = asrmicro650x
13 board = cubecell_board_plus
14 framework = arduino
15
16 build_flags = -std=c++11
17 monitor_speed = 9600
18 lib_deps =
19 adafruit/DHT sensor library@^1.4.4
20 bogde/HX711@^0.7.5
21 board_build.arduino.lorawan.region = EU868
22 board_build.arduino.lorawan.class = CLASS_A
23 board_build.arduino.lorawan.netmode = OTAA
24 board_build.arduino.lorawan.adr = ON
25 board_build.arduino.lorawan.uplinkmode = UNCONFIRMED
26 board_build.arduino.lorawan.net_reserve = ON
27 board_build.arduino.lorawan.at_support = ON
28 board_build.arduino.lorawan.rgb = DEACTIVE
29 board_build.arduino.lorawan.debug_level = NONE