Hi everyone. I created some code on an ESP32 to acquire info from multiple sensors, and save it to an SD, and I also wanted to send it via LoRa radio. the original code I created worked very well both for saving data on the SD card and for printing them on the serial port quite quickly. the problem is that by introducing LoRa it either slows down the code (if I put the data sending in the main loop) or if I separate it into a separate task on the extra core of the ESP32 it works but after a certain amount of time it signals me on the serial line that errors are writing to the SD and it slows down. How can I solve it? I'm not good at programming....
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BNO055.h>
#include <utility/imumaths.h>
#include <SPI.h>
#include <Adafruit_BME680.h>
#include <TinyGPS++.h>
#include <Adafruit_INA219.h>
#include <SD.h>
#include <LoRa.h>
const int ss = 15; // Pin CS (Chip Select)
const int rst = 33; // Pin RST (Reset)
const int dio0 = 32; // Pin IRQ (Interrupt Request)
byte destination = 0x3D;
// Dichiarazione dei pin
#define BME_SCK 22
#define BME_MOSI 21
#define SEALEVELPRESSURE_HPA (1013.25)
// Dichiarazione degli oggetti dei sensori
Adafruit_BNO055 bno = Adafruit_BNO055(-1, 0x28, &Wire);
Adafruit_BME680 bme;
TinyGPSPlus gps;
Adafruit_INA219 ina219;
// Dichiarazione delle variabili per i dati dei sensori
float roll, pitch, yaw, roll_d, pitch_d, yaw_d;
float temperature, humidity, pressure, altitude;
float lat, lng, alt, speed = 0;
int year, month, day, hour, minute, second = 0;
float shuntvoltage, busvoltage, current_mA, loadvoltage, power_mW;
// Offsets BNO055
int16_t offsets[] = {-26, 13, 0, -1, 0, 0, 2585, -13725, 32700, 1000, 627};
// Variabili per il controllo del tempo
uint32_t lastExecution = 0;
uint32_t currentMillis = 0; // Dichiarazione di currentMillis come variabile globale
uint32_t lastSendTime = 0;
const uint32_t sendInterval = 2000; // Intervallo di invio in millisecondi (2 secondi)
String sensorData;
// Oggetto per la scheda SD
File dataFile;
// Funzione per leggere i dati del sensore BME680 e INA219 (da eseguire sul secondo core)
void readSensorData(void * parameter) {
uint32_t lastSendTime = 0;
const uint32_t sendInterval = 2000; // Intervallo di invio in millisecondi (2 secondi)
while (true) {
// Lettura dei dati del sensore BME680
temperature = bme.readTemperature();
humidity = bme.readHumidity();
pressure = bme.readPressure() / 100;
altitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
// Lettura dei dati del sensore INA219
shuntvoltage = ina219.getShuntVoltage_mV();
busvoltage = ina219.getBusVoltage_V();
current_mA = ina219.getCurrent_mA();
power_mW = ina219.getPower_mW();
loadvoltage = busvoltage + (shuntvoltage / 1000);
// Invio dei dati tramite LoRa ogni 2 secondi
// Trasmissione dei dati tramite LoRa
LoRa.beginPacket();
LoRa.write(destination);
LoRa.print("£ , ");
LoRa.print(altitude);
LoRa.print(" , ");
LoRa.print(lat);
LoRa.print(" , ");
LoRa.print(lng);
LoRa.print(" , ");
LoRa.endPacket();
// Attendi per un secondo prima di eseguire una nuova lettura
delay(3000);
}
}
void setup() {
Serial.begin(115200);
Serial2.begin(9600); // Inizializzazione del GPS su Serial2
delay(1000);
// Inizializzazione del sensore BNO055
if (!bno.begin(OPERATION_MODE_NDOF)) {
Serial.println("Could not find BNO055 sensor!");
while (1);
}
// Calibrazione offset BNO055
adafruit_bno055_offsets_t calibrationData;
calibrationData.accel_offset_x = offsets[0];
calibrationData.accel_offset_y = offsets[1];
calibrationData.accel_offset_z = offsets[2];
calibrationData.gyro_offset_x = offsets[3];
calibrationData.gyro_offset_y = offsets[4];
calibrationData.gyro_offset_z = offsets[5];
calibrationData.mag_offset_x = offsets[6];
calibrationData.mag_offset_y = offsets[7];
calibrationData.mag_offset_z = offsets[8];
calibrationData.accel_radius = offsets[9];
calibrationData.mag_radius = offsets[10];
bno.setSensorOffsets(calibrationData);
// Inizializzazione del sensore BME680
if (!bme.begin()) {
Serial.println("Could not find BME680 sensor!");
while (1);
}
// Configurazione delle impostazioni del sensore BME680
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
// Inizializzazione del INA219
if (!ina219.begin()) {
Serial.println("Failed to find INA219 chip");
while (1) { delay(10); }
}
Serial.println("Measuring voltage and current with INA219 ...");
// Inizializzazione della scheda SD
if (!SD.begin(5)) {
Serial.println("Card failed, or not present");
while (1);
}
// Creazione del file di log
dataFile = SD.open("/datalog.txt", FILE_APPEND);
if (dataFile) {
dataFile.println("NUOVO Avvio test");
dataFile.println("£ , ANNO , MESE , GIORNO , ORA , MINUTO , SECONDI , ROLL , PITCH , YAW , ROLL_D , PITCH_D , YAW_D , LAT , LONG , ALT , SPEED , $");
dataFile.close();
} else {
Serial.println("Errore apertura file in scrittura");
}
// Inizializza il modulo LoRa con i pin specifici
LoRa.setPins(ss, rst, dio0);
if (!LoRa.begin(868E6)) {
Serial.println("Starting LoRa failed!");
while (1); }
LoRa.setTxPower(17); //17 dB (defoult)(max power)
LoRa.setSpreadingFactor(10); //7 defoult (can be set from 6 to 12)
LoRa.setSignalBandwidth(62.5E3); //125E3 defoult (7.8 10.4 15.6 20.8 31.25 41.7 62.5 125 250 500)
LoRa.setCodingRate4(8); //5 defoult (can be from 5 to 8 that correspond to 4/5 and 4/8)
// Creazione di un task separato per leggere i dati del sensore BME680 e INA219 (Core 1)
xTaskCreatePinnedToCore(
readSensorData, // Funzione da eseguire
"readSensorData", // Nome del task
10000, // Dimensione dello stack del task
NULL, // Parametro passato alla funzione
1, // Priorità del task
NULL, // Handle del task (opzionale)
1 // Core su cui eseguire il task (Core 1)
);
}
void loop() {
currentMillis = millis(); // Aggiorna il valore di currentMillis
// Controllo del tempo per la lettura del sensore BNO055 ogni 100 millisecondi
invio();
}
void invio(){
if (currentMillis - lastExecution >= 100) {
lastExecution += 100;
// Lettura dei dati del sensore BNO055
imu::Vector<3> euler = bno.getVector(Adafruit_BNO055::VECTOR_EULER);
yaw = euler.x();
roll = euler.y();
pitch = -euler.z();
imu::Vector<3> gyro = bno.getVector(Adafruit_BNO055::VECTOR_GYROSCOPE);
yaw_d = gyro.z();
roll_d = gyro.y();
pitch_d = gyro.x();
// Lettura dei dati del GPS
while (Serial2.available() > 0) {
if (gps.encode(Serial2.read())) {
if (gps.location.isValid()) {
lat = gps.location.lat();
lng = gps.location.lng();
}
if (gps.altitude.isValid()) {
alt = gps.altitude.meters();
}
if (gps.speed.isValid()) {
speed = gps.speed.kmph();
}
if (gps.date.isValid() && gps.time.isValid()) {
year = gps.date.year();
month = gps.date.month();
day = gps.date.day();
hour = gps.time.hour();
minute = gps.time.minute();
second = gps.time.second();
}
}
}
// Creazione della stringa con i dati dei sensori
sensorData = "&, ";
sensorData += String(roll) + "," + String(pitch) + "," + String(yaw) + ",";
sensorData += String(roll_d) + "," + String(pitch_d) + "," + String(yaw_d) + ",";
sensorData += String(temperature) + "," + String(pressure) + "," + String(humidity) + "," + String(altitude) + ",";
sensorData += String(year) + "," + String(month) + "," + String(day) + "," + String(hour) + "," + String(minute) + "," + String(second) + ",";
sensorData += String(lat) + "," + String(lng) + "," + String(alt) + "," + String(speed) + ",";
sensorData += String(busvoltage) + "," + String(shuntvoltage) + "," + String(loadvoltage) + "," + String(current_mA) + "," + String(power_mW) + ", §";
// Stampa dei dati dei sensori
Serial.println(sensorData);
// Salvataggio dei dati su scheda SD
dataFile = SD.open("/datalog.txt", FILE_APPEND);
if (dataFile) {
dataFile.println(sensorData);
} else {
Serial.println("Errore apertura file in scrittura");
}
}
}