raspberrypi / bookworm-feedback

13 stars 1 forks source link

I2cdetect program works sometime with Raspberry Pi5 and works all the time with Raspberry Pi4 #263

Open eugenedakin opened 5 months ago

eugenedakin commented 5 months ago

I2cdetect program works sometime with Raspberry Pi5 and works all the time with Raspberry Pi4

I was programming a GY-906 (MLX90614) and the program to read the temperature works. i2cdetect works on Raspberry Pi 4b with the exact same GY-906 (MLX90614) to identify the i2c address at 0x5a. When I run the program on a Raspberry Pi 5, the program reads the correct temperature, however the i2cdetect program does not detect the GY-906 (MLX90614) address at 0x5a - even though the program works.

Here are pictures of the GY-906. Pic1 Pic2

Here is a picture of the i2cdetect on the Raspberry Pi 5 with the GY-906. Pi5MLX90614

Here is a picture of the i2cdetect on the Raspberry Pi 4b with the GY-906. Pi4b

Here is the working code that successfully reads the temperature on both computers: `import smbus import time

class MLX90614():

MLX90614_RAWIR1=0x04
MLX90614_RAWIR2=0x05
MLX90614_TA=0x06
MLX90614_TOBJ1=0x07
MLX90614_TOBJ2=0x08

MLX90614_TOMAX=0x20
MLX90614_TOMIN=0x21
MLX90614_PWMCTRL=0x22
MLX90614_TARANGE=0x23
MLX90614_EMISS=0x24
MLX90614_CONFIG=0x25
MLX90614_ADDR=0x0E
MLX90614_ID1=0x3C
MLX90614_ID2=0x3D
MLX90614_ID3=0x3E
MLX90614_ID4=0x3F

comm_retries = 5
comm_sleep_amount = 0.1

def __init__(self, address=0x5a, bus_num=1):
    self.bus_num = bus_num
    self.address = address
    self.bus = smbus.SMBus(bus=bus_num)

def read_reg(self, reg_addr):
    err = None
    for i in range(self.comm_retries):
        try:
            x = self.bus.read_word_data(self.address, reg_addr)
            print("read_reg:",round(x,2)," number")
            return x
        except IOError as e:
            err = e
            #"Rate limiting" - sleeping to prevent problems with sensor
            #when requesting data too quickly
            time(self.comm_sleep_amount)
    #By this time, we made a couple requests and the sensor didn't respond
    #(judging by the fact we haven't returned from this function yet)
    #So let's just re-raise the last IOError we got
    raise err

def data_to_temp(self, data):
    temp = (data*0.02) - 273.15
    return temp

def get_amb_temp(self):
    data = self.read_reg(self.MLX90614_TA)
    return self.data_to_temp(data)

def get_obj_temp(self):
    data = self.read_reg(self.MLX90614_TOBJ1)
    return self.data_to_temp(data)

if name == "main": sensor = MLX90614() while True:
print("Ambient Temp:",round(sensor.get_amb_temp(),2),"C") print(" Object Temp:",round(sensor.get_obj_temp(),2),"C\n") time.sleep(0.5) ` The program runs, and reads the temperature correctly with the exact same equipment on the Raspberry Pi 4b and 5. However, i2cdetect -y 1 does not read the address on a Raspberry Pi 5, and i2cdetect-y 1 does read and display the correct address on the Raspberry Pi 4b.

My wild guess is that there is a bug in the i2cdetect program?

Warm regards.

6by9 commented 5 months ago

i2cdetect only does a SMBUS read or SMBUS write quick operation on each address. The default mode uses read for address 0x30-0x37 and 0x50-0x5f, and write quick for all other addresses - see https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/tree/tools/i2cdetect.c#n68

You can force read mode by adding -r to the command, or -q for write quick. It'd be interesting to know if one worked and the other didn't.

Pi5 does use a different I2C controller to Pi4, but I wouldn't expect there to be any difference for either of those access methods.

eugenedakin commented 5 months ago

i2cdetect only does a SMBUS read or SMBUS write quick operation on each address. The default mode uses read for address 0x30-0x37 and 0x50-0x5f, and write quick for all other addresses - see https://git.kernel.org/pub/scm/utils/i2c-tools/i2c-tools.git/tree/tools/i2cdetect.c#n68

You can force read mode by adding -r to the command, or -q for write quick. It'd be interesting to know if one worked and the other didn't.

