i2c Pressure Sensor Reading Help?

Status
Not open for further replies.
You'll want to use the Wire library:
https://www.arduino.cc/en/Reference/Wire

If you search by the sensor name and "github arduino" you'll find some arduino drivers for the sensor. I've never used that sensor and I haven't reviewed the libraries, so I can't say whether they are good or not, but that's a general strategy for finding open-source sensor libraries.
 
I can't help with a walk through - I don't have the sensor to test a driver against and my work is very busy at the moment. Maybe someone else on the forum can help?

I wouldn't use the library you found, that's for the PX4, rather then the Arduino. Here's what looks like an Arduino compatible library that came up when I searched:
https://github.com/yubox-node-org/MS5525DSO-Arduino

I would read through the code, read through the datasheet, and read the Arduino Wire API documentation to see if you can understand what's going on. Specific questions (i.e. why is XX line of code used?) are generally easier for people on the forum to answer.
 
Which Teensy are you using?
For most Teensys, you would normally connect SDA to pin 18 and SCL to pin 19. You will also need 3.3k pullup resistors on both SDA and SCL. Plus power and ground of course.
Then run an I2c scanner to make sure that the Teensy can "see" the device. There is a scanner in the IDE at File|Examples|Wire|Scanner
This should find and print the I2C address of your device.

Pete
 
First, run File > Examples > Wire > Scanner. This will test whether your device is responding and you can easily confirm what I2C address it uses. If the scanner doesn't detect your sensor, there is no point going any further. Get it working with the scanner first.


Do you think you could walk me through it once, so I and anyone else having problems learning about this can have a resource?

I'm going to make a quick attempt to walk you though using the Wire library, but first I want to be absolutely clear that many examples and projects and libraries use Wire to access devices very similar to this sensor. Plenty of resources already exist. I want to help you, but I also want to dis-spell any notion that resources are somehow lacking, so I'm going to show how a couple of the examples are modified to work...


On the PJRC site, you can find this page for the Wire library.

https://www.pjrc.com/teensy/td_libs_Wire.html

Scroll down to "Example Program". The code I'm about to explain is from that page, so please if you haven't read the example on that page, do so now.


Now, to apply that EEPROM example to this sensor, here the info from page 12 of the datasheet.

screenshot.png

To send this sensor a command like Figure 13, you would use the same code as the EERPOM example, but you would transmit only 1 byte.

Here is the EEPROM example code:

Code:
  // set the 24C256 eeprom address to 0
  Wire.beginTransmission(80);
  Wire.write(0);  // address high byte
  Wire.write(0);  // address low byte
  Wire.endTransmission();

To adapt this for your sensor, just replace the address with whatever address the Scanner example found (I'm going to guess it's 118 for the sake of this message). Then change the transmitted byte for the command you want to send, and delete the second write line since this sensor expects a 1 byte command rather than 2 bytes for the address of a 24C256 EEPROM. Also update the comments....

Code:
  // send "initiate a pressure conversion" command
  Wire.beginTransmission(118);
  Wire.write(0x48);  // page 12 says "0 1 0 0 1 0 0 0"
  Wire.endTransmission();

Hopefully you can see this is the same as the 24C256 EEPROM, only with the address and data byte changed.



Likewise to read data from this sensor, you would use basically the same code as the example, but you want to read 3 bytes. Since the EEPROM example reads only 1 byte, I'm going to instead copy from File > Examples > Wire > master_reader. This example reads 8 bytes. Here is the example code:

Code:
  Wire.requestFrom(8, 6);   // request 6 bytes from slave device #8

  while(Wire.available()) { // slave may send less than requested
    char c = Wire.read();   // receive a byte as character
    Serial.print(c);        // print the character
  }

  Serial.println();

To adapt this for your sensor, change the address and request only 3 bytes. Also change the variable to "int" type, so the results print to the Arduino Serial Monitor as numbers rather than characters.

Code:
  Wire.requestFrom(118, 3);   // request 3 bytes from pressure sensor

  while(Wire.available()) { // slave may send less than requested
    int n = Wire.read();   // receive a byte an integer
    Serial.print(n);        // print the number
  }

  Serial.println();


Hopefully with this you can see how the examples for the Wire library and code on the web page are meant to help you.
 
In addition to the walk through that @PaulStoffregen provided on using the wire library it becomes easier when you use a Arduino library for the sensor. As @brtaylor mention if you download and open the zip file from the link provided:
https://github.com/yubox-node-org/MS5525DSO-Arduino

There are three ways to install the library that you just downloaded:
1. Using the Arduino IDE's library manager
2. Installing from a zip file
3. Manual install.

A good resource is provided by DigiKey at https://www.digikey.com/en/maker/blogs/2018/how-to-install-arduino-libraries that walks you through the process of installing a library. In your case I would use method 2, Installing from a zip file.

