Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AbsoluteIMU ev3dev2 #650

Closed
southernwindle opened this issue Jul 24, 2019 · 26 comments
Closed

AbsoluteIMU ev3dev2 #650

southernwindle opened this issue Jul 24, 2019 · 26 comments

Comments

@southernwindle
Copy link

  • ev3dev version: 4.14.96-ev3dev-2.3.2-ev3
  • ev3dev-lang-python version:
Desired=Unknown/Install/Remove/Purge/Hold
| Status=Not/Inst/Conf-files/Unpacked/halF-conf/Half-inst/trig-aWait/Trig-pend
|/ Err?=(none)/Reinst-required (Status,Err: uppercase=bad)
||/ Name                                                         Version                             Architecture                        Description
+++-============================================================-===================================-===================================-==============================================================================================================================
ii  python3-ev3dev                                               1.2.0                               all                                 Python language bindings for ev3dev
ii  python3-ev3dev2                                              2.0.0~beta3                         all                                 Python language bindings for ev3dev

I am attempting to connect an AbsoluteIMU-ACG from mindsensors.com though ev3dev2-python

I have tried a few options but have not been able to figure it out, How would I get this connected and measure the values of it? Thanks.

@dlech
Copy link
Member

dlech commented Jul 24, 2019

Can you share the code of what you have tried so far?

@southernwindle
Copy link
Author

from ev3dev2.port import LegoPort

imu = LegoPort(address='ev3-ports:in2:i2c17')
imu.mode = 'uart'

imu.set_device('ms-absolute-imu')

abs = Sensor('ev3-ports:in2:i2c17')

the set_device and sensor always returns an error, I do not have access to the ev3 at this current time so I cannot send the error.

@dlech
Copy link
Member

dlech commented Jul 25, 2019

Try adding a delay after setting the device before creating the sensor object. It takes some time for it to get set up in the kernel.

@southernwindle
Copy link
Author

I have tried that, it doesn't appear to work even after 5 minutes (I tried doing it through SSH too)

@dlech
Copy link
Member

dlech commented Jul 25, 2019

one second should be more than enough

@dlech
Copy link
Member

dlech commented Jul 25, 2019

I just noticed that you are putting the port in uart mode. This is an I2C sensor, so it should be nxt-i2c.

@dlech
Copy link
Member

dlech commented Jul 25, 2019

And actually this sensor should be automatically detected, so you shouldn't have to mess with the port at all

@dlech
Copy link
Member

dlech commented Jul 25, 2019

Does the sensor show up in the Device Browser on the brick?

@southernwindle
Copy link
Author

Yes

@dlech
Copy link
Member

dlech commented Jul 25, 2019

The default address is 1, so abs = Sensor(address='ev3-ports:in2:i2c1') should be all you need (you can double-check the address against the one you see on the EV3).

@southernwindle
Copy link
Author

Alright, I got it working. Is there any way to read out each different value at the same time without having to change its mode?

also is there any documentation for this specifically

@dlech
Copy link
Member

dlech commented Jul 25, 2019

http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/sensor_data.html#ms-absolute-imu

It looks like there is an ALL mode to read everything at once.

@dlech
Copy link
Member

dlech commented Jul 25, 2019

You will probably have to read bin_data and use struct.unpack(...) for this mode because I'm pretty sure that the number of valueX attributes is limited to 8 (0 to 7). The description of the data can be found in the users guide for the sensor: http://www.mindsensors.com/pdfs/AbsoluteIMU-User-Guide.pdf

Totally untested, but hopefully close...

import struct

...

(x_tilt, y_tilt, z_tilt, x_accel, y_accel, z_accel, compass, x_mag, y_mag, z_mag,
 x_gyro, y_gyro, z_gyro) = struct.unpack('bbb<h<h<h<h<h<h<h<h<h<h', abs.bin_data)

It is also possible to use x in the format string to skip over any values that your aren't using.

https://docs.python.org/3.5/library/struct.html#struct-format-strings

@omartin2010
Copy link
Contributor

