Hi Everyone,
Secondary or High school student here running a project with Arduino with some of my friends. We have an a working ESP32 with BME280 (so temp. pressure, humidity all fine in the serial monitor). The thing is we have a mpu9250 that is not giving readings (just N/As) and we are at a bit of a loss.
Can anyone wiser than us see anything wrong with our code. Our teacher thinks it may be a faulty sensor but we don't have a spare so hoping that's not the problem.
We are using libraries as follows
SD by Arduino, Adafruit BME280, Adafruit BusIO, Adafruit GFX, Adafruit GPS, Adafruit ssf1306, Adafruit Unified Sensor, Bolder Flight Systems Eigen, Bolder Flight Systems MPU9250, Bolder Flight Systems Unit Conversions.
Our code is below.
Thanks for reading this and thanks for any advice!
CODE-
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>
#include <Adafruit_GPS.h>
#include <mpu9250.h>
#include <HardwareSerial.h>
#include "driver/ledc.h"
#define SEALEVELPRESSURE_HPA (1013.25)
Adafruit_BME280 bme; // I2C
float BMEPressure, BMETemp, BMEAltitude, BMEHumidity;
// MPU9250 and Magnetometer
#define MPU_ADDR 0x68
#define ACCEL_XOUT_H 0x3B
#define GYRO_XOUT_H 0x43
#define MAGNETOMETER_ADDR 0x0C
#define MAGNETOMETER_XOUT 0x03
float ax, ay, az, gx, gy, gz;
float ax_ms2, ay_ms2, az_ms2, gx_dps, gy_dps, gz_dps;
float magX, magY, magZ;
float accelBiasX = 0, accelBiasY = 0, accelBiasZ = 0;
float gyroBiasX = 0, gyroBiasY = 0, gyroBiasZ = 0;
#define GPSSerial Serial2
Adafruit_GPS GPS(&GPSSerial);
float deg_lat, deg_lon, Altitude, Speed;
int Satellites;
const int TONE_OUTPUT_PIN = 32;
const int TONE_PWM_CHANNEL = 0;
unsigned long timer;
void calibrateIMU(int samples = 1000);
void scanI2C();
void Read_BME();
void Read_IMU();
void Start_GPS();
void Print_results();
void tone_gen();
void initializeMPU9250();
void setup() {
Serial.begin(9600);
bool status = bme.begin(0x76);
if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1);
}
GPS.begin(9600);
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA);
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
delay(1000);
Wire.begin();
initializeMPU9250();
calibrateIMU();
scanI2C();
tone_gen();
timer = millis();
}
void loop() {
Read_BME();
Read_IMU();
Start_GPS();
if (millis() - timer > 1000) {
timer = millis();
Print_results(); // Print readings with labels
}
delay(500);
}
void Read_BME() {
BMETemp = bme.readTemperature() - 2.0; // Apply temperature offset
BMEPressure = bme.readPressure() / 100.0;
BMEAltitude = bme.readAltitude(SEALEVELPRESSURE_HPA);
BMEHumidity = bme.readHumidity() * 1.8; // Adjust humidity correction factor
}
void Read_IMU() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(ACCEL_XOUT_H);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 6);
if (Wire.available() == 6) {
ax = (Wire.read() << 8) | Wire.read();
ay = (Wire.read() << 8) | Wire.read();
az = (Wire.read() << 8) | Wire.read();
}
Wire.beginTransmission(MPU_ADDR);
Wire.write(GYRO_XOUT_H);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 6);
if (Wire.available() == 6) {
gx = (Wire.read() << 8) | Wire.read();
gy = (Wire.read() << 8) | Wire.read();
gz = (Wire.read() << 8) | Wire.read();
}
// Sanity check for gyro values to avoid erroneous high readings
if (abs(gx) > 500 || abs(gy) > 500 || abs(gz) > 500) {
gx = 0;
gy = 0;
gz = 0;
}
Wire.beginTransmission(MAGNETOMETER_ADDR);
Wire.write(MAGNETOMETER_XOUT);
Wire.endTransmission(false);
Wire.requestFrom(MAGNETOMETER_ADDR, 6);
if (Wire.available() == 6) {
magX = ((Wire.read() << 8) | Wire.read()) * 0.15; // Apply scaling factor
magY = ((Wire.read() << 8) | Wire.read()) * 0.15; // Adjust based on sensitivity
magZ = ((Wire.read() << 8) | Wire.read()) * 0.15;
}
// Handle cases where magnetometer reads all zeros
if (magX == 0 && magY == 0 && magZ == 0) {
magX = magY = magZ = NAN; // Set to NaN if not reading correctly
}
ax_ms2 = (ax - accelBiasX) / 16384.0 * 9.81;
ay_ms2 = (ay - accelBiasY) / 16384.0 * 9.81;
az_ms2 = (az - accelBiasZ) / 16384.0 * 9.81;
gx_dps = (gx - gyroBiasX) / 131.0;
gy_dps = (gy - gyroBiasY) / 131.0;
gz_dps = (gz - gyroBiasZ) / 131.0;
}
void initializeMPU9250() {
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x6B);
Wire.write(0x00);
Wire.endTransmission();
delay(100);
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1C);
Wire.write(0x00);
Wire.endTransmission();
Wire.beginTransmission(MPU_ADDR);
Wire.write(0x1B);
Wire.write(0x00);
Wire.endTransmission();
Wire.beginTransmission(MAGNETOMETER_ADDR);
Wire.write(0x0A); // Magnetometer control register
Wire.write(0x16); // Continuous measurement mode 2
Wire.endTransmission();
delay(100);
}
void Print_results() {
// Print labeled readings
Serial.print("Pressure (hPa): "); Serial.print(BMEPressure); Serial.print(", ");
Serial.print("Temperature (°C): "); Serial.print(BMETemp); Serial.print(", ");
Serial.print("Altitude (m): "); Serial.print(BMEAltitude); Serial.print(", ");
Serial.print("Humidity (%): "); Serial.print(BMEHumidity); Serial.print(", ");
Serial.print("Accel X (m/s²): "); Serial.print(ax_ms2); Serial.print(", ");
Serial.print("Accel Y (m/s²): "); Serial.print(ay_ms2); Serial.print(", ");
Serial.print("Accel Z (m/s²): "); Serial.print(az_ms2); Serial.print(", ");
Serial.print("Gyro X (°/s): "); Serial.print(gx_dps); Serial.print(", ");
Serial.print("Gyro Y (°/s): "); Serial.print(gy_dps); Serial.print(", ");
Serial.print("Gyro Z (°/s): "); Serial.print(gz_dps); Serial.print(", ");
Serial.print("Magnetometer X (µT): ");
if (isnan(magX)) Serial.print("N/A");
else Serial.print(magX);
Serial.print(", Magnetometer Y (µT): ");
if (isnan(magY)) Serial.print("N/A");
else Serial.print(magY);
Serial.print(", Magnetometer Z (µT): ");
if (isnan(magZ)) Serial.print("N/A");
else Serial.print(magZ);
Serial.print(", ");
Serial.print("Latitude: "); Serial.print(deg_lat, 6); Serial.print(", ");
Serial.print("Longitude: "); Serial.print(deg_lon, 6); Serial.print(", ");
Serial.print("Altitude (GPS): "); Serial.print(Altitude); Serial.print(", ");
Serial.print("Speed (m/s): "); Serial.print(Speed); Serial.print(", ");
Serial.print("Satellites: "); Serial.println(Satellites);
}
void tone_gen() {
ledcAttachPin(TONE_OUTPUT_PIN, TONE_PWM_CHANNEL);
for (int x = 0; x < 5; x++) {
ledcWriteTone(TONE_PWM_CHANNEL, 1200);
delay(100);
ledcWriteTone(TONE_PWM_CHANNEL, 1800);
delay(100);
}
ledcDetachPin(TONE_OUTPUT_PIN);
}
void scanI2C() {
for (byte addr = 1; addr < 127; addr++) {
Wire.beginTransmission(addr);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.print("I2C device found at 0x");
if (addr < 16) Serial.print("0");
Serial.println(addr, HEX);
}
}
}
void calibrateIMU(int samples) {
long sumAx = 0, sumAy = 0, sumAz = 0;
long sumGx = 0, sumGy = 0, sumGz = 0;
for (int i = 0; i < samples; i++) {
Wire.beginTransmission(MPU_ADDR);
Wire.write(ACCEL_XOUT_H);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 6);
int16_t rawAx = (Wire.read() << 8) | Wire.read();
int16_t rawAy = (Wire.read() << 8) | Wire.read();
int16_t rawAz = (Wire.read() << 8) | Wire.read();
Wire.beginTransmission(MPU_ADDR);
Wire.write(GYRO_XOUT_H);
Wire.endTransmission(false);
Wire.requestFrom(MPU_ADDR, 6);
int16_t rawGx = (Wire.read() << 8) | Wire.read();
int16_t rawGy = (Wire.read() << 8) | Wire.read();
int16_t rawGz = (Wire.read() << 8) | Wire.read();
sumAx += rawAx;
sumAy += rawAy;
sumAz += rawAz;
sumGx += rawGx;
sumGy += rawGy;
sumGz += rawGz;
delay(3);
}
accelBiasX = sumAx / (float)samples;
accelBiasY = sumAy / (float)samples;
accelBiasZ = (sumAz / (float)samples) - 16384.0;
gyroBiasX = sumGx / (float)samples;
gyroBiasY = sumGy / (float)samples;
gyroBiasZ = sumGz / (float)samples;
Serial.println("IMU calibration complete.");
Serial.print("Accel Bias Z: "); Serial.println(accelBiasZ);
}
void Start_GPS() {
while (GPS.available()) {
char c = GPS.read();
if (GPS.newNMEAreceived()) {
if (GPS.parse(GPS.lastNMEA())) {
deg_lat = GPS.latitudeDegrees;
deg_lon = GPS.longitudeDegrees;
Altitude = GPS.altitude;
Speed = GPS.speed;
Satellites = GPS.satellites;
}
}
}
}