Pi5 does use a different I2C controller to Pi4, but I wouldn't expect there to be any difference for either of those access methods.

Hi 6by9,

Thanks for the suggestion. The command results you suggested are ..... interesting.... :)

Pi5MLX90614-r

On the Raspberry Pi with the MLX90614 (GY-906) board should show the hexadecimal address 0x5a. Using the i2cdetect -y 1 command, there were no results (see the screen grab above).

Using the command i2cdetect -r -y 1 there were also no results.

Using the command i2cdetect -q -y 1 did show the proper address at 5a.

I have been programming and writing electronic books for the Raspberry Pi for about 8 years https://scispec.ca/index.php/books and i2cdetect has been pretty dependable. I am not sure if I did something wrong or if there was a newer version of i2cdetect that I was supposed to be using. :-)

What is your opinion why there is a difference with the additional parameter -q on the i2cdetect command?

Thanks for your thoughts.

Eugene Dakin Ph.D. Eng. edit: Screen grab is above not below.

6by9 commented 5 months ago

i2cdetect is not doing anything wrong here, but there needs to be a little understanding of what it does.

Addresses 0x30-0x37 and 0x50-0x5f (which will include the 0x5a of your sensor) use SMBus read when in auto mode to avoid corrupting Atmel AT24RF08 EEPROMs (at least that's what the comment says). Conversely Read mode can lock up some write-only devices.

The I2C driver for Pi5 claims to be able to directly implement I2C_FUNC_SMBUS_QUICK. The I2C driver for Pi0-4 (i2c-bcm2835) uses the kernel's SMBus emulation. It's quite possible there is some quirk in the Pi5 implementation, but it needs a device that misbehaves in order to verify it. We'll look to buy a MLX90614 to test.

We do know that there is a quirk in the i2c-brcmstb I2C controller that only works reliably with with the -r flag, and not the quick write mechanism, so it does happen.

6by9 commented 5 months ago

Just as a test I've looked to see if forcing -r or -q causes any problems on other devices (in this case a Pi camera module), and it doesn't appear to.

eugenedakin commented 5 months ago

Thanks for looking into this issue.

I am adding a little more information, as I have tested i2c addresses with two separate GY-521 (gyrometer and accelerometer), and i2cdetect -y 1 command correctly detects the address on both the Raspberry Pi 4b and 5.

A total of 7 MLX90614 (GY-906) boards were purchased from 4 different suppliers. 2 were completely faulty and did not work on the Raspberry Pi 4b or 5. The remaining 5 boards worked with the above python code to read the temperature. All 5 remaining boards did not detect the 0x5a address with i2cdetect -y 1 on the Raspberry Pi 5, and the addresses were detected on the remaining 5 boards with the Raspberry Pi 4.

Maybe there is something different with i2c on the GY-906 as compared to the GY-521?

Warm regards.

6by9 commented 5 months ago

One thought - you are using the 3.3V versions of the MLX90614 (ie MLX90614ESF-BAA). A device being used on the edge of voltage tolerance may well explain erratic behaviour.

Reading the datasheet for MLX90614, page 18

8.4.2. Differences with the standard SMBus specification (reference [1])Differences with the standard SMBus specification (reference [1])
Differences with the standard SMBus specification (reference [1])Differences with the standard SMBus specification (reference [1])
There are eleven command protocols for standard SMBus interface. The MLX90614 supports only two of them. Not
supported commands are:
- Quick Command <<<<<<<<
- Byte commands - Sent Byte, Receive Byte, Write Byte and Read Byte
- Process Call
- Block commands – Block Write and Write-Block Read Process Call
Supported commands are:
- Read Word
- Write Word

So according to the spec the device doesn't support the quick command. Using -q is therefore technically invalid, which makes it even more curious as to why it works when -r doesn't.

eugenedakin commented 5 months ago

I like the points that you mentioned. Although the MLX90614 is supposed to be 3.3v, I briefly hooked up the MLX90614 to 5v and i2cdetect -y 1 did not work. A 3.3v-5v Level Shifter has been purchased, and has not arrived yet.

Yes, I know I am not supposed to connect 5.0v to a 3.3v input, and my curiosity got the best of me :-)

eugenedakin commented 5 months ago

Confirmed MLX90614 sensors are BAA.

BAAPic

BAA