krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 6:49 pm

I've been frustrated with my efforts to read a temp/humidity sensor, so I connected my board to a scope and read the data being transferred. When I use the command read_i2c_block_data(addr, 0, 4), I noticed that the raspberry pi first writes a '0' to the device, then immediately reads 4 bytes in succession. It's not supposed to write a 0 first. That screws up my chip big time. Why is it doing this and how can I fix it/work around it?

I'm using python (a tkinter interface) on a raspberry pi zero. Here's a section of relevant code:

Code: Select all

try:
    from Tkinter import *
except ImportError:
    from tkinter import *
try:
    import tkinter.messagebox
except ImportError:
        import tkMessageBox
import smbus
import csv
import time
from datetime import datetime
import subprocess, sys

sens_addr = 0x28

def csv_write (self):
        global directory
        global file_name
        logFile = open(directory+file_name, 'a')
        with logFile:
            
            block = bus.read_i2c_block_data(sens_addr, 0, 4) #read 4 bytes
            print(block)
Last edited by krisss on Wed Aug 22, 2018 7:01 pm, edited 1 time in total.

DirkS
Posts: 9967
Joined: Tue Jun 19, 2012 9:46 pm
Location: Essex, UK

Re: 'smbus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 6:56 pm

Yes, maybe, 42...

Any answer is possible with so little to go on...
Minimum you have to give us is some more code, and which programming language you're using...

krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 7:07 pm

Edited the top post. Is that enough?

stevend
Posts: 214
Joined: Fri Oct 11, 2013 12:28 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 7:30 pm

http://www.raspberry-projects.com/pi/pr ... nterface-2 suggests that the read syntax is:

Code: Select all

long[] read_i2c_block_data(int addr,char cmd)
If I've found the right reference, your line should be:

Code: Select all

block = bus.read_i2c_block_data(sens_addr,  4) #read 4 bytes

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

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 7:33 pm

The initial 0 will be the register to read on the device.

See my pigpio equivalent.

http://abyz.me.uk/rpi/pigpio/python.htm ... block_data

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

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 7:37 pm

stevend wrote:
Wed Aug 22, 2018 7:30 pm
http://www.raspberry-projects.com/pi/pr ... nterface-2 suggests that the read syntax is:

Code: Select all

long[] read_i2c_block_data(int addr,char cmd)
If I've found the right reference, your line should be:

Code: Select all

block = bus.read_i2c_block_data(sens_addr,  4) #read 4 bytes
The example was C (using the Linux I2C interface) whereas the OP is using the Python SMBus module.

krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 7:46 pm

stevend wrote:
Wed Aug 22, 2018 7:30 pm
If I've found the right reference, your line should be:

Code: Select all

block = bus.read_i2c_block_data(sens_addr,  4) #read 4 bytes
This causes it to read 32 bytes now. I don't have it connected to the scope anymore but I'm getting the same nonsense numbers indicating it's writing a 0 first.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 7422
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Wed Aug 22, 2018 8:19 pm

Don't use an smbus library when you want an i2c one. They may have a lot in common, but they are not the same (smbus is really a subset of i2c).
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 3:21 pm

I think this is a really simple problem: I just need to read four bytes using a repeated start condition. Can I do that with smbus or is there a python library that can do this? I'm sure I'm not the first person with this problem.

6by9
Raspberry Pi Engineer & Forum Moderator
Raspberry Pi Engineer & Forum Moderator
Posts: 7422
Joined: Wed Dec 04, 2013 11:27 am
Location: ZZ9 Plural Z Alpha, aka just outside Cambridge.

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 3:47 pm

Talk I2C then, not SMBus.
https://github.com/quick2wire/quick2wir ... ith-i2c.md appears to be talking to the I2C functions of the kernel rather than smbus. It's using the ioctl I2C_RDWR to allow multiple read and/or write transactions as a single entity. The lengths of those transactions is entirely up to you and what your device requires.
Software Engineer at Raspberry Pi Trading. Views expressed are still personal views.
I'm not interested in doing contracts for bespoke functionality - please don't ask.

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

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 5:22 pm

What device are you trying to read?


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

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 5:42 pm

https://github.com/tonyastolfi/chipcap2 ... hipcap2.py uses the Python smbus module. I presume it is meant to work.

krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 6:08 pm

Thanks for finding that. It's very similar to my own code. Unfortunately I tried it and it spits out the same numbers as before. The code again reads 32 bytes from the device, all garbage.

User avatar
Paeryn
Posts: 2704
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Thu Aug 23, 2018 11:17 pm

As 6by9 pointed out earlier, you are trying to use SMBus to talk to an I2C device, the chip you linked to doesn't use SMBus so it shouldn't be expected that it follows the SMBus protocol.

From a quick look at what read_i2c_block_data(address, comm, count) involves :-

Code: Select all

Key to symbols
==============

S     (1 bit) : Start bit
P     (1 bit) : Stop bit
Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0.
A, NA (1 bit) : Accept and reverse accept bit. 
Addr  (7 bits): I2C 7 bit address. Note that this can be expanded as usual to 
                get a 10 bit I2C address.
Comm  (8 bits): Command byte, a data byte which often selects a register on
                the device.
Data  (8 bits): A plain data byte. Sometimes, I write DataLow, DataHigh
                for 16 bit data.
Count (8 bits): A data byte containing the length of a block operation.

[..]: Data sent by I2C device, as opposed to data sent by the host adapter.

SMBus Block Read:  i2c_smbus_read_block_data()
==============================================

This command reads a block of up to 32 bytes from a device, from a 
designated register that is specified through the Comm byte. The amount
of data is specified by the device in the Count byte.

S Addr Wr [A] Comm [A] 
           S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
From that it says that the comm byte is first written to the device to tell the device which register it wants to read from, then the first byte received is how many more bytes the device is going to send, followed by the data.

According to the docs for your chip, when you send a command byte it expects to be sent two more bytes of data (and that 0 is not a valid command) and any responses to a command are either 1, 2 or 3 bytes (and it doesn't send a count byte first).

To just read the humidity and temperature you don't send a command each time, you just issue data fetches and by the looks of it SMBus only has one function that can read without sending a command and that only allows reading one byte.
She who travels light — forgot something.

krisss
Posts: 15
Joined: Mon Aug 06, 2018 5:24 pm

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Fri Aug 24, 2018 5:47 pm

That's what I figured. Is there a way for me to edit the smbus code? I searched on my Pi but couldn't find anything.

EDIT: Thanks everyone, I'm going to take your advice and abandon smbus and use quick2wire. I'll start a new thread as well.

User avatar
Paeryn
Posts: 2704
Joined: Wed Nov 23, 2011 1:10 am
Location: Sheffield, England

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Fri Aug 24, 2018 7:52 pm

The version installed is likely to be the C version pre-compiled as a shared object file which Python can use. There is a pure Python version but probably not in the repos so either a pip or a manual download may be needed.

Either way you don't want to go modifying libraries to do something they aren't supposed to do as it could have a negative effect on other libraries / programs that use them, unless you make a new library using the source library as a template.

Hopefully the quick2wire library does what you need, it looked as though it does when I checked 6by9's link.
She who travels light — forgot something.

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

Re: 'bus.read_i2c_block_data' writes a 0 first then reads data

Fri Aug 24, 2018 8:00 pm

What I don't understand is how the github I linked worked (presumably). Perhaps the chipcap2 has changed or smbus has changed or the github author didn't actually check the data.

Return to “Interfacing (DSI, CSI, I2C, etc.)”