Autonomo I2C with MS5803-14BA

I am trying to read pressure and temperature data from a MS5803-14BA through I2c. Everything works great with an Arduino UNO but when I try in Sodaq Autonomo it seems that I can not send or read data through the Wire library.
My code is (I’ve also tried with other libraries with same error)

/*
Sketch to read a MS5803-14BA pressure sensor, written from scratch.
Will output data to the serial console.
Written by Walt Holm 
Initial revision 10 Oct 2013
Rev 1 12 Oct 2013 -- Implements 2nd order temperature compensation
*/


#include <Wire.h>

const int DevAddress = 0x76;  // 7-bit I2C address of the MS5803

// Here are the commands that can be sent to the 5803

const byte Reset = 0x1E;
const byte D1_256 = 0x40;
const byte D1_512 = 0x42;
const byte D1_1024 = 0x44;
const byte D1_2048 = 0x46;
const byte D1_4096 = 0x48;
const byte D2_256 = 0x50;
const byte D2_512 = 0x52;
const byte D2_1024 = 0x54;
const byte D2_2048 = 0x56;
const byte D2_4096 = 0x58;
const byte AdcRead = 0x00;
const byte PromBaseAddress = 0xA0;



unsigned int CalConstant[8];  // Matrix for holding calibration constants

long AdcTemperature, AdcPressure;  // Holds raw ADC data for temperature and pressure
float Temperature, Pressure, TempDifference, Offset, Sensitivity;
float T2, Off2, Sens2;  // Offsets for second-order temperature computation
 
byte ByteHigh, ByteMiddle, ByteLow;  // Variables for I2C reads

// Program initialization starts here

void setup(){
   SerialUSB.begin(115200);
  SerialUSB.println("Code is running");
  delay(1000);
  Wire.begin();
  SerialUSB.println("initialized I2C");
  delay(10);
  delay(10000);
  
  
  // Reset the device and check for device presence
  
  sendCommand(Reset);
  delay(10);
  delay(1000);
  SerialUSB.println("Device is reset");
   
  // Get the calibration constants and store in array
  
  for (byte i = 0; i < 8; i++)
  {
   sendCommand(PromBaseAddress + (2*i));
   Wire.requestFrom(DevAddress, 2);
   while(Wire.available()){
  ByteHigh = Wire.read();
  ByteLow = Wire.read();
  SerialUSB.print("ByteHigh:");
  SerialUSB.println(ByteHigh);
  SerialUSB.print("ByteLow:");
  SerialUSB.println(ByteLow);
   }
  CalConstant[i] = (((unsigned int)ByteHigh << 8) + ByteLow);
     }
  
  SerialUSB.println("Calibration constants are:");
  
  for (byte i=0; i < 8; i++)
  {
    SerialUSB.println(CalConstant[i]);
  }
  
  SerialUSB.println("");
  SerialUSB.println("");
}


void loop(){

  // Read the Device for the ADC Temperature and Pressure values
  
  sendCommand(D1_512);
  delay(10);
  sendCommand(AdcRead);
  Wire.requestFrom(DevAddress, 3);
  while(Wire.available())
  {
   ByteHigh = Wire.read();
    ByteMiddle = Wire.read();
   ByteLow = Wire.read();
  }
  AdcPressure = ((long)ByteHigh << 16) + ((long)ByteMiddle << 8) + (long)ByteLow;
  
//  SerialUSB.print("D1 is: ");
//  SerialUSB.println(AdcPressure);
  
  sendCommand(D2_512);
  delay(10);
  sendCommand(AdcRead);
  Wire.requestFrom(DevAddress, 3);
  while(Wire.available())
  {
    ByteHigh = Wire.read();
   ByteMiddle = Wire.read();
      ByteLow = Wire.read();
  }
  AdcTemperature = ((long)ByteHigh << 16) + ((long)ByteMiddle << 8) + (long)ByteLow;
 // SerialUSB.print("D2 is: ");
//  SerialUSB.println(AdcTemperature);
  

  // Calculate the Temperature (first-order computation)
  
  TempDifference = (float)(AdcTemperature - ((long)CalConstant[5] << 8));
  Temperature = (TempDifference * (float)CalConstant[6])/ pow(2, 23);
  Temperature = Temperature + 2000;  // This is the temperature in hundredths of a degree C
  
  // Calculate the second-order offsets
  
  if (Temperature < 2000.0)  // Is temperature below or above 20.00 deg C ?
  {
  T2 = 3 * pow(TempDifference, 2) / pow(2, 33);
  Off2 = 1.5 * pow((Temperature - 2000.0), 2);
  Sens2 = 0.625 * pow((Temperature - 2000.0), 2);
  }
  else
  {
  T2 = (TempDifference * TempDifference) * 7 / pow(2, 37);
  Off2 = 0.0625 * pow((Temperature - 2000.0), 2); 
  Sens2 = 0.0;
  }
  
  // Check print the offsets
  
  SerialUSB.println("Second-order offsets are:");
  SerialUSB.println(T2);
  SerialUSB.println(Off2);
  SerialUSB.println(Sens2);
  
  
  // Print the temperature results
  
  Temperature = Temperature / 100;  // Convert to degrees C
  SerialUSB.print("First-Order Temperature in Degrees C is ");
  SerialUSB.println(Temperature);
  SerialUSB.print("Second-Order Temperature in Degrees C is ");
  SerialUSB.println(Temperature - (T2 / 100));
  
  // Calculate the pressure parameters
  
  Offset = (float)CalConstant[2] * pow(2,16);
  Offset = Offset + ((float)CalConstant[4] * TempDifference / pow(2, 7));

  Sensitivity = (float)CalConstant[1] * pow(2, 15);
  Sensitivity = Sensitivity + ((float)CalConstant[3] * TempDifference / pow(2, 8));
  
  // Add second-order corrections
  
  Offset = Offset - Off2;
  Sensitivity = Sensitivity - Sens2;
  
  // Calculate absolute pressure in bars

  Pressure = (float)AdcPressure * Sensitivity / pow(2, 21);
  Pressure = Pressure - Offset;
  Pressure = Pressure / pow(2, 15);
  Pressure = Pressure / 10000;  // Set output to bars;
  
  // Convert to psig and display
  
  Pressure = Pressure - 1.015;  // Convert to gauge pressure (subtract atmospheric pressure)
  Pressure = Pressure * 14.50377;  // Convert bars to psi
  SerialUSB.print("Pressure in psi is: ");
  SerialUSB.println(Pressure);
  SerialUSB.println();
  
  delay(1000);   // pause for 1 second before looping  
}

void sendCommand(byte command){
  byte TransResults;
  Wire.beginTransmission(DevAddress);
  Wire.write(command);
  TransResults= Wire.endTransmission();
  SerialUSB.print("Transmission Results: ");
  SerialUSB.println(TransResults);
}

Every SendMessage returns a “Transmission Results: 3” which from the wire documentation is
3:received NACK on transmit of data

I’ve tried with several SODAQ board versions from 7 to 9, including the Beta with no luck
Any pointers?
Thanks

I would recommend trying the I2cScanner sketch:
http://playground.arduino.cc/Main/I2cScanner

This will allow you to check whether the I2C bus is able to see the device and also to check if there are any address conflicts. You will have to modify that sketch to work on the Autonomo. I believe it will just be a matter of changing the Serial to SerialUSB for the debug output.

Thanks Gabriel.
I’ve uploaded that code on the autonomo and strangely it says it finds a device in every address with no error reported on 0x76; // 7-bit I2C address of the MS5803

That is strange, you should see something like this (this was run using a SodaqONE):

Scanning...
I2C device found at address 0x1E  !
I2C device found at address 0x42  !
done

How do you have the device wired up? I2C requires pull-up resistors on both the SDA and SCL lines.

Thanks for your help.
I’ve added 2.2k pull-up resistors to both SDA and SCL, basically my schematic is similar to https://cdn.sparkfun.com/datasheets/Sensors/Weather/MS5803-14BA_Breakout_v10.pdf
Now, without the device connected to the Autonomo I still get that every address recognizes a device, I don’t know if this is normal behaviour…
With the device connected to the autonomo Grove shield in the SCL/SCA connection I get a “No I2C devices found” with all the addresses returning error = 2 from the wire.endTransmission.
Connected to an Arduino Uno the device initializes OK, the i2Scanner returns error=2 for all the addresses except for 0x76 that returns error=0
I’ve tried with a second Autonomo Board and the problem remains the same

I’ve tried this with an Autonomo. If you have nothing connected to the SDA/SCL lines and they are just floating, then you may see devices recognised on random addresses.

I assume you have the PS pin wired high to select the I2C protocol (as it is working for you with the UNO).

As it appears to work correctly on the AVR platform (UNO etc) but not on the SAMD platform, my suspicion is that the default I2C settings may be different and this device does not like the default SAMD settings.

I’ll look at this further later today.

Thanks a lot, yes PS is connected to VCC, in the Arduino Uno the pressure and temperature readings work OK.

I’ve had a look at the internal workings of both the AVR & SAMD Wire libraries. I cannot see anything that is much different. Both run at 100KHz by default.

You could try different bus frequencies (use Wire.setClock(uint32_t)), but I don’t see that making much of a difference as the datasheet says it supports up to 400KHz.

Can you double check that you have selected the Autonomo or Autonomo BETA as the target board. Also if you are using a grove shield and cable the yellow wire is SCL and white is SDA.

1 Like

Thanks for taking the time to check those things.
Yes, I’ve re-check that I have either Autonomo or Autonomo Beta, even tried again with other library versions with no luck.
The wiring is Ok (even tried to switch the SCL/SDA cables in case something was wrong).
Tried several frequencies using Wire.SetClock with no luck.
If you can think of something else I could tried, please let me know.
Thanks

I’ve ordered a sparkfun breakour board for the MS5803 (https://www.sparkfun.com/products/12909) and hooked it to the Autonomo. It works perfectly so there must have been an error with my previous circuit (probably with the pull up resistors… since with the Arduino it worked OK).
So this is just to report that the MS5803-14BA works perfectly with the Autonomo

Please make sure all your address are ready for 32bit. A lot of libraries need the addition of uint8_t for an int to work on 32 bit.