self.gyroSensor.bin_data('<b16xh4x') outputs: (0,0) and I know this isn't right... in fact even if I don't skip any of the values (self.gyroSensor.bin_data('<bbbbbbbbbbbbbbbbbbbbbbb'), everything I extract out of this gives 0,0,0,0,0,0,.. which doesn't feel right. Basically the bin_data seems to give 0 all the time... perhaps it requires some initialization...

@ZMcWilliam
Copy link

ZMcWilliam commented Aug 27, 2019

This code works assuming that the gyro is plugged into in2, it can easily be changed to work for any other port

absport = LegoPort(address='ev3-ports:in2')
absport.mode = 'nxt-i2c'

abs = Sensor('ev3-ports:in2:i2c17')

This should setup the sensor and allow it to be accessed, the Sensor class needs to be imported from sensor.lego

to use the gyro you must set the mode you want and then call the value

To find the mode/value you can find information here:
http://docs.ev3dev.org/projects/lego-linux-drivers/en/ev3dev-stretch/sensor_data.html#ms-absolute-imu
If I wanted the X-axis angle (tilt) I would use this code:

abs.mode = "TILT"
print(abs.value(0))

@southernwindle
Copy link
Author

Thanks @1StormDragon! That works perfectly.
I hope that helps you too @omartin2010

@omartin2010
Copy link
Contributor

I'm essentially doing what you're describing above - I'm ok running it in "tilt mode" but whenever I try running it in "ALL" mode, which is what I need for my application, then I get all zeros from the bin_data. Flip it to "TILT" mode, and I get my readings... any clue?

@omartin2010
Copy link
Contributor

in fact, after thinking things a bit, I suspect there being something to do with the driver. The TILT, GYRO, etc. modes can all be read independently so it's got to have something to do with the driver level at the OS (since the same problem can be seen from the OS :

robot@ev3dev:/sys/class/lego-sensor/sensor0$ echo 'TILT' > mode 
robot@ev3dev:/sys/class/lego-sensor/sensor0$ cat value0
157 
robot@ev3dev:/sys/class/lego-sensor/sensor0$ echo 'ALL' > mode
robot@ev3dev:/sys/class/lego-sensor/sensor0$ cat value0
0 
robot@ev3dev:/sys/class/lego-sensor/sensor0$

Any pointer to the driver in the code I could take a look at? Or idea of what else to look for?

@dlech
Copy link
Member

dlech commented Aug 27, 2019

Any pointer to the driver in the code I could take a look at

https://github.com/ev3dev/lego-linux-drivers/blob/bd56e4527bfe7eacddf3e8135463e69e2bdcb6e3/sensors/nxt_i2c_sensor_defs.c#L1723

self.gyroSensor.bin_data('<b16xh4x')

This is wrong. '<b16xh4x' is an argument to struct.unpack(), not bin_data.


robot@ev3dev-ev3:/sys/class/lego-sensor/sensor3$ hd bin_data
00000000  d0 d1 ca 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020

It looks like only the first few data values are non-zero, so maybe it is not possible to read everything at once?

Possible workaround is to set the mode and read one value you need, the change the mode and read another value. It will be slightly slower, but it should work just fine.

@omartin2010
Copy link
Contributor

Agreed it looks wrong, but bin_data('fmt') takes fmt as an argument (at least according to here). I've also tried the struct.unpack() route, and got zeroes.

robot@ev3dev:/sys/class/lego-sensor/sensor1$ hd bin_data
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000020
robot@ev3dev:/sys/class/lego-sensor/sensor1$ cat mode                                                                                                                                            
ALL
robot@ev3dev:/sys/class/lego-sensor/sensor1$ cd ../sensor4                                                                                                                                       
robot@ev3dev:/sys/class/lego-sensor/sensor4$ hd bin_data                                                                                                                                         
00000000  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
*
00000020

and if I change the mode...

robot@ev3dev:/sys/class/lego-sensor/sensor1$ echo 'TILT' > mode
robot@ev3dev:/sys/class/lego-sensor/sensor1$ hd bin_data
00000000  a0 80 03 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000010  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00  |................|
00000020
robot@ev3dev:/sys/class/lego-sensor/sensor1$

tadam. That's why I'm thinking it has nothing to do with Python in this case...

@dlech
Copy link
Member

dlech commented Aug 27, 2019

robot@ev3dev-ev3:/sys/class/lego-sensor/sensor3$ echo ALL > mode
robot@ev3dev-ev3:/sys/class/lego-sensor/sensor3$ hd bin_data
00000000  db 79 db be 02 cb ff 88  02 af 00 ac ff ea 00 11  |.y..............|
00000010  fa 19 fa 13 00 e6 ff 00  00 00 00 00 00 00 00 00  |................|
00000020

Oops, I forgot to set the mode to ALL. Look like it is "works for me". 😕

@dlech
Copy link
Member

dlech commented Aug 27, 2019

The fact you are getting all 0s is strange because the driver doesn't actually do anything when you set the mode other than changing the register index and size of data that is being read. The TILT mode and the ALL mode both read from the same starting register, but read a different number of bytes.

Although I just realized that you are probably using BrickPi3, not EV3, so that is probably the issue.

@omartin2010
Copy link
Contributor

I am indeed using BrickPi3. Not sure how that can cause an issue. And 2 stacked boards... and 2 sensors. So I'll try removing one of the boards and go with a single sensor. Although both sensor read from "TILT" without any problem (although I'm not super impressed with the precision... my phone's level is way more precise). But that's a very different problem. What do you have to set, again, under /sys/class/lego-ports/port0/ so that this becomes a /sys/class/lego-sensor/.. ? I forget if/how this can be done directly at the command line versus in Python.

@dlech
Copy link
Member

dlech commented Aug 27, 2019

For starters, since we have determined this is not a python problem, lets open a new issue at https://github.com/ev3dev/ev3dev/issues and continue the discussion there.

@omartin2010
Copy link
Contributor

Thanks, done (see here)

@gaminoi
Copy link

gaminoi commented Aug 30, 2021

Hello, I'm newbie with EV3DEV and I'm trying to make my absolute sensor working on my ev3.
The sensor is recognized by the brick but i have a problem with loading the "sensor.lego" module.
Here is the error message in vscode :

Traceback (most recent call last):
File "/home/robot/vscode-hello-python-master/test mindstorm.py", line 5, in
from sensor.lego import Sensor
ImportError: No module named 'sensor'

Kernel 4.14.117-ev3dev-2.3.5-ev3

Can you help me please ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants