Connexion et test du lecteur de carte SD
Mon lecteur de carte SD est un module qui communique au moyen du protocole SPI à un niveau logique de 3,3 V qui convient parfaitement à l'ESP8266.
En ce qui concerne l'ESP8266, j'ai utilisé une carte Wemos D1, mais bien entendu n'importe quel ESP8266 comportant un nombre suffisant de broches GPIO fera l'affaire.
Le module lecteur de cartes SD est connecté à l'ESP8266 de la façon suivante:
Carte SD --- ESP8266
GǸD --- GND
+3,3 --- 3,3V
+5 --- ----
CS --- GPIO 15
MOSI --- GPIO 13
SCK --- GPIO 14
MISO --- GPIO 12
Bonne nouvelle: la bibliothèque "SD" fournie avec l'IDE Arduino est parfaitement compatible avec l'ESP8266, ce qui simplifie évidemment les choses.
Pour vérifier le fonctionnement correct de la carte SD, c'est toujours une bonne idée de faire l'essai de l'exemple "CardInfo". Il faudra toutefois utiliser "15" comme valeur de la constante "chipSelect".
Sketch
Voici le sketch qui prend une mesure à chaque minute et consigne le résultat à l'intérieur d'un fichier intitulé "Mesures.txt" sur la carte SD. Pour faire mes tests, j'ai simplement utilisé un potentiomètre branché à l'ADC de l'ESP8266. La date et l'heure de chaque mesure est également enregistrée, après interrogation d'un serveur NTP (il n'est donc pas nécessaire de brancher une horloge temps réel (RTC) à l'ESP8266.
Afin de profiter au maximum des possibilités de l'ESP8266, j'ai également programmé un serveur web qui présente les 10 mesures les plus récentes ayant été enregistrées sur la carte SD.
Lors du démarrage, le moniteur série indique la réussite (ou l'échec) de la connexion au réseau WiFi, de la mise en place du serveur web, de la connexion au serveur NTP et de l'initialisation de la carte SD. L'enregistrement de chaque mesure dans la carte SD est également signalée.
Au moyen d'un fureteur, on accède à l'adresse IP indiquée dans le moniteur série, ce qui nous permet de consulter les 10 dernières mesures ayant été consignées sur la carte SD.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/************************************************************** | |
Data Logger ESP8266 | |
Les mesures d'un capteur sont enregistrées à intervalle | |
régulier sur une carte SD. | |
On peut consulter, par l'entremise d'une page web, les | |
10 plus récentes valeurs enregistrées. | |
Plus d'infos: | |
https://electroniqueamateur.blogspot.com/2019/03/esp8266-et-carte-sd.html | |
*****************************************************************/ | |
// bibliothèques pour le lecteur de carte SD: | |
#include <SPI.h> | |
#include <SD.h> | |
// bibliothèques pour la communication WiFi | |
#include <ESP8266WiFi.h> | |
#include <WiFiClient.h> | |
#include <ESP8266WebServer.h> | |
// bibliothèque pour l'affichage de la date et de l'heure | |
#include <time.h> | |
// adresse et mot de passe du réseau wifi | |
const char* ssid = "********"; | |
const char* password = "********"; | |
// constantes | |
const int delaiEnMinutes = 1; // combien de minutes entre deux mesures consécutives? | |
const int stockage_max = 10; //nombre maximal de données stockées en mémoire, pour affichage dans la page web | |
const int decalage = -5; // la valeur dépend de votre fuseau horaire. Essayez 2 pour la France. | |
// variables globales | |
unsigned long derniereMesure; // derniere fois qu'une mesure a été prise | |
int mesures[stockage_max]; // tableau contenant les plus récentes mesures | |
time_t date_et_heure[stockage_max]; // tableau contenant le moment des plus récents scans | |
int nb_de_donnees = 0; // nombre de données déjà stockées dans mesures et dateHeure | |
File monFichier; // fichier sur la carte SD | |
ESP8266WebServer serveur(80); // serveur web | |
// Construction de la page web | |
void handle_root() { | |
struct tm * timeinfo; | |
String contenu; | |
for (int i = 0; i < stockage_max; i++) { | |
if (date_et_heure[i] != 0) | |
{ | |
timeinfo = localtime(&date_et_heure[i]); | |
contenu.concat( "<p> Date et heure: " + String(timeinfo->tm_mday) + "-" + String(timeinfo->tm_mon + 1) + "-" + String(timeinfo->tm_year + 1900) + " " + String(timeinfo->tm_hour) + ":" + String(timeinfo->tm_min) + ":" + String(timeinfo->tm_sec) + " Mesure: " + String(mesures[i]) + "</p>"); | |
} | |
} | |
serveur.send(200, "html", "<head> <title>Data logger ESP8266</title> <meta http-equiv=Refresh content=30></head> " | |
"<body><H1>" + String(stockage_max) + " plus récentes mesures enregistrées</H1>" | |
"<p>" + contenu + "<p>" | |
"<p>Visitez <a href=http://electroniqueamateur.blogspot.com/>Électronique en Amateur</a>!</p></body>"); | |
delay(100); | |
} | |
// Initialisation du WiFi et de la carte SD. Les progrès s'affichent dans le moniteur série | |
// pour faciliter le débogage, et pour connaître l'adresse IP de l'ESP8266. | |
void setup() | |
{ | |
SPI.begin(); | |
Serial.begin(9600); | |
Serial.println(); | |
WiFi.begin(ssid, password); | |
Serial.print("Connexion au reseau WiFi"); | |
while (WiFi.status() != WL_CONNECTED) { | |
Serial.print("."); | |
delay(1000); | |
} | |
Serial.println(); | |
Serial.print("Nom du reseau WiFi: "); | |
Serial.println(ssid); | |
Serial.print("Adresse IP de la page web: "); | |
Serial.println(WiFi.localIP()); | |
serveur.on("/", handle_root); | |
serveur.begin(); | |
Serial.println("Le serveur web est en fonction."); | |
configTime(decalage * 3600, 0, "ca.pool.ntp.org"); //serveurs NTP canadiens | |
// en Europe, essayez europe.pool.ntp.org ou fr.pool.ntp.org | |
Serial.print("Attente date et heure"); | |
while (time(nullptr) <= 100000) { | |
Serial.print("."); | |
delay(1000); | |
} | |
Serial.println(); | |
Serial.println("Pret."); | |
Serial.print("Initialisation de la carte SD..."); | |
if (!SD.begin(15)) { // CS du lecteur de carte branché à GPIO15 | |
Serial.println("echec!"); | |
while (1); | |
} | |
Serial.println("reussie"); | |
} | |
void loop() | |
{ | |
int nouvelleMesure; | |
time_t heureMesure; | |
struct tm * timeinfo; | |
if ((millis() - derniereMesure) >= delaiEnMinutes * 60000) // c'est le moment de prendre une nouvelle mesure | |
{ | |
nouvelleMesure = analogRead(A0); // mesure de l'entrée analogique A0 | |
time(&heureMesure); // quelle heure est-il? | |
timeinfo = localtime(&heureMesure); | |
// enregistrement de la mesure sur la carte SD | |
// ouverture (ou création) du fichier "Archives.txt") | |
monFichier = SD.open("Mesures.txt", FILE_WRITE); | |
// si l'ouverture a réussi, on écrit à l'intérieur | |
if (monFichier) { | |
Serial.print("Ecriture dans le fichier Mesures.txt ... "); // dans le moniteur série | |
monFichier.print("Date et heure: "); // dans le fichier | |
monFichier.print(String(timeinfo->tm_mday)); | |
monFichier.print("-"); | |
monFichier.print(String(timeinfo->tm_mon + 1)); | |
monFichier.print("-"); | |
monFichier.print(String(timeinfo->tm_year + 1900)); | |
monFichier.print(" "); | |
monFichier.print(String(timeinfo->tm_hour)); | |
monFichier.print(":"); | |
monFichier.print(String(timeinfo->tm_min)); | |
monFichier.print(":"); | |
monFichier.print(String(timeinfo->tm_sec)); | |
monFichier.print(" Mesure:"); | |
monFichier.println(nouvelleMesure); | |
// on referme le fichier | |
monFichier.close(); | |
Serial.println("reussie."); | |
} else { | |
// si l'ouverture du fichier a échoué: | |
Serial.println("Erreur d'ouverture du fichier Mesures.txt"); | |
} | |
// Stockage des 10 mesures les plus récentes pour affichage dans la page web | |
if (nb_de_donnees < stockage_max) { // il y a encore des lignes vides pour l'affichage web | |
mesures[nb_de_donnees] = nouvelleMesure; | |
date_et_heure[nb_de_donnees] = heureMesure; // quelle heure est-il? | |
nb_de_donnees++; | |
} | |
else // la page web est pleine | |
{ | |
for (int i = 0; i < stockage_max - 1; i++) { // on décale toutes les infos d'une ligne | |
mesures[i] = mesures[i + 1]; | |
date_et_heure[i] = date_et_heure[i + 1]; | |
} | |
mesures[stockage_max - 1] = nouvelleMesure; // on enregistre la nouvelle info | |
date_et_heure[stockage_max - 1] = heureMesure; // quelle heure est-il? | |
} | |
derniereMesure = millis(); | |
} | |
serveur.handleClient(); | |
} |
À lire également:
Aucun commentaire:
Enregistrer un commentaire