I am using an arduino Uno R3 board and three sensors: MPU6050, GPS-NEO6MV2 and a Micro SD reader. It works all properly , but when I put the function to save the data into the sd card it crashes or it start to loop the setup that doesn't make any sense. It's my first arduino project so i am a beginner, if anybody can help me I would be so greatfull.
you are just too low in memory, the uno is struggling. (don't you get a warning when you compile?)
try replacing all the Serial.print("xxxx: "); by Serial.print(F("xxxx: ")); as well as the dataFile.print("xxx"); by dataFile.print(F("xxx"));
➜ that will put all the text in flash memory, that might be enough to free up some memory to accommodate the 512 bytes buffer required by the SD card (your UNO only has 2KB of SRAM) and the rest of your code
even if you have 1000 of these prints. the string in between the double quotes is a string literal, a const char *, the compiler knows it can't change, so if it spots the same string literal elsewhere, it will reuse it.
➜ the compiler will notice 'F' 'r' 'a' 'n' 'c' 'e' '\0' are shared bits of memory and so text2 will point within text1 so text2 will not use extra memory for its content (just for the pointer)
I think is a problem beetween the sd activity and the mpu6050 because in this code when I add the mpu6050 library and the mpu6050.calcGyroOffsets(true) it doesn't work anymore.`
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <MPU6050_tockn.h>
TinyGPSPlus gps;
MPU6050 mpu6050(Wire);
SoftwareSerial gpsSerial(4, 3); // Imposta i pin RX (4) e TX (3) per la comunicazione GPS
File dataFile;
void setup() {
delay(2000);
Serial.begin(9600);
gpsSerial.begin(9600);
mpu6050.begin();
mpu6050.calcGyroOffsets(true);
// Inizializza la scheda SD
if (SD.begin(10)) {
Serial.println("Scheda SD inizializzata con successo.");
} else {
Serial.println("Errore nell'inizializzazione della scheda SD.");
}
dataFile = SD.open("gpsdata.csv", FILE_WRITE); // Apre il file CSV
if (dataFile) {
dataFile.println("Latitudine,Longitudine,Data,Time"); // Intestazione del file CSV
dataFile.close();
}
}
void loop() {
static unsigned long t1 = 0;
double lat = 0.0; // Valore di default per latitudine
double lon = 0.0; // Valore di default per longitudine
int hour = 0; // Valore di default per l'ora
int minute = 0; // Valore di default per i minuti
int second = 0; // Valore di default per i secondi
int year = 0; // Valore di default per l'anno
int month = 0; // Valore di default per il mese
int day = 0; // Valore di default per il giorno
while (gpsSerial.available() > 0) {
if (gps.encode(gpsSerial.read())) {
if (gps.location.isValid()) {
if (millis() - t1 >= 1000) {
t1 = millis();
lat = gps.location.lat();
lon = gps.location.lng();
hour = gps.time.hour() + 2;
minute = gps.time.minute();
second = gps.time.second();
year = gps.date.year();
month = gps.date.month();
day = gps.date.day();
// Stampa le coordinate su Arduino
Serial.print("Latitudine: ");
Serial.println(lat, 6);
Serial.print("Longitudine: ");
Serial.println(lon, 6);
Serial.print("Data: ");
Serial.print(day);
Serial.print("/");
Serial.print(month);
Serial.print("/");
Serial.print(year);
Serial.print(" ");
Serial.print("Ora locale: ");
if (hour >= 10) {
Serial.print(hour);
} else if (hour >= 1 && hour <= 9) {
Serial.print("0");
Serial.print(hour);
} else {
Serial.print("00");
}
Serial.print(":");
if (minute >= 10) {
Serial.print(minute);
} else if (minute >= 1 && minute <= 9) {
Serial.print("0");
Serial.print(minute);
} else {
Serial.print("00");
}
Serial.print(":");
if (second >= 10) {
Serial.println(second);
} else if (second >= 1 && second <= 9) {
Serial.print("0");
Serial.println(second);
} else {
Serial.println("00");
}
}
// Salva le coordinate sul file CSV
dataFile = SD.open("gpsdata.csv", FILE_WRITE);
if (dataFile) {
dataFile.print(lat, 6);
dataFile.print(",");
dataFile.print(lon, 6);
dataFile.print(",");
dataFile.print(day);
dataFile.print("/");
dataFile.print(month);
dataFile.print("/");
dataFile.print(year);
dataFile.print(",");
dataFile.print(hour);
dataFile.print(":");
if (minute >= 10) {
dataFile.print(minute);
} else if (minute >= 1 && minute <= 9) {
dataFile.print("0");
dataFile.print(minute);
} else {
dataFile.print("00");
}
dataFile.print(":");
if (second >= 10) {
dataFile.print(second);
} else if (second >= 1 && second <= 9) {
dataFile.print("0");
dataFile.print(second);
} else {
dataFile.print("00");
}
dataFile.println();
dataFile.close();
}
}
}
}
}
There might be timing conflicts where things would get slow or you would lose GPS data on software serial because the buffer would fill up but that's not your main issue. Memory is. Get a more capable arduino.
int hour = 0;
int minute = 0;
int second = 0;
int year = 0;
int month = 0;
int day = 0;
Only year needs to be an int, the rest can be byte.
Since you only use Serial to send data, and only receive data from the GPS on SoftwareSerial, it is possible to eliminate the SoftwareSerial and instead use Serial to receive from the GPS (there is a 1K Ohm resistor between the Rx pin of the atmega328 and the Tx pin of the atmega16u2 Serial-to-USB chip, so the Tx from the GPS can generally safely override this signal). That will eliminate the 128 bytes of memory needed for the Rx and Tx buffers for SoftwareSerial. Note that there is no connection to the Rx of the GPS module, and doing this will require disconnecting the Tx from the GPS during an upload.