I²C reads on broken out bus #1 always return 0

169 views
Skip to first unread message

Torsten K.

unread,
May 11, 2017, 12:44:40 PM5/11/17
to BeagleBoard

Hi,

two weeks ago I received my BeagleBone Blue.

So far, I've managed to get

  - an OrangeRX DSMX receiver
  - a GP-735T GPS receiver
  - a Servo
  - and a 2S LiPo Akku

going, more or less without any problems.

However, all the I²C devices I connected to the available I²C bus #1 so far only work "one-way". I.e., I can send data to the devices and they do what they are supposed to, but I can't seem to get any data from a device to the BBBlue.

E.g., I've got a I²C DC motor controller (with more juice than the builtin one).
I can set my motors spinning, braking, reversing, ... using this controller, but I can't get any status information back from the device.

I already swapped all cables (and measured them) - they seem to be okay.

Can it have something to do with the I²C-settings in the dtb? How does u-boot select the right dtb anyway?

Thanks in advance,
Torsten

Graham

unread,
May 11, 2017, 2:21:11 PM5/11/17
to BeagleBoard
If you are successfully sending I2C commands, then everything is hooked up correctly, and the device tree is properly configured.

I2C is a bi-directional bus.  If it works in one direction, then it has to work in the other direction down at the hardware level.

How are you "reading" the I2C devices?

What app or tool? or what program in what language?

--- Graham

==

William Hermans

unread,
May 11, 2017, 5:10:57 PM5/11/17
to beagl...@googlegroups.com

On Thursday, May 11, 2017 at 11:44:40 AM UTC-5, Torsten K. wrote:

Hi,

two weeks ago I received my BeagleBone Blue.

So far, I've managed to get

  - an OrangeRX DSMX receiver
  - a GP-735T GPS receiver
  - a Servo
  - and a 2S LiPo Akku

going, more or less without any problems.

However, all the I²C devices I connected to the available I²C bus #1 so far only work "one-way". I.e., I can send data to the devices and they do what they are supposed to, but I can't seem to get any data from a device to the BBBlue.

E.g., I've got a I²C DC motor controller (with more juice than the builtin one).
I can set my motors spinning, braking, reversing, ... using this controller, but I can't get any status information back from the device.

I already swapped all cables (and measured them) - they seem to be okay.

Can it have something to do with the I²C-settings in the dtb? How does u-boot select the right dtb anyway?

Thanks in advance,
Torsten

So, you have to be doing something wrong. A beaglebone wont function unless I2C is working. Show us what you're doing, that is not working. The command, and the output. If you're using your own source, we need to see that too. Keep in mind that I do also have hands on experience with writing applications that use I2C in C, and most recent just a week ago. But no personal hands on with the beaglebone blue. The hardware in this case however should be exactly the same.

Torsten K.

unread,
May 12, 2017, 8:44:55 AM5/12/17
to BeagleBoard
Hi Graham + William,

thank you for getting back to me so quickly.

The device I'm trying to communicate with is this motor controller:


It's made for the Raspberry PI, but I don't see any reason for it not to work with the Beaglebone Blue.
With the help of an RPi I've been able to confirm that the device is in full working condition.

Now, let's have some fun:

tkurbad@beaglebone:~$ i2cdetect -y -r 1
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- 44 -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                      

0x44 is the correct default address for the PicoBorgRev.
(Just to have that out of the way: User tkurbad is a member of the 'i2c' group.)

Now, let's try to read the board ID, i.e. version:

tkurbad@beaglebone:~$ i2cget -y 1 0x44 0x99
0x00

This should return 0x15 instead.

Set motor A spinning forward:

tkurbad@beaglebone:~$ i2cset -y 1 0x44 6 255

Motor is spinning full throttle now.

Read motor PWM setting:

tkurbad@beaglebone:~$ i2cget -y 1 0x44 8
0x00

Should return 0xff now.

Turn off motor A:

tkurbad@beaglebone:~$ i2cset -y 1 0x44 6 0

Motor shuts off.

i2cdump behaves the same as all other read operations. At least some of the values should be != 0x00:

tkurbad@beaglebone:~$ i2cdump -y 1 0x44
No size specified (using byte-data access)
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
10: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
20: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
30: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
40: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

I've also got some Python3 code that behaves exactly the same (writes to the device work flawlessly, while reading always returns 0x00):


Any ideas what I may be doing wrong here?

Best,
Torsten

Torsten K.

unread,
May 12, 2017, 10:41:15 AM5/12/17
to BeagleBoard
Update: I lowered the clock frequency of i2c1 to 100kHz via the dtb. That also doesn't change the behaviour.

Graham Haddock

unread,
May 12, 2017, 11:05:55 AM5/12/17
to BeagleBoard
It looks like the MPU9250 has a non standard (to my way of thinking) I2C read sequence that requires you to resend the register address as part of a consolidated write/read sequence.  The default tool i2cget does not deal with this, and only deals with simple (standard to my way of thinking) read sequences.

Since you can write to the device, and a write requires an acknowledgement from the device, there is nothing wrong down at the hardware and low-level driver level.  

If you get a driver specific to the MPU9250 running, that understands the required byte control sequence, I would expect it to work.

If you are using Python, I would suggest using Python 2.7 rather than Python 3.  At least to get started, until you are in control.

The last time I did Python control of I2C, you needed to load python-smbus, and it had not yet been updated for Python 3 compatibility.

It may have been updated and re-released in the last six months.

I did find instructions on the web about how to manually recompile python-smbus for Python 3, so it is possible.

--- Graham

==

On Fri, May 12, 2017 at 9:41 AM, 'Torsten K.' via BeagleBoard <beagl...@googlegroups.com> wrote:
Update: I lowered the clock frequency of i2c1 to 100kHz via the dtb. That also doesn't change the behaviour.

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/-cVwfP40L0M/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard+unsubscribe@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/beagleboard/5b4d695c-e108-4f7e-a154-8c7e81bf8b41%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Torsten K.

unread,
May 12, 2017, 11:48:29 AM5/12/17
to BeagleBoard
Hi Graham,

Am Freitag, 12. Mai 2017 17:05:55 UTC+2 schrieb Graham:
It looks like the MPU9250 has a non standard (to my way of thinking) I2C read sequence that requires you to resend the register address as part of a consolidated write/read sequence.  The default tool i2cget does not deal with this, and only deals with simple (standard to my way of thinking) read sequences.

It's not the MPU9250 that's causing the problem. This is the IMU built into the Beaglebone Blue and connect to I²C bus #0. The example I posted uses the input of the IMU to control the motors via the PicoBorgRev board. Reading the IMU on I²C bus 0 works like a charm, btw. Only reading from the motor controller does not work.
 
Since you can write to the device, and a write requires an acknowledgement from the device, there is nothing wrong down at the hardware and low-level driver level.

Ok, I didn't know that. 

If you are using Python, I would suggest using Python 2.7 rather than Python 3.  At least to get started, until you are in control.

I'm a fairly advanced Python programmer and I don't want to start off with something as deprecated as Python 2.7. Nonetheless, I tried a Python 2.7 of my code, and it yields the same results: Writing to the motor controller works, while reading from it doesn't.
 
The last time I did Python control of I2C, you needed to load python-smbus, and it had not yet been updated for Python 3 compatibility.

There are inofficial ports that work. One is in my repo: https://github.com/tkurbad/python3-smbus. Works well with Raspberry PI and the built-in devices of the Beaglebone that are connected to I²C bus #0 (i.e. IMU and barometric pressure sensor).

Just for completeness' sake, I created a very simple test script using Python 2.7 (it does exactly the same as the original Python code for the motor controller does during init):

#!/usr/bin/python2

import smbus

address = 0x44
id_cmd = 0x99
i2c_max_len = 4

bus = smbus.SMBus(1)

i2cread = bus.read_i2c_block_data(address, id_cmd, i2c_max_len)

print "Raw I2C read result:", i2cread
print "Would yield a version of:", i2cread[1]


If I run the script, this is the result:

tkurbad@beaglebone:~$ python revision.py 
Raw I2C read result: [0, 0, 204, 204]
Would yield a version of: 0

The correct value of i2read[1] would be 21 (or 0x15), not 0.

The raw result, btw., is also the same, regardless of what register of the motor controller I read from.

So, I'm still convinced that it has to do with the hardware and/or the setup of the I²C bus of the beaglebone...

Where else could I look?

Best, Torsten

David Lechner

unread,
May 12, 2017, 11:56:17 AM5/12/17
to beagl...@googlegroups.com
On 05/12/2017 10:48 AM, 'Torsten K.' via BeagleBoard wrote:
>
> So, I'm still convinced that it has to do with the hardware and/or the
> setup of the I²C bus of the beaglebone...
>
> Where else could I look?

Have you stuck an oscilloscope or logic analyzer on it to see what is
actually on the bus?

What are the pinconf settings for the I2C pins?

Graham Haddock

unread,
May 12, 2017, 12:44:38 PM5/12/17
to BeagleBoard
I take back what I said about a non standard read sequence. I re-read the data sheet, and they describe a standard concatenated write/read sequence for a single byte read.  But I do note that they do not describe a simple read only sequence, where the part would start reading from the last register position.

A lot of the tools do not actually do the concatenated write/read, but instead do a separate  write-stop, read-stop. I have not seen a I2C part that would not accept this.

Do you have another "trusted" I2C device you could parallel across the bus as a test device?  
I use an MCP9808 temperature sensor on most of my boards when bringing up a new design.

Or as suggested by David, put a bus analyzer on the bus to see if the chip is not sending good data, or the Beaglebone is loosing the good data when the chip sends it.

--- Graham

==

--
For more options, visit http://beagleboard.org/discuss
--- You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/-cVwfP40L0M/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard+unsubscribe@googlegroups.com.

William Hermans

unread,
May 12, 2017, 2:40:03 PM5/12/17
to beagl...@googlegroups.com
On Fri, May 12, 2017 at 9:44 AM, Graham Haddock <gra...@flexradio.com> wrote:
I take back what I said about a non standard read sequence. I re-read the data sheet, and they describe a standard concatenated write/read sequence for a single byte read.  But I do note that they do not describe a simple read only sequence, where the part would start reading from the last register position.

Yeap, that's standard I2C comms, I knew that, but kept my mouth shut. Also for what it's worth, smbus I2C is the preferred I2C comms method in Linux. But it's not impossible to use the older protocol.

Torsten K.

unread,
May 13, 2017, 4:07:18 PM5/13/17
to BeagleBoard
Hi again,


Do you have another "trusted" I2C device you could parallel across the bus as a test device?  
I use an MCP9808 temperature sensor on most of my boards when bringing up a new design.

I think I'll do that on Monday, when I'm near my Beaglebone again,

Or as suggested by David, put a bus analyzer on the bus to see if the chip is not sending good data, or the Beaglebone is loosing the good data when the chip sends it.

I've only got a small oscilloscope (1 channel) that probably won't help that much, but I can try.

Anyway, I tried i2cget on the two devices connected to the third I²C bus (i2c2) on the Beaglebone Blue. One is the MPU9250, which also works with my Python code.

If I ask this device for it's ID, I get a perfectly response:

tkurbad@beaglebone:~$ i2cget -y 2 0x68 0x75
0x71

So, I'm more and more under the impression that somethings wrong in the way the second I²C bus (i2c1) is set up. This is the only broken out bus on the Beaglebone Blue, so I don't have a chance but put my motor controller there.

So, I'll try another - confirmedly working - device on Monday and report back.

Thank you so far and best regards,
Torsten

Torsten K.

unread,
May 15, 2017, 4:59:03 AM5/15/17
to BeagleBoard
Hi again,

this morning, I connected another IMU unit (Polulu AltIMU10 v5) in parallel to the motor controller on I²C bus #1.
It works flawlessly and I can read the ID of the accel/gyro unit using i2cget:

tkurbad@beaglebone:~/projects/mipSIE/python3$ i2cget -y 1 0x6b 0x0f
0x69

However, I still can't read from the motor controller. The working IMU however leads to the conclusion that the problem must lie with the motor controller, not with the Beaglebone.

I've ordered a PIC debugger to see what's going on inside the PIC on the motor controller that does all the I²C communication.

Anyway, thanks for all your help!

Best,
Torsten

Graham

unread,
May 15, 2017, 9:07:15 AM5/15/17
to BeagleBoard
Torsten:

OK. That makes more sense.  

If it is a PIC misbehaving, I would re-program it first, then make sure you have good bypass capacitor to ground, with short leads, on the power input pin to the ground pin on the PIC.

Good luck.

--- Graham

==

Torsten K.

unread,
May 15, 2017, 10:36:07 AM5/15/17
to BeagleBoard
Hi Graham,

just for reference: The guys who built the motor controller confirmed that they are having trouble with newer kernels on the Raspberry PI, too.


They say it's probably a timing issue. And with all the information I collected so far I must assume they are probably true. ;-)

I hope it's not the PIC itself that can't cope, but rather something that could be solved in software...

Best,
Torsten

Graham Haddock

unread,
May 15, 2017, 12:33:20 PM5/15/17
to BeagleBoard
What part number PIC?
--- Graham

==

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/-cVwfP40L0M/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard+unsubscribe@googlegroups.com.

Graham Haddock

unread,
May 15, 2017, 12:39:10 PM5/15/17
to BeagleBoard
When they say drop the clock speed on the bus, I am sure they mean to drop it down to 50kbps or 10 kbps, and see if it starts working.
As a diagnostic, that would be strong indication of a timing problem in the PIC software.

If they are using the PIC hardware peripheral, then it is totally I2C compliant/conforming, although you could still screw up the response time servicing it slowly internally.

If they are "bit-banging" the I2C interface, then anything can happen, depending on the quality of the programmer.

--- Graham

Torsten K.

unread,
May 15, 2017, 12:46:14 PM5/15/17
to BeagleBoard
Hi Graham,


Am Montag, 15. Mai 2017 18:39:10 UTC+2 schrieb Graham:
When they say drop the clock speed on the bus, I am sure they mean to drop it down to 50kbps or 10 kbps, and see if it starts working.
As a diagnostic, that would be strong indication of a timing problem in the PIC software.

I tried bus speeds down to 50 kbps to no avail. I'll probably try 10 kbps tomorrow.

Unfortunately, I never programmed a PIC, so I'll probably have a hard time finding out what's going on.

Best,
Torsten

Torsten K.

unread,
May 19, 2017, 6:21:07 AM5/19/17
to BeagleBoard
Status Update (a bit off topic for beagleboard, I suppose):

I took the MPLABX PIC code that the PiBorg folks provided for their motor controller and ported it to the sdcc compiler, so I have a chance to understand what's going on.

Result is here:


If I flash the hex file to the PIC it behaves exactly as it does with the original code, i.e. all I2C reads return 0x00 and all writes result in the desired action.

Now follows the debugging...

Best,
Torsten

Torsten K.

unread,
May 29, 2017, 10:32:16 AM5/29/17
to BeagleBoard
FYI: It's working now. The PIC code that came with the motor controller was not I²C re-start aware.

I re-implemented the ISR to accept both stop/start and re-start sequences before reading the slave's output. That did the trick.

Best,
Torsten

Graham Haddock

unread,
May 29, 2017, 10:43:28 AM5/29/17
to BeagleBoard
Torsten:
Great job.
--- Graham

==

--
For more options, visit http://beagleboard.org/discuss
---
You received this message because you are subscribed to a topic in the Google Groups "BeagleBoard" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/beagleboard/-cVwfP40L0M/unsubscribe.
To unsubscribe from this group and all its topics, send an email to beagleboard+unsubscribe@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages