qjbarry
Posts: 4
Joined: Wed Nov 15, 2017 11:30 pm

I2C Write repeated Read

Sun Feb 18, 2018 9:45 pm

HI, I am somewhat confused, there is so much "old" information available on the web regarding Write->Read issues. I no longer know what the current status really is. I am trying to read a few sensors on a board I designed, and as fate would have it, two of the devices make use of Write -> Read. To sum it up:

Write to the slave device *and I2C DOES NOT SEND STOP*
Read from the slave device immediately.

In this case it is a pressure sensor. Sequence:
Start Pressure measurement. Write Start Pressure Conversion Command
Wait 10 ms
Write "Read Sensor" command (No Stop bit must be sent after this command)
Read byte 1
Read byte 2
Read byte 3

My Code to test:

Code: Select all

def read_raw_pressure(self):    
        #Reads the uncompensated pressure from the sensor
        self.i2c_bus.write_byte(self.addr, self.P_Res)
        time.sleep(0.02) #20 ms pause
        data_0, data_1, data_2 = self.i2c_bus.read_i2c_block_data(self.addr, self.ADC_Read, 3)
        return((data_0 << 16) | (data_1<<8) | data_2)

    def read_raw_temp(self):    
        #Reads and returns the uncompensated temperature from the sensor
        self.i2c_bus.write_byte(self.addr, self.T_Res)
        time.sleep(0.02) #20 ms pause
        self.i2c_bus.write_byte(self.addr, self.ADC_Read)
        data_0 = self.i2c_bus.read_byte(self.addr)
        data_1 = self.i2c_bus.read_byte(self.addr)
        data_2 = self.i2c_bus.read_byte(self.addr)
        return((data_0 << 16) | (data_1<<8) | data_2)
Neither of these work because:
read_raw_pressure does not write a command to fetch the result. It does return data but it is incorrect.
read_raw_temp initiates the conversion, writes the command to fetch the result, sends a stop bit, and then the I2C bus is unavailable.

Can one do a Write ->Repeated Start on the Raspberry Pi model 3B, if so is this a hack, if not how must I approach this?

Thanks in advance

User avatar
joan
Posts: 14936
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: I2C Write repeated Read

Sun Feb 18, 2018 10:12 pm

So you want

start condition

address+write bit
write byte

start condition

address+read bit
read byte
read byte
read byte

stop condition

I don't think that is possible with SMBus. The closest is probably the unofficial SMBus read I2C block data command. I'd try that.

qjbarry
Posts: 4
Joined: Wed Nov 15, 2017 11:30 pm

Re: I2C Write repeated Read

Sun Feb 18, 2018 10:28 pm

Hi Joan,

My code snippet I attached tried to make use of the method you suggested. The data returned is invalid.
I seem to get the idea that the Pi does not support Write Repeated Reads.
The problem is that I have to write a command which tells the sensor that I am going to read the A/D
Thereafter I have to read three bytes, and I must not send a stop bit, rather a repeated start bit.

I am feeling sad.

User avatar
joan
Posts: 14936
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: I2C Write repeated Read

Sun Feb 18, 2018 10:37 pm

In what way is the returned data invalid? The read I2C block data command should issue the sequence you want.

qjbarry
Posts: 4
Joined: Wed Nov 15, 2017 11:30 pm

Re: I2C Write repeated Read

Mon Feb 19, 2018 3:40 pm

Hi All,
I managed to sort out the problem. The datasheet states that the calibration constants are stored in a ROM and that the data is 16 bits wide. For example, they state that at address 0 one can find the manufacturer reserved data (16 bits) and at address 1 Coefficient 1 16 bits wide. This is not the case, the ROM is 8 bits wide, so the manufacturer reserved data is located at addresses 0 and 1, the first coefficient at addresses 2 and 3, etc. I was reading 16 bits starting at Address 0, then 16 bits starting at Address 1 etc. When I corrected the temperature and pressure readings, my coefficients were incorrect. I had to read 16 bits starting at address 0, 16 bits starting at address 2, etc.

So to sum it up the Repeated Start DOES work. I used it as follows:

Code: Select all

#Write a command to start a 24 bit temperature conversion with 12xOSR to I2C bus address 0x77
i2c_bus.write_byte(0x77,0x58) 
#Wait 20 ms
time.sleep(0.02)
#Write 0x00 (Read Analog result) to I2C bus address 0x77 and then Read 3 bytes with a Repeated start from I2C address 0x77 
#Put the first byte (MS Byte) into data_0, Middle Byte into data_1 and LS Byte into data_2
data_0,data_1,data_2 = i2c_bus.read_i2c_block_data(0x77,0x00,3)
#Concatenate it all to make up a 24 bit value
Temperature = ( (data_0<<16)|(data_1<<8)|(data_2) )
I have now written and tested a library for the MEAS MS5607-02BA barometric pressure sensor. If anyone wants the code for it drop me an email. It features 20 cm resolution in altitude (10 to 1200 mbar) and +- 0.8 degrees temperature accuracy in the range -40 to +85 degrees C.
What is interesting is the temperature accuracy across the entire temperature range. There are devices that offer better accuracy, but within a smaller temperature range.

Thanks again

Quentin

I am happy

Return to “Troubleshooting”