3

We are having some trouble with reading the D1 (0x40 ~ 0x4A) and D2 (0x50 ~ 0x5A) registers of Measurement Specialties MS5637. Every time an I2C call is made to these register they always return 0. This is odd since we can read the PROM just fine.

Our setup is as followed: We have a custom PCB that houses a BLE121LR (with an embedded TI microcontroller) that is connected to the MS5637 and some other sensors.

Our procedure thus far is: 1. Write Reset at 0x1E 2. Read PROM at 0xA0 ~ 0xA5 3. Read D1 & D2 at 0x40 & 0x50 -> this always returns 0 at any OSR.

I hope someone here can spot our error and help us getting up and running with the MS5637.

I've attached our running code (BGscript), hopefully it's of some assistance. Before each command I've commented it's functionality:

#=======================================================================================
# MS5637 BaroWITHer
# address:    1110110x (write : x=0, read : x=1) EC ED
# RESET:      0x1E
# PROM READ:  0xA0 to 0xAE
# READ ADC:   0x00
#=======================================================================================

## RESET COMMAND
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\x1E")(MSResetwritten)

## WRITE TO PROM A0
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA0")(MSPromwritten)
## READ TO PROM A0
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(0:2))

## WRITE TO PROM A1
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA1")(MSPromwritten)
## READ TO PROM A1
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(2:2))

## WRITE TO PROM A2
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA2")(MSPromwritten)
## READ TO PROM A2
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(4:2))

## WRITE TO PROM A3
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA3")(MSPromwritten)
## READ TO PROM A3
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(6:2))

## WRITE TO PROM A4
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA4")(MSPromwritten)
## READ TO PROM A4
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(8:2))

## WRITE TO PROM A5
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\xA5")(MSPromwritten)
## READ TO PROM A5
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 2)(i2c_result, data_len, prom(10:2))

## WRITE THE PROM VALUES TO BLE SERVICE prom_handle
#  call attributes_write(handle, offset, value_len, value_data)(result)
call attributes_write(prom_handle, 0, 12, prom(0:12))

#-----------------------------
# D1 & D2
#-----------------------------
## READ D1 WITH OSR=256
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\x40")(MSD1D2written)
## READ D1
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 3)(i2c_result, data_len, dvalues(0:3))

## READ D2 WITH OSR=256
#call hardware_i2c_write(address, stop, data_len, data_data)(written)
call hardware_i2c_write($EC, 1, 1, "\x50")(MSD1D2written)
## READ D2
#call hardware_i2c_read(address, stop, length)(result, data_len, data_data)
call hardware_i2c_read($ED, 1, 3)(i2c_result, data_len, dvalues(3:3))

## WRITE THE D1 & D2 VALUES TO BLE SERVICE d2_handle
#  call attributes_write(handle, offset, value_len, value_data)(result)
call attributes_write(d_handle, 0, 6, dvalues(0:6))
Yu Hao
  • 119,891
  • 44
  • 235
  • 294
Jason Schot
  • 371
  • 1
  • 3
  • 13

3 Answers3

2

After much experimentation I'm answering my own question in the hopes it might help others.

Here are the steps to read the D1 & D2 values from the MS5637 over I2C:

  1. Write to the D register (for D1 this is 0x40 (HEX))
  2. Write to the ADC register (0x00)
  3. Read the ADC (the ADC will return the D1 value)
  4. If working with Bluetooth like in my case: write to the value to a bluetooth service. in BG script this is done with: "call attributes_write"
Jason Schot
  • 371
  • 1
  • 3
  • 13
1

so you need to be careful when using BGScript's read/write commands (FYI: I have an old example on how to do it here: http://www.sureshjoshi.com/embedded/ble112-how-to-use-i2c/)

How to read:

If you want to read from a register, you need to call hardware_i2c_write using the 7-bit device address, left-shifted once and then write to the device the register address you’re interested in, without setting the stop flag (0).

The slave device will put the data up on the I2C lines, so to receive it, call hardware_i2c_read with the same device address, set the stop flag to 1 (to let the device know that you’re done with it) and read 1 byte of data (which will contain the register bit information).

And to write:

The first byte is the register you want to write to and the second is the data you want to write to it. Please MAKE SURE you escape the second byte of data with "\x"

The above assumes you have a device which uses the structure of Address -> Register -> Value... Looking at your datasheet (http://www.meas-spec.com/downloads/MS5637-02BA03.pdf), it appears to just be Address -> Value. Strange.

A key thing to remember is that the 'address' portion of the read/write commands is always the same! Internally, the LSB becomes a 1 or 0 depending on the command itself.

const MS5637_I2C_ADDRESS = $88

## RESET COMMAND
call hardware_i2c_write(MS5637_I2C_ADDRESS, 1, 1, "\x1E")(MSResetwritten)

Additionally, for your D1/D2 conundrum, try setting the stop bit on your initial write to 0, so that your device knows it is still awaiting commands (honestly, even though I2C is a spec, each device has it's own quirky implementations):

## READ D1
call hardware_i2c_write(MS5637_I2C_ADDRESS, 0, 1, "\x40")(MSD1D2written)
call hardware_i2c_read(MS5637_I2C_ADDRESS, 1, 3)(i2c_result, data_len, dvalues(0:3))
SJoshi
  • 1,866
  • 24
  • 47
  • He Joshi, Thanks for your response! Your blog has actually been of great help in getting readings from the other sensors, kudos! While the 1 left shifted address for read and write seems true for the other sensors it's not so for the MS5637 (i've just tested and verified) const MS5637_I2C_WRITE_ADDRESS = $EC const MS5637_I2C_READ_ADDRESS = $ED We did get to read the D1 & D2 values now tough! The trick was to read them via the ADC not directly. Unfortunately now we're stuck on finding the right register values. only 7 are valid and there are many more options in the data sheet A0 to AE – Jason Schot Jul 09 '15 at 10:14
0

Another thing you need to do is DELAY a bit between writing to 0x40 and 0x00. If you don't delay, and the 0x40 command hasn't yet completed, you will get 0 back, or an invalid value. Appropriate delays are as follows:

> switch (cmd & 0x0f) {
>     case MS5637_CMD_ADC_256 : wait_us(900); break;
>     case MS5637_CMD_ADC_512 : wait_ms(3); break;
>     case MS5637_CMD_ADC_1024: wait_ms(4); break;
>     case MS5637_CMD_ADC_2048: wait_ms(6); break;
>     case MS5637_CMD_ADC_4096: wait_ms(10); break; }
Curtis
  • 5,794
  • 8
  • 50
  • 77