En diverses entrades he anat explicant com connectar sensors als microprocessadors Arduino i similars, i com programar-los per a visualitzar i guardar les dades que obtenen, tant a l’ordinador com al telèfon mòbil. En aquesta entrada intentaré explicar com recollir les dades captades pels sensors en una targeta SD per posteriorment recuperar les i analitzar-les.
Moltes vegades l’experiment que realitzem té lloc en un temps curt i va bé recollir els valors que proporciona l’Arduino mentre es van produint, però hi ha ocasions en les que volem dades al llarg de molt temps (l’evolució de la temperatura i la humitat en un hivernacle, per exemple) o fora de l’abast del nostre ordinador o telèfon (si pugem l’Arduino amb un dron en l’atmosfera, per exemple) i convé que es vagin enregistrant en el propi maquinari. Aquí és quan pot venir bé una tarja SD que les guardi.
El maquinari
A més de la placa Arduino Uno o ESP32 es necessita una targeta de memòria SD o microSD, el lector de targetes en la que introduir la microSD i que es connecta al microprocessador, i el sensor que necessitem per obtenir les dades desitjades.
Com a sensor utilitzaré el BME280, del que ja he parlat aquí i aquí, que proporciona dades de pressió, temperatura i humitat, i indirectament també d’altura. Són 15 € en el mercat europeu i 5 € en el asiàtic, comprats d’un en un.
Com a microprocessador m’agrada molt el ESP32 muntat en la placa Wemos D1 R32, i és al que me referiré, encara que per guardar les dades en una SD no es necessita que el microprocessador tingui bluetooth ni wifi i, per tant, amb un Arduino Uno és suficient. L’ESP32 són 10 € en el mercat europeu i 6 € en el asiàtic.

Com a lector de targetes utilitzo un SPI comprat en AZDelivery (5 € d’un en un), però que també es pot comprar en aliexpress per 2 €, que llegeix microSD (2G) i MicroSDHC (32G). De targes microSD podeu usar qualsevol de les que tingueu per casa ja que en 2 gigas es poden emmagatzemat milions de dades.
La connexió
El mòdul de la targeta microSD se comunica mitjançant el protocol de comunicació SPI. Es pot connectar al ESP32 usant els pins SPI predeterminats.

De manera que les connexions haurien de quedar com es mostra en el dibuix de sota. Fixeu-vos que tant el lector de targetes SD com el sensor estan connectats a 5V. Encara que diuen que el lector de SDs va a 3,3 i a 5 V, només va a 5V.

