I am very new to Arduino and have only started doing projects about a month and a half ago. Apologies in advance if this has been answered countless times, but I couldn't figure this out from what I've already looked at.
I am currently trying to read data from an MPU6050 that is connected to an Elegoo Uno R3, and then send that data to an Arduino Mega 2560, and finally save that data onto an SD Card which is connected to the Arduino Mega.
How fast I need to record this data is not yet confirmed, but it needs to be at least a few times a second.
I am fairly certain all my problems lie in the receiver code, but I'll post the sender as well. Using the code below, only pieces of my data are printed (attached is serial monitor) and then after awhile, my SD card fails to open.
Do I need to incorporate a buffer, or a ring buffer? If so, how would I do that for this situation. Also, I can only write to the SD Card in 512 byte blocks, correct? Is this why it fails to open after a certain amount of time?
If anyone could help me with any of these questions, I'd be very grateful!
SENDER (ELEGOO UNO R3):
// Includes
#include <Wire.h> // I2C library
#include <math.h> // for atan2(double y, double x)
#include <SD.h> // Load the SD library
#include <SPI.h> // Load the SPI communication library
// Defines
#define DegConvert 57.29577951
// Global Variables
const int MPU1_addr = 0x68; // 0110 1000 from data sheet. AD0 is grounded Sec. 9.2
double accelX, accelY, accelZ;
double gForceX, gForceY, gForceZ;
double gyroX, gyroY, gyroZ;
double rotX, rotY, rotZ;
double Temp, TempF, RawTemp;
double roll;
unsigned long timestamp;
void setup()
{
Serial.begin(9600);
Wire.begin(); // join the I2C bus
setupMPU();
}
void loop()
{
timestamp = millis();
recordAccelRegisters();
recordGyroRegisters();
recordTempRegisters();
printData();
delay(250);
}
void setupMPU()
{
Wire.beginTransmission(MPU1_addr); //MPU1_addr = 0x68
Wire.write(0x6B); //Accessing the register 0x6B - Power Management (Sec. 4.28)
Wire.write(0x00); //Setting SLEEP register to 0. (Required to wake up MPU; see Note on p. 9)
Wire.endTransmission();
Wire.beginTransmission(MPU1_addr); //I2C address of the MPU
Wire.write(0x1B); //Accessing the register 0x1B - Gyroscope Configuration (Sec. 4.4)
Wire.write(0x00); //Setting the gyro to full scale +/- 250deg./s
Wire.endTransmission();
Wire.beginTransmission(MPU1_addr); //I2C address of the MPU
Wire.write(0x1C); //Accessing the register 0x1C - Acccelerometer Configuration (Sec. 4.5)
Wire.write(0x00); //Setting the accel to +/- 2g
Wire.endTransmission();
}
void recordAccelRegisters()
{
Wire.beginTransmission(MPU1_addr); //I2C address of the MPU
Wire.write(0x3B); //Starting register for Accel Readings
Wire.endTransmission();
Wire.requestFrom(MPU1_addr, 6, true); //Request Accel Registers (0x3B - 0x40)
//while(Wire.available() < 6);
accelX = Wire.read() << 8 | Wire.read(); //0x3B (ACCEL_XOUT_H) and 0x3C (ACCEL_XOUT_L)
accelY = Wire.read() << 8 | Wire.read(); //0x3D (ACCEL_YOUT_H) and 0x3E (ACCEL_YOUT_L)
accelZ = Wire.read() << 8 | Wire.read(); //0x3F (ACCEL_ZOUT_H) and 0x40 (ACCEL_ZOUT_L)
processAccelData();
}
void processAccelData() {
gForceX = accelX / 16384.0; // +/- 2g setting. 16834/°/g Sec 4.17 in datasheet
gForceY = accelY / 16384.0;
gForceZ = accelZ / 16384.0;
}
void recordGyroRegisters()
{
Wire.beginTransmission(MPU1_addr); //I2C address of the MPU
Wire.write(0x43); //Starting register for Gyro Readings
Wire.endTransmission();
Wire.requestFrom(MPU1_addr, 6, true); //Request Gyro Registers (0x43 - 0x48)
//while(Wire.available() < 6);
gyroX = Wire.read() << 8 | Wire.read(); //0x43 (GYRO_XOUT_H) and 0x44 (GYRO_XOUT_L)
gyroY = Wire.read() << 8 | Wire.read(); //0x45 (GYRO_YOUT_H) and 0x46 (GYRO_YOUT_L)
gyroZ = Wire.read() << 8 | Wire.read(); //0x47 (GYRO_ZOUT_H) and 0x48 (GYRO_ZOUT_L)
processGyroData();
}
void processGyroData() {
rotX = gyroX / 131.0; // The +/- 250°/sec setting --> Maximum detection = 41.67 RPM
rotY = gyroY / 131.0;
rotZ = gyroZ / 131.0;
roll = atan2(rotZ, rotY) * DegConvert;
}
void recordTempRegisters() {
Wire.beginTransmission(MPU1_addr); //I2C address of the MPU
Wire.write(0x41); //Accessing the register 0x41 - Temperature Registers (Sec. 4.18)
Wire.endTransmission();
Wire.requestFrom(MPU1_addr, 2, true); // Stop transmission after request
RawTemp = Wire.read() << 8 | Wire.read(); // Store the upper and lower byte into RawTemp
processTemp();
}
void processTemp() {
Temp = ((RawTemp / 340.0) + 36.532); // From section 4.18 in Register Map Datasheet
TempF = (Temp * (9.0 / 5.0)) + 32; // Temp in F
}
void printData() {
Serial.print(rotX);
Serial.print(",");
Serial.print(rotY);
Serial.print(",");
Serial.print(rotZ);
Serial.print(",");
Serial.print(gForceX);
Serial.print(",");
Serial.print(gForceY);
Serial.print(",");
Serial.print(gForceZ);
Serial.print(",");
Serial.print(Temp);
Serial.print(",");
Serial.println(timestamp);
}
RECEIVER (ARDUINO MEGA 2560):
if (Serial3.available() > 0) {
mySensorData = SD.open("Test.txt", FILE_WRITE);
if (mySensorData) // If SD opens correctly, go into this conditional
{
while (Serial3.available() > 0)
{
reading = Serial3.read();
mySensorData.print(reading);
Serial.print(reading);
}
} else {
Serial.println("File failed to open");
}
}
mySensorData.close();
delay(250);
}