Hello everyone,
I hope this message finds you well.
Over the last couple of days, I've been working on writing code to make use of the MS5611 sensor via the I2C protocol. However, I've been encountering some odd readings for the pressure. As for the temperature, it seems alright, although I've noticed that the value decreases rapidly when I touch the sensor.
Here's the code I've written so far:
#include "Particle.h"
#include "Wire.h"
#define MS5611_ADDR 0x77 // I2C address of the MS5611
// MS5611 commands
#define MS5611_CMD_RESET 0x1E
#define MS5611_CMD_CONV_D1_256 0x40
#define MS5611_CMD_CONV_D2_256 0x50
#define MS5611_CMD_ADC_READ 0x00
// Calibration coefficients
uint16_t C1, C2, C3, C4, C5, C6;
void setup() {
Wire.begin();
Serial.begin(9600);
delay(1000); // Wait for sensor to power up
resetSensor();
if (!readCalibrationCoefficients()) {
Serial.println("Failed to read calibration coefficients! Check connections.");
while (true); // Hang here if calibration fails
}
}
void loop() {
float pressure, temperature;
if (readPressureAndTemperature(pressure, temperature)) {
Particle.publish("Pressure: ", String(pressure));
Particle.publish("Temperature: ", String(temperature));
Serial.print("Pressure: ");
Serial.print(pressure, 2);
Serial.println(" mbar");
Serial.print("temp: ");
Serial.print(temperature, 2);
Serial.println(" C");
} else {
Serial.println("Failed to read pressure and temperature! Retrying...");
delay(1000); // delay before retrying
}
delay(1000); // delay between readings
}
void resetSensor() {
Wire.beginTransmission(MS5611_ADDR);
Wire.write(MS5611_CMD_RESET);
Wire.endTransmission();
delay(3); // reset takes 2.8ms
}
bool readCalibrationCoefficients() {
// Read C1 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xA2); // address of first coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C1 = (Wire.read() << 8) | Wire.read();
// Read C2 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xA4); // address of second coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C2 = (Wire.read() << 8) | Wire.read();
// Read C3 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xA6); // address of third coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C3 = (Wire.read() << 8) | Wire.read();
// Read C4 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xA8); // address of fourth coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C4 = (Wire.read() << 8) | Wire.read();
// Read C5 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xAA); // address of fifth coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C5 = (Wire.read() << 8) | Wire.read();
// Read C6 coefficient
Wire.beginTransmission(MS5611_ADDR);
Wire.write(0xAC); // address of sixth coefficient
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 2);
C6 = (Wire.read() << 8) | Wire.read();
// Check if all coefficients are non-zero
if (C1 == 0 || C2 == 0 || C3 == 0 || C4 == 0 || C5 == 0 || C6 == 0) {
return false; // Calibration failed
}
return true; // Calibration successful
}
bool readPressureAndTemperature(float& pressure, float& temperature) {
// Start pressure conversion
Wire.beginTransmission(MS5611_ADDR);
Wire.write(MS5611_CMD_CONV_D1_256);
Wire.endTransmission();
delay(10); // conversion time for 256 oversampling is 0.9ms
// Read pressure ADC
Wire.beginTransmission(MS5611_ADDR);
Wire.write(MS5611_CMD_ADC_READ);
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 3);
uint32_t pressureADC = 0;
pressureADC |= (Wire.read() << 16);
pressureADC |= (Wire.read() << 8);
pressureADC |= Wire.read();
// Start temperature conversion
Wire.beginTransmission(MS5611_ADDR);
Wire.write(MS5611_CMD_CONV_D2_256);
Wire.endTransmission();
delay(10); // conversion time for 256 oversampling is 0.9ms
// Read temperature ADC
Wire.beginTransmission(MS5611_ADDR);
Wire.write(MS5611_CMD_ADC_READ);
Wire.endTransmission();
Wire.requestFrom(MS5611_ADDR, 3);
uint32_t temperatureADC = 0;
temperatureADC |= (Wire.read() << 16);
temperatureADC |= (Wire.read() << 8);
temperatureADC |= Wire.read();
// Check if any of the ADC readings are zero
if (pressureADC == 0 || temperatureADC == 0) {
return false; // Sensor reading error
}
// Calculate temperature
int32_t dT = temperatureADC - C5 * (1 << 8);
temperature = 2000 + ((dT * C6) / (1 << 23));
temperature /= 100.0; // Convert to degrees Celsius
// Calculate temperature compensated pressure
int64_t off = C2 * (1 << 16) + (C4 * dT) / (1 << 7);
int64_t sens = C1 * (1 << 15) + (C3 * dT) / (1 << 8);
int32_t pressureComp = (pressureADC * sens / (1 << 21) - off) / (1 << 15);
pressure = pressureComp / 100.0; // Convert to mbar
return true; // Readings successful
}
Here are the results observed when viewing the serial monitor on Arduino or the Particle dashboard:
And here are the results obtained when utilizing an Arduino Uno with a library:
I would greatly appreciate any guidance or suggestions on how to effectively implement I2C communication for this setup. If anyone has experience with similar projects or has insights into alternative approaches, your input would be invaluable.
Thank you in advance for your assistance.
Best regards,
Nayel