S’ha d’introduir la targeta microSD que tingueu en el lector de targetes pressionant una mica la molla que es troba a dins. Hi ha una posició en la que entra i altra en la que no. Prèviament heu de comprovar que la targeta microSD estigui formatada com a FAT32. Això l’heu de fer amb un ordinador que tingui o al que li acobleu un lector de targetes. El profe d’informàtica del centre segur que us el proporciona.
El projecte
El projecte necessita incloure les llibreries del lector de la targeta microSD i del sensor de pressió, temperatura i humitat BME280 per tal de simplificar el codi.
Les llibreries per al lector de targetes venen de sèrie a l’IDE d’Arduino si estan actualitzades les targetes Arduino i esp32. En el cas de les plaques amb microprocessadors esp32 la biblioteca necessària és la esp32 d’Expressif en la seva versió 2.0 en amunt. Per a que l’IDE d’Arduino la trobi ha de tenir guardada la direcció dels paquets d’Expressif en Archivo, Preferencias, URLs adicionales al gestor de placas. Pegueu allí l’adresa https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json i ja podeu instal·lar la placa esp32 d’Expressif i automàticament s’instal·laran les llibreries per al lector de targetes microSD.
El sensor BME280 utilitza diferents llibreries en funció del projecte que es disseny i del protocol (I2C o SPI) que es vulgui utilitzar. Aquí usarem el protocol I2C i la part del projecte del sensor està basada en un exemple de Lambort de Seeedstudio. La llibreria del sensor (Grove_BME280-master.zip) es pot instal·lar amb el gestor de biblioteques del mateix IDE d’Arduino, o es pot baixar de Github. També es necessita la llibreria Wire para I2C que ja està inclosa de sèrie en l’IDE d’Arduino
Com hem vist, el sensor i el lector de targetes es connecten a la placa Wemos D1 R32 que incorpora el microprocessador esp32, per la qual cosa s’han d’instal·lar els seus controladors que no venen de sèrie a l’IDE d’Ardduino, però que s’instal·len fàcilment si ja heu introduït la direcció dels paquets d’Expressif, buscant-la (esp32 de Expressif Systems) en el gestor de plaques.
Per a que apareguin les plaques en el gestor de plaques de l’IDE d’Arduino s’ha de tenir connectada a l’ordinador la placa que interessi, i l’ordinador l’ha de reconèixer. El Windows 10 o 11 reconeix automàticament les plaques Arduino i les assigna un port sèrie, però no és el cas de les plaques amb esp32, i s’ha d’instal·lar prèviament el controlador del circuit integrat de connexió USB CH340/CH341.
La part del codi de l’escriptura de les dades en la targeta microSD del projecte que proposo està basada en la pàgina web de Rui i Sara Santos titulada Guide for MicroSD Card Module using Arduino IDE. Donen permís per utilitzar la informació sempre que se’n faci referència.
El projecte el podeu baixar, descomprimir-lo i obrir (Sketch_Sd_THPA.ino), o copiar directament el codi següent a l’IDE d’Arduino i executar-lo.
/*
Basat en la informació de la pàgina de Rui i Sara Santos
https://RandomNerdTutorials.com/esp32-microsd-card-arduino/
Donen permís per utilitzar la informació sempre que se'n faci referència
*/
//El mòdul de la targeta microSD se comunica mitjançant el protocol de comunicació SPI.
//Es pot connectar al ESP32 usant els pins SPI predeterminats:
//VCC a Vin (5v), CS a GPIO5, MOSI a GPIO23, CLK a GPIO18, MISO a GPIO19, TERRA a GND
// Llibreries per SD card. Pel esp32 venen de sèrie amb la biblioteca de la tarja esp32 d’Expressif 2.0 i amunt
#include "FS.h"
#include "SD.h"
#include <SPI.h>
//Connexions del sensor BME280: Vcc a 3,3V o 5V, GND a Gnd, SCL a SCL, SDA a SDA
//Llibreries pel sensor BME280
//La llibreria del sensor es pot baixar de
//https://github.com/Seeed-Studio/Grove_BME280
//Wire per I2C ja està inclosa de sèrie a l'IDE d'Arduino
#include "Seeed_BME280.h"
#include <Wire.h>
BME280 bme280;
// Variables que ha de llegir el sensor
float temp; //En ºC
float hum; //En %
float pres; //En Pa
float tiempo; // Se define el tiempo como numero con decimales
float tiempoSegundos; // Se define el tiempo en segundos como número con decimales
float altitud; //Se calculará a patir de la presión, en m
String dataMessage;
// Initialize SD card
void initSDCard(){
if (!SD.begin()) {
Serial.println("Card Mount Failed");
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE){
Serial.println("No SD card attached");
return;
}
Serial.print("SD Card Type: ");
if(cardType == CARD_MMC){
Serial.println("MMC");
} else if(cardType == CARD_SD){
Serial.println("SDSC");
} else if(cardType == CARD_SDHC){
Serial.println("SDHC");
} else {
Serial.println("UNKNOWN");
}
uint64_t cardSize = SD.cardSize() / (1024 * 1024);
Serial.printf("SD Card Size: %lluMB\n", cardSize);
}
// Write to the SD card
void writeFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Writing file: %s\n", path);
File file = fs.open(path, FILE_WRITE);
if(!file) {
Serial.println("Failed to open file for writing");
return;
}
if(file.print(message)) {
Serial.println("File written");
} else {
Serial.println("Write failed");
}
file.close();
}
// Append data to the SD card
void appendFile(fs::FS &fs, const char * path, const char * message) {
Serial.printf("Appending to file: %s\n", path);
File file = fs.open(path, FILE_APPEND);
if(!file) {
Serial.println("Failed to open file for appending");
return;
}
if(file.print(message)) {
Serial.println("Message appended");
} else {
Serial.println("Append failed");
}
file.close();
}
void setup() {
Serial.begin(9600);
if(!bme280.init()){
Serial.println("Device error!");
}
tiempo = millis(); //mide el tiempo en milisegundos desde que se pone en marcha Arduino
initSDCard();
// If the data.txt file doesn't exist
// Create a file on the SD card and write the data labels
File file = SD.open("/data.txt");
if(!file) {
Serial.println("File doesn't exist");
Serial.println("Creating file...");
writeFile(SD, "/data.txt", "Epoch Time, Temperature, Humidity, Pressure \r\n");
}
else {
Serial.println("File already exists");
}
file.close();
}
void loop() {
//Get sensor readings
tiempo = millis(); //Actualiza el tiempo actual
tiempoSegundos = tiempo/1000; //cambia los milisegundos a segundos
temp = bme280.getTemperature(); //En ºC
//temp = 1.8*bme280.getTemperature() + 32; //En Fahrenheit
hum = bme280.getHumidity(); //En %
pres = bme280.getPressure(); //En Pa
altitud = bme280.calcAltitude(pres); //En m
//Concatenate all info separated by commas
dataMessage = String(tiempoSegundos) + ";" + String(temp) + ";" + String(hum) + ";" + String(pres) + ";" + String(altitud) + "\r\n";
Serial.print("Saving data: ");
Serial.println(dataMessage);
//Append the data to file
appendFile(SD, "/data.txt", dataMessage.c_str());
//Informació redundant de les dades al port sèrie
Serial.print("Tiempo(s)=");
Serial.print(tiempoSegundos);
Serial.print(", Temperatura=");
Serial.print(temp);
Serial.print(", Humitat=");
Serial.print(hum);
Serial.print(", Pressio=");
Serial.print(pres);
Serial.print(", Altitud=");
Serial.println(altitud);
delay (1000);
}
Encara que no cal, al final del codi he ficat que es puguin veure les dades pel port sèrie de l’ordinador, en cas que estigui la placa connectada. Com he dit al començament la idea és que la placa actuï autònomament rebent el corrent de 5 V d’unes piles o una bateria de les que serveixen per recarregar els telèfons mòbils, com es veu en la fotografia de sota.