To use the example file from the library next open the Arduino IDE, go to FILE->EXAMPLES and scroll down to the library that you just installed - in this case MS5525DSO-Arduino, select it and you should see the example. Select the example and the IDE will load the example. Then compile and upload to the your Teensy and try it out.
 
I tried using your requestFrom method to read the pressure, but I wasn't receiving anything. I decided to use that library mjs513 posted, but it's giving me a pressure of 140 and a temp of over 20k Celsius which obviously isn't right. How do I calibrate it?
 
I tried using your requestFrom method to read the pressure, but I wasn't receiving anything. I decided to use that library mjs513 posted, but it's giving me a pressure of 140 and a temp of over 20k Celsius which obviously isn't right. How do I calibrate it?

Unfortunately I don't have one of those press/temp sensors so not sure I can be of much more help. At this point you are probably going to have read the RM (https://www.te.com/commerce/Documen...EnglishENG_DS_MS5525DSO_C1.pdfCAT-BLPS0003) and bounce it against the library or write your own using the methods that @Paul described
 
Hmm. Man this shit is complicated. Looking at the library and datasheet would you be able to guide me on how to calibrate it? It's hard for me to understand reading it in c.
 
Copy and paste all the output from the example code including the list of coefficients that are printed before it gets the temperature and pressure.

Pete
 
Copy and paste all the output from the example code including the list of coefficients that are printed before it gets the temperature and pressure.

Pete

INFO: pressure 141.1734 psi temperature 20341.150391 C
C1 - Pressure Sensitivity : 15753
C2 - Pressure Offset : 10568
C3 - Temperature Coefficient of Pressure Sensitivity : 3763
C4 - Temperature Coefficient of Pressure Offset : 2198
C5 - Reference Temperature : 30081
C6 - Temperature Coefficient of Temperature : 8434

I've tried two other sensors and all three show different values for psi. I'm honestly completely lost at this point. I'm checking all of his equations in his library and I don't see the problem.
 
Do you have pullups on SDA and SCL? If so, what value are they?
It might help if you post a photo of the device and its connections to the Teensy.

Pete
 
Yes.

Do you have pullups on SDA and SCL? If so, what value are they?
It might help if you post a photo of the device and its connections to the Teensy.

Pete

Yes I have pull ups and i2c for the device works perfectly. I have no problem with the connectivity. I was just struggling to create the code
 
I tested the library's calculation of temperature with the example values given in the PDF and it gets the correct answer. So, I suspect that your code must be getting incorrect values from the sensor (rather than the library getting it wrong). I note that the library does not do the CRC check described in the PDF and it would also be useful to know what PROM values have been read from the sensor.
Can you add the code, below, to the MS5525DSO::_begin_common function in MS5525DSO.cpp immediately after the reset() statement:
Code:
#define MS5525_TEST
#ifdef MS5525_TEST
  uint16_t temporary;
  Serial.printf("uint16_t nprom[8] = {");
  for (uint8_t i = 0; i <= 7; i++) {
    if(!_read_prom(i,&temporary)) success = false;
    Serial.printf("0x%04X\n, ",temporary);
  }
  Serial.println("};");
#endif

Then recompile and upload the example sketch again and copy and paste the entire output here.

Pete
 
I tested the library's calculation of temperature with the example values given in the PDF and it gets the correct answer. So, I suspect that your code must be getting incorrect values from the sensor (rather than the library getting it wrong). I note that the library does not do the CRC check described in the PDF and it would also be useful to know what PROM values have been read from the sensor.
Can you add the code, below, to the MS5525DSO::_begin_common function in MS5525DSO.cpp immediately after the reset() statement:
Code:
#define MS5525_TEST
#ifdef MS5525_TEST
  uint16_t temporary;
  Serial.printf("uint16_t nprom[8] = {");
  for (uint8_t i = 0; i <= 7; i++) {
    if(!_read_prom(i,&temporary)) success = false;
    Serial.printf("0x%04X\n, ",temporary);
  }
  Serial.println("};");
#endif

Then recompile and upload the example sketch again and copy and paste the entire output here.

Pete

uint16_t nprom[8] = {0x0001
, 0x3D89
, 0x2948
, 0x0EB3
, 0x0896
, 0x7581
, 0x20F2
, 0x0004
, };
INFO: sensor inicializado, volcando coeficientes...
C1 - Pressure Sensitivity : 15753
C2 - Pressure Offset : 10568
C3 - Temperature Coefficient of Pressure Sensitivity : 3763
C4 - Temperature Coefficient of Pressure Offset : 2198
C5 - Reference Temperature : 30081
C6 - Temperature Coefficient of Temperature : 8434
 
It prints all 8 values in the PROM. The library only reads 6 of them and ignores the CRC. The data above show that the CRC is correct.
But you didn't include the line which has the calculated pressure and temperature and I forgot to add code to print the raw ADC values.
I'll get back to this later today.

