Détecteur d’orage avec un nodemcu et un AS3935
Pour compléter la station météo, il était important d’avoir un détecteur de foudre. Couplée à un webservice qui enverra les données sur le site, nous pourrons avoir un vrai historique de l’activité orageuse autour de la maison.
Matériel
Pour réaliser ce projet, j’ai d’abord choisi le nodemcu pour son côté sans fil wifi, qui permettra de le positionner presque n’importe où dans la maison. Ensuite, pour le détecteur d’orage, je me suis basé sur le module AS3935 produit par Sparkfun.
Branché en I2C, ce module a une connectique et un fonctionnement simple : on branche le module en I2C, on branche la pin IRQ sur un port d’interruption du nodemcu et c’est parti. A chaque détection de foudre, une interruption est levée sur la pin choisie (D8 ici) et le programme affiche alors la distance et l’énergie de l’impact.
Câblage AS3935 – Nodemcu:
- VCC (V) – 3V
- GND(G) – GND
- SCL (CL) – D1
- SDA (DA) – D2
- MI – /
- IRQ – D8
- SI – 3V
- CS – /
Attention : ne pas brancher l’IRQ sur les pin D3 et D4, ca fait planter le nodemcu et on ne peut pas téléverser le code.
Remarque : les pins d’interruptions du nodemcu sont de D0 à D8.
J’ai décidé d’ajouter 3 led au montage :
- une verte, qui s’allume et clignote quand l’accès au webservice via le réseau est OK
- une rouge, qui signale une erreur (module ou réseau)
- une bleu, qui s’allume quand des orages sont détectés
Les 3 LEDS sont branchées sur les ports D5/D6/D7. J’ai soudé les 3 masses pour n’avoir qu’un seul fil à brancher.
Pour la mise en boite, j’aime bien faire simple et utiliser des boites de dérivation, ça fait assez propre et les led sont faciles à encastrer (led de 5mm = mèche de 4,8mm).
Le code
Pour commencer, on va installer la librairie AS3935MI de Gregor Christandl qui marche directement sur Nodemcu. Un grand merci à lui. Les sources sont sinon ici.
Ensuite, une fois le câblage fait, il faut détecter l’adresse I2C du module. Vous pouvez le faire avec le scanner I2C Arduino.
Mon module est en 0x03. Par défaut, la librairie de Gregor est configurée pour 0x01. Pour mettre 0x03 en adresse, il faut passer la variable AS3935I2C::AS3935I2C_A11 au lieu de AS3935I2C::AS3935I2C_A01.
AS3935I2C as3935(AS3935I2C::AS3935I2C_A11, PIN_IRQ);
//0x01 = AS3935I2C_A01
//0x02 = AS3935I2C_A10
//0x03 = AS3935I2C_A11
Comme sur nos autres programmes, il faut paramétrer le wifi du module et la clé du webservice.
const char* ssid = "xxxxx";
const char* password = "xxxxx";
char server[] = "192.168.1.2";
WiFiClient client;
String KEY_WS="45698753349560223";
Puis on initialise les variables d’orage et les variables pour la boucle d’envoi du webservice.
int storm = 0;
int dist = 0;
int energy = 0;
unsigned long previousMillis= 0;
unsigned long delaiProgramme = 60000L; //60 sec
Dans le setup, pour identifier le démarrage du programme, je fais une séquence d’affichage/extinction des LED.
pinMode(LED_TRANSMISSION, OUTPUT);
pinMode(LED_STORM, OUTPUT);
pinMode(LED_ERROR, OUTPUT);
digitalWrite(LED_TRANSMISSION, HIGH);
digitalWrite(LED_STORM, HIGH);
digitalWrite(LED_ERROR, HIGH);
delay(1000);
digitalWrite(LED_TRANSMISSION, LOW);
digitalWrite(LED_STORM, LOW);
digitalWrite(LED_ERROR, LOW);
Une fois connecté au wifi (je ne re-détaille pas le code, voir ici), je refais une séquence de led pour valider qu’on est connecté.
//sequence led reseau OK
digitalWrite(LED_TRANSMISSION, HIGH);
delay(500);
digitalWrite(LED_TRANSMISSION, LOW);
delay(500);
digitalWrite(LED_TRANSMISSION, HIGH);
delay(500);
digitalWrite(LED_TRANSMISSION, LOW);
delay(500);
Sur le code de l’initialisation de l’AS3935, je n’ai pas touché grand chose si ce n’est 2 paramètres : le mode indoor/outdoor que j’ai mis indoor et le nombre de détection avant de déclencher l’interruption (5 ici, 1 par défaut, choix entre 1/5/9/16)
as3935.writeAFE(AS3935MI::AS3935_INDOORS);
//outdoor = AS3935_OUTDOORS
...
as3935.writeMinLightnings(AS3935MI::AS3935_MNL_5);
//AS3935_MNL_1 or AS3935_MNL_5 or AS3935_MNL_9 or AS3935_MNL_16
A l’intérieur du loop, je ne touche presque rien au code original. Dans l’interruption, j’ajoute ceci : l’incrément de la variable storm qui compte le nombre d’impacts, la distance et l’énergie du dernier impact. Je fais clignoter la led bleu et la laisser allumer.
else if (event == AS3935MI::AS3935_INT_L)
{
Serial.print("Lightning detected! Storm Front is ");
Serial.print(as3935.readStormDistance());
Serial.println("km away.");
dist = as3935.readStormDistance();
energy = as3935.readEnergy();
storm += 1;
digitalWrite(LED_STORM, HIGH);
delay (250);
digitalWrite(LED_STORM, LOW);
delay (250);
digitalWrite(LED_STORM, HIGH);
}
Puis j’ajoute le traditionnel appel à webservice pour envoyer les valeurs au serveur. A la fin de la séquence, je remet à zéro et variable et éteint la led bleu. Elle se rallumera si un nouvel impact est détecté. La led n’est donc allumé que pendant la minute où l’impact est détecté.
unsigned long currentMillis = millis();
if (currentMillis - previousMillis > delaiProgramme){
previousMillis = millis();
String url = "/stationmeteo/storm.php?key="+KEY_WS+"&storm="+storm+"&distance="+dist+"&energy="+energy;
HTTPClient http;
String Link = "http://192.168.1.2:81"+url;
http.begin(Link);
int httpCode = http.GET();
String payload = http.getString();
Serial.println(httpCode);
Serial.println(payload);
if(httpCode != 200){
digitalWrite(LED_TRANSMISSION, LOW);
digitalWrite(LED_ERROR, HIGH);
}
if(httpCode == 200){
digitalWrite(LED_TRANSMISSION, HIGH);
delay (250);
digitalWrite(LED_TRANSMISSION, LOW);
delay (250);
digitalWrite(LED_TRANSMISSION, HIGH);
digitalWrite(LED_ERROR, LOW);
}
http.end();
//RAZ valeurs
storm = 0;
dist = 0;
energy = 0;
digitalWrite(LED_STORM, LOW);
}
Le webservice est quand à lui tout simple : il loggue le résultat courant dans un fichier texte sur le serveur et historique le résultat dans un fichier journalier. L’ensemble est récupéré alors par un autre script qui traitera les données.
<?php
$REFKEY = '45698753349560223';
if(isset($_GET['key'])){
$key = $_GET['key'];
if($key == $REFKEY){
if(isset($_GET['storm'])){
$storm = $_GET['storm'];
$dist = $_GET['distance'];
$energy = $_GET['energy'];
$file = 'storm.txt';
$line = $storm.';'.$dist.';'.$energy;
file_put_contents($file, $line);
echo 'data added to '.$file;
$folder = 'datas/'.date('Y').'/'.date('m').'/';
$file = $folder.date('Ymd').'_storm.txt';
$date = date('Y-m-d H:i');
$line = $date.';'.$storm.';'.$dist.';'.$energy;
$line .= "\n";
file_put_contents($file, $line, FILE_APPEND);
echo 'data added to '.$file;
}
}
else{
echo 'Mauvaise clé utilisée';
}
}
else{
echo 'Erreur formatage URL';
}
?>
Le code complet est à retrouver sur Github.
Conclusion
J’ai trouvé peu de ressources pour faire ce projet, et j’ai pas mal galéré pour avoir un truc stable. Mais je suis content du résultat et de la fiabilité du module. J’ai eu quelques faux positifs en test, j’avoue être impatient qu’il y ait des orages pour le tester 🙂
Bonjour, merci pour votre excellent tuto. Je vais le faire incessamment sous peu. Par contre, quel NodeMCU utilisez vous ? CH340 ? Au vu des orages des derniers jours, quel sont étaient les résultats ? Bien cordialement, Sébastien
Bonjour,
Oui ce sont les nodemcu de AZDelivery sur Amazon.
Par contre, j’ai testé pendant des jours mon montage et malgré les orages, il n’a jamais rien detecté ☹️.
Je ne sais pas si c’est le materiel lui meme ou pas mais il ne detecte rien. J’ai testé d’autres librairies mais sans succès.
Il faut que j’update l’article pour l’indiquer. Si toutefois vous essayez, er que ca marche, je suis preneur du resultat !
Merci
Fabien
Merci beaucoup, Fabien, de votre retour. J’ai aussi commencé ce projet, il me manque plus que le capteur à particules : https://luftdaten.info.
Vous pouvez retrouver les graphiques sur ce site, mais rien de significatif, car provisoirement à l’intérieur :
https://api-rrd.madavi.de/grafana/d/q87EBfWGk/temperature-humidity-pressure?orgId=1&var-chipID=esp8266-8281825.
J’aimerais retrouver mes données extérieures sur une petite station LCD 1.3′ ESP8266, j’ai trouvé le programme pour le faire (http://www.mediafire.com/file/n3etw0f9ccyq3ug/file), serait-il possible de m’expliquer le code nécessaire pour récupérer les données extérieures ?
Merci pour les autres articles météo très inspirants. Sincèrement, Sébastien
Le site de restitution des données est top ! C’est vraiment pas mal.
Pour récupérer les données à l’extérieur (je suppose sur madavi.de), il faut qu’il y ait une API ouverte pour requeter. Idéalement, il faut un fichier json que l’on parcours ensuite pour extraire la donnée et l’afficher sur le LCD.
Moi j’ai testé ThingSpeak où j’envoie mes données et on peut requêter le site via une URL.
URL de base : https://thingspeak.com/channels/929881
URL de récupération : http://api.thingspeak.com/channels/929881/feed.json
Doc API : https://community.thingspeak.com/documentation%20…/api/
Si vous souhaitez envoyer des données à thingspeak, je vous donnerais le format d’URL à lancer.
Une fois les données envoyées, il suffit de lancer l’url et lire le json par programme et d’en extraire les valeurs.
Pour écrire sur le LCD, voir ici : https://www.sla99.fr/2018/03/16/multimetre-arduino/ le principe est le même sur un écran plus grand.
Si besoin, on pourra continuer par email.
Merci pour vos encouragements pour le site 🙂
Fabien
J’aimerais bien avoir votre email car j’aurais sûrement d’autres questions et je commence petit à petit à « construire » ma station météo. Le suivi des orages m’intéresse particulièrement car je suis radioamateur et il fort pratique d’être prévenu de la foudres afin de mettre nos installations en sécurité.
Le projet collaboratif allemand sur la surveillance de la qualité de l’air est très simple à installer et effectivement le programme arduino permet de recevoir ces données en local via une interface Web et de les partager sur divers sites via différents API.
Je vous tiens au courant de l’avancement de mes projets en cours afin de partager différents thèmes. Bonne continuation. Très sincèrement, Sébastien
je viens de me remettre sur le montage, vous m’avez titillé 🙂 Et avec la librairie Sparkun et un arduino uno (les nodemcu et autres wemos ne sont pas faits pour faire de l’interruption …), j’arrive à simuler de la foudre et récupérer des données. Je l’ai reprogrammé pour envoyer sur mon site des infos, à suivre dans les prochains jours si des orages arrivent 🙂
Je vous tiens au courant et mettrais à jour l’article en fonction.
Bonjour, c’est la 1ere fois que je trouve autant d’infos sur ce module, étant moi même électronicien et radioamateur, c’est une aubaine bien que je n’ai pas trop la fibre programmation. Toutefois les librairies utilisées pour le WIFI et le WEBSERVICE dans ce projet sont introuvables via l’interface ARDUINO auriez vous plus de détails les concernant. Personnellement j’ai déjà une station météo qui me renvois les données via GRAFANA avec Influxdb, Y intégrer un compteurs d’impact de foudre serait parfait. Cordialement
Bonjour,
Merci ! J’ai pas mal galéré donc j’ai documenté et j’en fait profiter 🙂
Pour le wifi, j’utilise les classiques :
#include
#include
Pour le webservice, il est appelé depuis l’arduino comme ceci (voir github)
…
String url = « /stationmeteo/storm.php?key= »+KEY_WS+ »&storm= »+storm+ »&distance= »+dist+ »&energy= »+energy;
HTTPClient http;
String Link = « http://192.168.1.2:81″+url;
…
en face, je n’ai qu’un simple fichier PHP qui répond et fait les actions lorsqu’on l’appelle.
Voici l’essentiel de mon fichier storm.php
$REFKEY = ‘xxxxxxxxx’;
if(isset($_GET[‘key’])){
$key = $_GET[‘key’];
if($key == $REFKEY){
if(isset($_GET[‘storm’])){
$storm = $_GET[‘storm’];
$dist = $_GET[‘distance’];
$energy = $_GET[‘energy’];
//je fais mon traitement ici
} else {
//traitement du else
}
}
}
else{
echo ‘Mauvaise clé utilisée’;
}
}
else{
echo ‘Erreur formatage URL’;
}
J’espère que ca vous éclaire.
J’ai mis un KEY pour pas que n’importe qui sui serait sur mon LAN envoie des données dans ma bdd via le script PHP (oui c’est un peu parano en LAN 🙂 )
L’indentation s’est perdue dans le commentaire, si besoin je vous l’enverrais par mail