How to read data from i2c using i2cget? - linux

I'm new to embedded devices and am trying to understand how to use i2cget (or the entire I2C protocol really).
I'm using an accelerometer MMA8452, and the datasheet says the Slave Address is 0x1D (if my SAO=1, which I believe is referring to the I2C bus being on channel 1 on my raspberrypi v2).
From the command line, I enter
sudo i2cget -y 1 0X1d
It returns
0X00
I think that means I'm attached to the correct device.
So now, I'm trying to figure out how do I get actual data back from the accelerometer?
The i2c spec says
i2cget [-y] i2cbus chip-address [data-address [mode]]
So I have tried
sudo i2cget -y 1 0x1D 0x01
where 0x01 is the OUT_X_MSB. I'm not sure entirely what I'm expecting to get back, but I figured if I saw some data other than 0x00, I might be able to figure that out.
Am I using ic2get wrong? Is there a better way to learn and get data from i2c?
The datasheet for my accelerometer chip is at
http://dlnmh9ip6v2uc.cloudfront.net/datasheets/Sensors/Accelerometers/MMA8452Q.pdf

I am way too late but this might help other people. You might be getting the 0x00 output every time you use i2cget is because you might have forgotten to set some mode. For instance, I was working on pcf8583 which is a clock and calendar chip and can also be use as a counter.
My goal was to use this chip as a counter. It was connected to i2cbus1 with device address 0x51. So reading the data sheet, I found out that, the chip would work as a counter when the mode is set to 0x20 in the control register 0x00. The command I used for doing this:
i2cset 1 0x51 0x00 0x20
Now, I could read the counter pulses from a wind sensor with the command:
watch i2cget -y 1 0x51
watch is just a linux command that runs the specified command (i2cget) repeatedly every 2 seconds and displays the results on standard output.

From the datasheet its clear that the default value of Status Register Address 0x00 is 0x00, so you are doing fine I guess. See Table 11 Register Map Address in the datasheet.
You may try reading the device ID at Register Address 0x0D. You should get value 0x2A when you read this register(0x0D).

Related

I2C - Read specific data register (Raspberry Pi 3+ Python)

I have an assembly between a Raspberry Pi 3B+ (OS Raspbian GNU/Linux 10 buster) and a gas analyser (the gas analyser sensor use I2C), so i tried to communicate with it via my Raspberry.
On my linux terminal, my sensor is correctly identified at address "0X2D" via the i2cdetect -y 1 command:
This sensor stores various data in a total of 26 registers (from 0x00 to 0x1A). My goal would be to be able to access via python code (Python 3.7.3) the values of any register. As stated in the sensor user manual, in order to read register X, it is necessary to write "empty" to this directory X of sensor 0X2D and then make a read request to sensor 0X2D.
Extract from the sensor manual:
Unfortunately, both via the Linux terminal (using the i2cget/set functions of the i2c-tools library) and via python code (using the smbus2 library), I have never managed to query a specific register, I always start from the first register 0X00.
On Linux, when I interrogate the sensor (which allows sequential reading) several times in a row after writing to first register 0x00, it returns the values of the successive registers (starting from the first register 0x00). These values seem to be correct because I get the correct serial number of the sensor which is stored in the registers from 0x13 to 0x19).
But when I try to start from another register (0x02 for example), it restarts from 0x00 register :
Am I making a mistake or is this the normal behaviour of such a sensor?
As far as the python part is concerned, I have not been able to find any code examples (or libraries) that allow you to make "empty" writes to a register in order to be able to read the value of this register afterwards.
You are not passing data-address to i2cget. See man page.
i2cget -y 1 0x2d 0x02

Issues reading Modbus RTU holding registers. Response is the same as request

I wrote a program using python3.8.2 and pymodbus on a beaglebone to do modbus RTU communication via RS485. I am using a MAX13487E on a cape connected to UART1 to drive the RS485 (p9_24, p9_26). The beaglebone is the master.
For my purposes I only require to use FC3 (read holding) and FC6 (write holding). I have been able to write with no issue. However, I am unable to read. Pymodbus returns an exception ModbusIOException('No Response received from the remote unit/Unable to decode response', 4).
Using pymodbus REPL to debug, I found that the replies received were the same as the requests sent, only shorter as the master is expecting a shorter response. i.e.
SEND: 0x32 0x3 0x1 0x30 0x0 0x1 0x80 0x3a
RECV: 0x32 0x3 0x1 0x30 0x0 0x1 0x80
I have been able to poll this same slave in the past using other masters (e.g. diagslave-modpoll for windows) with no problems.
What would be the reason this would be happening? If anyone has any experience working with the MAX13487E transceiver, would you be able to aid in its use?
I found an attribute of ModbusRTUClient() included in the kwargs** called "handle_local_reflection". Setting that to true seemed to solve the problem. I didn't bother looking into how it works, I'm just happy that it does.
However, if I was doing multiple requests in succession in only worked for the first one. Adding a small delay time.sleep(0.05) between requests made it all more stable.

Component that can create a hex value?

TLDR:
Is there a way to create a hex value between 0x20 and 0x7E with 5 volts? Is there a cheap component on the market or circuit logic that can achieve this?
I'm not sure what the proper terminology for this is, but here's what I'm trying to do:
I have a bluetooth module connected to my pico via UART0 TX and UART0 RX. The use for this is a bit long to explain, but essentially, I want the bluetooth module to work without my pico attached to it. I have a device that outputs a signal, the pico reads the signal, then it tells the bluetooth module to transmit to the receiver. However, since the data to transmit isn't actually important, it makes sense to cut out the pico and simply have the bluetooth module read the signal directly then transmit.
I have the device that outputs exactly when I want, but it outputs the equivalent of 00 in hex. My computer is connected via bluetooth and can read it just fine. However, the pico, reading the input through RX, can't. I've found no way for micropython using UART to read 00 - UART.any() and UART.read() want a character, and 00 only corresponds to NULL.
So essentially, I need some way to transmit a hex value between 0x20 and 0x7E without using the raspberry pi pico. Is there some kind of component that is able to do this? In practice, the bluetooth module will be connected to 5V power with up to 5 amps.
Any idea on how to get the Pico to read 00 in hex through the RX pin is welcomed too. The purpose of this is to not need multiple Picos, since the receiver and the transmitter will be a good distance from each other.
I found the issue. The pico actually can accept 0 through the UART RX pin. The issue was me having a wire misplaced. My computer saw the 0 input which made me think the pico couldn't handle it, but in fact it was never receiving it. Thanks for the help Kotzjan. Would have been interesting to fake a value into the port though!

i2c and Linux (127 devices and i2cdetect question)

[Update: This is wrong]It seems that with the i2cdetect program in Linux, it only scans addresses from 0 to 7f, while you technically can have 127 devices on the bus (0 to FF).[End of Wrong]
Furthermore, I've found that for an address that you might expect at 0x22 shows up as 0x11 in the program. This suggests that the i2cdetect program is bit shifting the address and ignoring the least significant bit.
However, the device tree also seems to require the 0x11 address in the tree versus the expect 0x22 address. I.e. my device is not recognized unless I put the bit shifted address. I do not have a long past history with linux and hardware drivers, so I'm wondering if this is expected behavior? E.g. I'm looking at the PCA9655 I/O Expander.
https://www.onsemi.com/pdf/datasheet/pca9655e-d.pdf
Thanks,

MCP23017 I2C Device driver probe function is not called

I am using the following I2C/GPIO Device driver to access the MCP23017 GPIOs. With the insmod command I am able to load the driver and its listed in /proc/modules. I have two MCP23017 chips connected to my Raspberry Pi. Both are detected at addresses 0x20 and 0x21. The initcall to the driver registers the driver. I checked this by printing out a message. But the driver probe function is not called. The devices are not opened/ cannot be located elsewhere.
How is the probe function called?
Should the probe be done manually to locate the devices?
Is the probe call similar to the open call?
I tried this echo mcp23017 0x20 > new_device to manually create a new device with the address. But it didnt work. I got the followin message: Driver 'mcp23s08' is already registered, aborting...
Any help would be appreciated.
probe() function is called when driver is matched with your device description in Device Tree. Matching happens when compatible field of your driver found in Device Tree (for your driver it's "microchip,mcp23017" string).
Apparently you don't have your device (MCP23017) described in Device Tree, that's why probe() is not called. You can load corresponding Device Tree Overlay to overcome this issue. The one you pointed out in your comment seems to be correct. Read more about loading overlays in Raspberry Pi ecosystem here.
You can try to load your overlay like described in that article:
$ sudo dtoverlay mcp23017.dtbo
Or you can try to use Capemgr for this purpose. Personally I didn't try any of those, so you should look which works for you best.
Update
Replying to your questions in comments.
But when I try the i2cdetect command it shows UU.
See man i2cdetect. So "UU" means that i2cdetect skipped probing because device at the address you specified is already used by driver. I guess it what you intended, so it's ok.
With a rmmod mcp23017 command I see the device still under devices but i2cdetect shows 0x20
So you unloaded the driver and now i2cdetect shows you that there is some device on 0x20 address. I guess it's correct behavior. Also if you want to get rid completely of your device -- try to unload DT overlay along with driver.
Also I have connected two MCP23017 chips. But I can see only the device at 0x20 under devices. The I2C chip at 0x21 is still not detected, though the driver says it supports up to 8 chips
I can see two possible causes to this issue.
DT overlay only has description for device with 0x20 address, but missing description for device with 0x21 address. If this is the case, you should find sources for your DT overlay, add description for rest of your devices, compile that modified DT overlay and then load it instead of pre-built one.
All devices may be configured for using 0x20 address. See section 1.4
Hardware Address Decoder in MCP23017 datasheet for details. Check A0, A1, A2 pins on your chips.

Resources