i2cdetect
Andrew Conroy (370) 740 posts |
Is it possible for RISC OS to have an equivalent of the i2cdetect command from Linux? This simply probes the specified i2c bus and lists what devices are found there. It provides a very simple and quick method of checking if your i2c device is recognised, and for unknown devices, what their address is. It’s not foolproof, but having it would be better than not having it, in my opinion (though I expect that to be shot to pieces shortly!). There do seem to be sources for the Linux version out there, eg. https://github.com/groeck/i2c-tools/blob/master/tools/i2cdetect.c but porting it isn’t something I think I could do in BASIC! |
Theo Markettos (89) 919 posts |
You can do that very simply. Just use IIC_Control to read every address (0 to 256, the bottom bit is the read/write direction) on the bus. If you get the error ‘No response from IIC device’ there isn’t anything there, if you get data there is. Once you know the address you can tell to some degree what kind of device it is, though many addresses are used by several chips. |
Jeffrey Lee (213) 6048 posts |
For RISC OS 5, OS_IICOp is the preferred way of performing IIC transfers. IIC_Control only allows you to access bus zero, and doesn’t allow you to perform multiple bus transactions in an atomic fashion. E.g. for the typical case of reading from an EEPROM-like device, you need two transactions – a write in order to program the address within the EEPROM, and a read to read the data. With IIC_Control that would require two SWI calls, and if something interrupts you in the middle and programs the EEPROM for a different address then you’d get the wrong data back from your second op. With OS_IICOp you just make one call with two iic_transfer structures and the kernel will make sure no other transfers are allowed during the middle of the sequence. |
Dave Higton (1515) 3534 posts |
AFAIK: all you can do is to attempt to write the address of the device, followed by a STOP state, and see whether that simple transaction has succeeded or failed. If a device is at that address (and there are only 128 addresses), it will ACK the transaction and cause it to succeed. The STOP state allows you to address a different device immediately. IIC addresses were originally assigned in coarse blocks according to the rough functionality of the device. Whether that remains true in these days of multi-function devices, I don’t know. But IIC gives you no protocol to read back exactly what device is there. If it’s in the block for EEPROM functionality, all you can divine is that it’s probably an EEPROM, but not which device, capacity, how to drive it, what the write page size is, etc. It was invented back in the 1980s for embedded systems, where the number and types of devices on a bus were known. It wasn’t intended for systems where you can plug in devices that the system manufacturer didn’t specifically cater for. |
Andrew Conroy (370) 740 posts |
As I understand from the source linked above, i2cdetect is a little bit more subtle than just writing/reading “some data” from each address, it knows certain devices are at certain addresses, and just reading data can crash them, so it uses different methods for different addresses to try to avoid crashing the devices there, though still with no guarantee:
I know it doesn’t tell you what device is there, but it does tell you a device is there, which can be reassuring, and possibly more useful that writing a bit of code each time to probe where you think a device is. I have come across one device where you could change the I2C device address in firmware, so once that was done, i2cdetect will tell you what the device address is if you happen to unplug it and come back to it a while later! Certainly the Linux world seems to find a use for it anyway, even if the RISC OS world can’t see the point of it. |
Rick Murray (539) 13850 posts |
I think you are supposed to probe for devices that you think could exist, by whatever method works for that device. And that’s about it. “Unlike PCI or USB devices, I2C devices are not enumerated at the hardware level. Instead, the software must know which devices are connected on each I2C bus segment, and what address these devices are using. For this reason, the kernel code must instantiate I2C devices explicitly.” Here is a quick program to tell you what devices are on an IIC bus. It only reads from the default bus zero (note: this is not for Pandaboard and IGEPv5 users where the IIC bus that stuff hooks on to is 3 and 1 respectively!). It works by reading one byte from each device in turn. This may have side effects so use this sparingly to see if a connected device is responding. When you know it is, probe for it directly.
On my Pi(1), I have the following devices responding: 60, 79, 104, and 116. I have a CJE add-on, which explains devices 79, 116, and whatever device the RTC is. |
Rick Murray (539) 13850 posts |
That said, you need to either know what device IDs you are looking for, or you need to scan the bus first, connect the device, then scan again and see what’s different. Why? Because my SSD1306-based OLED device is connected to my IIC bus, it appears as device 60 (&3C). It appears that this address is also used by the HMC5883L compass… …which sounds like a fun thing to play with. I might see if I can get one. Hmmm, Adafruit do one. Actually, there are a lot of interesting IIC gadgets there… |
Jeffrey Lee (213) 6048 posts |
Obvious mistake: Your code is enumerating everything twice. It should be |
Rick Murray (539) 13850 posts |
Facepalm time. ;-) Code corrected. You’ll notice it is 1 to 126 as I believe that 0 and 127 have special meaning. One is (was?) a general call address, but sadly nobody envisaged having the devices respond with “I’m here!”. |
Andrew Conroy (370) 740 posts |
Thanks Rick. I have previously done a quick hack like that, but as mentioned before, it does have the possibility of messing up some devices, which is why the version everyone seems to use in the Linux world has the different methods for different address ranges. Thanks for the input folks, I guess I’ll leave it here. |
Rick Murray (539) 13850 posts |
And even that carries a warning that it could mess things up. Best thing to do – if there is a device that you think should be there, look for it and it alone. You will likely need prior knowledge (like my CJELED module, I need to know which IIC bus on which board). That, incidently, is why I was asking how best to tell one board from another – things are NOT the same so sometimes this information is necessary. |