I2C Send, Lejos 0.9

This is where you talk about the NXJ hardware related topics such as the brick, sensors, LEGO pieces, etc.

Moderators: 99jonathan, roger, imaqine

I2C Send, Lejos 0.9

Postby TechnoX » Sat May 07, 2011 3:51 pm

Hey!
I have tested the code from the snapshot (April 6'th) and I think I have found a bug or mistake from your side.

In this thread gloomyandy say that one should always call i2cComplete after an i2cStart. I know this is for lejos 0.8.5, but is this also true for the new version?
For me it seems like that, because you have them both in the i2cTransaction method.
Why do one need to call i2cComplete after an i2cStart, if one just want to send bytes??
You have abstracted away the two low level methods (i2cStart and i2cComplete) in the new lejos. I can't call them from an I2CPort anymore.

The problem comes when you for example want to change the address of an Mindsensor sensor, in the datasheet they say:
Changing the I2C Bus Address:
The I2C bus address of DIST-Nx can be changed. To set an address
different from default address, send sequence of following
commands on the command register:
0xA0, 0xAA, 0xA5, <new I2C address>
Note: Send these commands with no break/read operation in
between. This new address is effective immediately. Please note
down your address carefully for future reference.

The fact that the sensor don't allow any break/read operation in between cause problems.

To make it work I use
Code: Select all
SensorPort.S1.i2cStart(old, new byte[]{0x41, (byte)0xA0}, 0, 2, 0);
Delay.msDelay(50);
SensorPort.S1.i2cStart(old, new byte[]{0x41, (byte)0xAA}, 0, 2, 0);
Delay.msDelay(50);
SensorPort.S1.i2cStart(old, new byte[]{0x41, (byte)0xA5}, 0, 2, 0);
Delay.msDelay(50);
SensorPort.S1.i2cStart(old, new byte[]{0x41, (byte)newAddress}, 0, 2, 0);
Delay.msDelay(50);

I think this code is very odd, and I can't make a general solution for an arbitrary sensor port. I would suggest you to at least have the i2cStart left in the I2CPort interface. Or some other solution to just send data.

In addition I have some problem with more than one I2C sensor on the same port. Maybe it's the same bug that fail activation of ADPA. But it can as well be my electronic skills that cause that...
TechnoX
Novice
 
Posts: 52
Joined: Tue May 03, 2011 5:57 pm
Location: Sweden

Re: I2C Send, Lejos 0.9

Postby gloomyandy » Sat May 07, 2011 5:54 pm

Hi,
Thanks for taking the time to try the 0.9 snapshot. Please see my comments below...

You need to call i2cComplete so that you can
a) Obtain the result of the write operation (check for errors), the actual i2c operations are only started by the call to start, they run asynchronously.
b) So we know we can release the bus.
Note that calling i2cComplete will send nothing to the sensor, so using it should have no impact on any i2c operations like the ones needed to set the address of some devices. If you do not want to release the bus between transactions you can enable the port using the NO_RELEASE mode (but I'm not sure that you will ever need to do this).

The i2cStart etc. methods are still available in the SensorPort class and can be used from there. Though we don't expect many people to need them which is why we have removed them from the I2CPort class. I'm not sure I understand your comment about any difficulty in using the SensorPort class rather than I2CPort as I2CPort is only an interface, the only concrete implementation of which is SensorPort. Perhaps you could explain more?

The following code works fine for me to set the address of a Mindsensors accelerometer/NXTCam/Dist-NX:
Code: Select all
        int old = 2;
        int newAddress = 10;
        I2CPort s = SensorPort.S1;
        s.i2cEnable(I2CPort.LEGO_MODE);
        s.i2cTransaction(old, new byte[]{0x41, (byte)0xA0}, 0, 2, null, 0, 0);
        Delay.msDelay(50);
        s.i2cTransaction(old, new byte[]{0x41, (byte)0xAA}, 0, 2, null, 0, 0);
        Delay.msDelay(50);
        s.i2cTransaction(old, new byte[]{0x41, (byte)0xA5}, 0, 2, null, 0, 0);
        Delay.msDelay(50);       
        s.i2cTransaction(old, new byte[]{0x41, (byte)newAddress}, 0, 2, null, 0, 0);
        Delay.msDelay(50);
        s.i2cDisable();

You can use the sample program I2CDevices to check to see if the address has been changed.

Multiple devices on the same port seem to work fine for me. I have 3 mindsensors devices (NXTCam, 3 axis accerometer and DIST-Nx) all connected via a port splitter here on my bench and working fine. I can also use the HiTechnics compass sensor with one of the above devices, but it does not seem so happy with 3 or more devices on the same bus. Is it possible for you test your setup in some other way?

Hope the above makes some sort of sense

Andy
User avatar
gloomyandy
leJOS Team Member
 
Posts: 4184
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: I2C Send, Lejos 0.9

Postby TechnoX » Sat May 07, 2011 7:34 pm

Thanks for fast reply! (y)

a) So the return code of i2cStart() don't tell if the write operation was successful? Which information does it return? :)
b) Okay, I thought that it did send some extra bytes. Thanks for that information!



Your code works fine! I have tried to change address for days and I was sure I had tested this one, but it seems like I must have forgotten the Delays. Without the pauses the addresses does not change. Why? The i2cTransaction returns -5 (ERR_BUS_BUSY).
Doesn't the i2cComplete wait for the bus to not be busy?
In the i2cTransaction there is code to handle ERR_BUS_BUSY. I'm sorry, I don't really understand how it should work.
How can I know how long I have to wait before the next transaction? A while-loop that checks i2cStatus every iteration?