Pete
 
It prints all 8 values in the PROM. The library only reads 6 of them and ignores the CRC. The data above show that the CRC is correct.
But you didn't include the line which has the calculated pressure and temperature and I forgot to add code to print the raw ADC values.
I'll get back to this later today.

Pete

uint16_t nprom[8] = {0x0001
, 0x3B71
, 0x2847
, 0x0F12
, 0x0908
, 0x7E93
, 0x2045
, 0x0003
, };
INFO: sensor inicializado, volcando coeficientes...
C1 - Pressure Sensitivity : 15217
C2 - Pressure Offset : 10311
C3 - Temperature Coefficient of Pressure Sensitivity : 3858
C4 - Temperature Coefficient of Pressure Offset : 2312
C5 - Reference Temperature : 32403
C6 - Temperature Coefficient of Temperature : 8261
INFO: Pressure 0.005300 psi, Temperature 26.230000 C

INFO: Pressure 0.006700 psi, Temperature 26.209999 C

INFO: Pressure 0.005900 psi, Temperature 26.510000 C
 
The CRC of both nprom arrays is correct, so that gives some confidence that the library is using valid values. Also, those temperatures don't look as wildly improbable as you mentioned in #9.
Next is to print the raw ADC. In the readPressureAndTemperature function (MS5525DSO.cpp), immediately before the statement which starts with " int64_t dT", insert:
Code:
Serial.printf("raw = %d, %d\n",raw[0],raw[1]);
And again, post all the output.
The sample code prints output every 200ms. You can stop it after a second or so and copy the results.

Pete
 
The CRC of both nprom arrays is correct, so that gives some confidence that the library is using valid values. Also, those temperatures don't look as wildly improbable as you mentioned in #9.
Next is to print the raw ADC. In the readPressureAndTemperature function (MS5525DSO.cpp), immediately before the statement which starts with " int64_t dT", insert:
Code:
Serial.printf("raw = %d, %d\n",raw[0],raw[1]);
And again, post all the output.
The sample code prints output every 200ms. You can stop it after a second or so and copy the results.

Pete

So, the reason the temperature looks fine is, because I changed the source code to go to only 2 digits, the original library made the temp sit at closer to 26000.00 so, I forced it to multiply to get more decimal places. I believe it's accurate too, because I checked it against a lab thermometer we have. My psi was also closer to 140 before I made a simple change to the formula in the source code.

New:
Code:
int64_t dT = raw[1] - (((int64_t)T_REF) << Q5);

Old:
Code:
int64_t dT = raw[1] - ((int64_t)T_REF) << Q5;

Now it seems to give a much closer output, but I can still tell that the sensor isn't calibrated, because sometimes it will throw a random -4.3psi or something of that nature. Here is the output of what you asked. I'm sorry for not telling you what I've updated as that is important for you to see a problem.

Code:
uint16_t nprom[8] = {0x0001
, 0x3CDE
, 0x2EC0
, 0x0EE5
, 0x0A85
, 0x7A4D
, 0x20B6
, 0x0003
, };
INFO: sensor inicializado, volcando coeficientes...
C1 - Pressure Sensitivity                            : 15582
C2 - Pressure Offset                                 : 11968
C3 - Temperature Coefficient of Pressure Sensitivity : 3813
C4 - Temperature Coefficient of Pressure Offset      : 2693
C5 - Reference Temperature                           : 31309
C6 - Temperature Coefficient of Temperature          : 8374
raw = 6431130, 4159132
INFO: Sensor 1 Pressure -0.005500 psi, Temperature 26.049999 C

raw = 6431150, 4159148
INFO: Sensor 1 Pressure -0.005500 psi, Temperature 26.049999 C

raw = 6431144, 4158912
INFO: Sensor 1 Pressure -0.005500 psi, Temperature 26.039999 C
 
I've been toying with the library to see how I can add a second sensor. I want to run one high and the other low. Hopefully it works XD
 
int64_t dT = raw[1] - ((int64_t)T_REF) << Q5;
Where did you get this from? This is completely wrong and is why you were seeing temperatures in the region of 26000 instead of 20.
The original code that I have is:
Code:
int64_t dT = raw[1] - (((int64_t)T_REF) << Q5);
and this gives the correct results.

I've done some testing of the original code with the raw numbers and PROM values that you've posted and they produce reasonable values. Therefore, the code is correct as it is.
If you've changed the calculations, I suggest that you go back to the original code.

Pete
 
What? No the one you just said was your original code was not what I had originally. I had
Code:
raw[1] - ((int64_t)T_REF) << Q5;
somehow and I changed it to
Code:
int64_t dT = raw[1] - (((int64_t)T_REF) << Q5);
 
Status
Not open for further replies.
Back
Top