I wanted to use I2CSensor, to get access to getProductID and such methods. Another reason is because the I2CSensor class have I2CEnable, address etc. inside itself.
Then this code fails because getPort() return a I2CPort:
Code: Select all
I2CSensor sensor = new I2CSensor(SensorPort.S1, old, I2CPort.LEGO_MODE, I2CSensor.TYPE_LOWSPEED);
sensor.getPort().i2cStart(...);

Of course I can use the SensorPort class, and keep track of the address and i2cEnable by myself :)
Code: Select all
SensorPort sensor = SensorPort.S1;
[...]
sensor.i2cStart(...);




Yeah, the standard sensors work fine on the same port. For example I can use two DIST-Nx, or DIST-Nx with some other I2C sensor (Ultrasonic or a homemade TouchMux).
But I have bought a TPA81 Thermopile, and when I use it togheter with the DIST-Nx, the heat sensor takes over all communication and I just get the heat data. I have tested with different values on the pullups (from 33k to 100k). I even tested without pullups and then I got some data from the DIST-Nx, but not correct (like 65300).
TechnoX
Novice
 
Posts: 52
Joined: Tue May 03, 2011 5:57 pm
Location: Sweden

Re: I2C Send, Lejos 0.9

Postby gloomyandy » Sat May 07, 2011 9:27 pm

Hi,
The return value from the start command tells you if the operation was able to be started. It may fail for various reasons a bad port number, the port already being used by another thread, the bus being busy etc. The status returned by the complete method tells you if the operation has completed or not, or if there was some sort of data transfer error.

I'm a little puzzled as to why you seem to be trying to combine the address setting operation into the sensor class. Normally the address setting operation is a very rare operation and you would normally just set the address once (with a separate program) and it is done. All you need to do then is to use the correct address when you create the Sensor object. In 0.9 we have switched to making the i2c address be a parameter to the constructor for those sensors that can have different addresses. If you find one that does not have such a constructor you can still use the setAddress method (it has been deprecated), but please let us know and we will act the required constructor.

I'm not sure why you care about how long to wait. The only time you need the delay is when setting the address and a wait of 50ms seems fine. I assume that during this period the device is busy and will not respond to i2c requests. I suspect that I still don't understand what it is you are trying to do. For instance why do you still want to access the start method directly?

As to your TPA81 device, I'm afraid I can't offer much help I don't have one so can't test it. I suspect that a combination of the protection resistor built into the NXT port, the voltages used by the NXT and the sensor, and the logic 0 and 1 thresholds of the devices just mean that when you load the bus with more than one sensor things just don't work... Sorry but that's probably just the way it is. You may be able to fix it by using some sort of level shifter or buffer, but it's not possible to be sure without actually trying it...

Andy
User avatar
gloomyandy
leJOS Team Member
 
Posts: 4184
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Re: I2C Send, Lejos 0.9

Postby TechnoX » Sat May 07, 2011 10:04 pm

gloomyandy wrote:The return value from the start command tells you if the operation was able to be started. It may fail for various reasons a bad port number, the port already being used by another thread, the bus being busy etc. The status returned by the complete method tells you if the operation has completed or not, or if there was some sort of data transfer error.
Okay, seems logical :)

gloomyandy wrote:I'm a little puzzled as to why you seem to be trying to combine the address setting operation into the sensor class. Normally the address setting operation is a very rare operation and you would normally just set the address once (with a separate program) and it is done.[...]
Good point ;) It's true!
I try to understand how I2C works in lejos, and I'm starting simple by changing a address. Which wasn't so easy until I realised I had missed the delays...
I have an Wii Motion Plus I want to access, and I'm learning how to send data by changing address of the sensor :) Later on I want to read the MotionPlus continuously and then I need to have a as short as possible delay.


gloomyandy wrote:I'm not sure why you care about how long to wait. The only time you need the delay is when setting the address and a wait of 50ms seems fine. I assume that during this period the device is busy and will not respond to i2c requests. I suspect that I still don't understand what it is you are trying to do. For instance why do you still want to access the start method directly?
It was a response to why I originally wanted to have i2cStart in the I2CPort interface:
gloomyandy wrote:I'm not sure I understand your comment about any difficulty in using the SensorPort class rather than I2CPort as I2CPort is only an interface, the only concrete implementation of which is SensorPort. Perhaps you could explain more?
Now when i2cTransaction works, and even sendData() there is no need for i2cStart, as you said. Thanks!


gloomyandy wrote:As to your TPA81 device, I'm afraid I can't offer much help I don't have one so can't test it. I suspect that a combination of the protection resistor built into the NXT port, the voltages used by the NXT and the sensor, and the logic 0 and 1 thresholds of the devices just mean that when you load the bus with more than one sensor things just don't work... Sorry but that's probably just the way it is. You may be able to fix it by using some sort of level shifter or buffer, but it's not possible to be sure without actually trying it...
Okay, I can just move some other combos of sensors to the split and use the thermopile on a separate port. So it isn't such a big problem just now :)


EDIT: I was just looking at your homepage, and guess what I found! You have already done a MotionPlus :D
Now I'm very happy, just sitting here with a big smile :D
TechnoX
Novice
 
Posts: 52
Joined: Tue May 03, 2011 5:57 pm
Location: Sweden


Return to NXJ Hardware

Who is online

Users browsing this forum: No registered users and 0 guests

cron
more stuff