laurensvalk / segway

Code for robots balancing on two wheels, made with various robotics platforms.
MIT License
42 stars 22 forks source link

Document how to use the NXT HiTechnic Gyroscope sensor on segway.py #11

Closed BertLindeman closed 7 years ago

BertLindeman commented 7 years ago

The building instructions state you can use:

1x Gyroscopic Sensor. Use one of the following sensors:

Running segway.py with the driver for the HiTechnic gyro sensor set like this: echo ht-nxt-gyro > /sys/class/lego-port/port1/set_device

The program ends like this:

Traceback (most recent call last):
  File "./segway.py", line 52, in <module>
    gyroSensor.mode     = gyroSensor.MODE_GYRO_RATE
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 1716, in mode
    self._mode = self.set_attr_string(self._mode, 'mode', value)
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 229, in set_attr_string
    return self._set_attribute(attribute, name, value)
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 216, in _set_attribute
    raise Exception("%s is not connected" % self)
Exception: GyroSensor is not connected

Second attenpt with the HT gyro set as default analog device ends quite the same:

Traceback (most recent call last):
  File "./segway.py", line 52, in <module>
    gyroSensor.mode     = gyroSensor.MODE_GYRO_RATE
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 1716, in mode
    self._mode = self.set_attr_string(self._mode, 'mode', value)
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 229, in set_attr_string
    return self._set_attribute(attribute, name, value)
  File "/usr/lib/python3/dist-packages/ev3dev/core.py", line 216, in _set_attribute
    raise Exception("%s is not connected" % self)
Exception: GyroSensor is not connected

System info (from ev3dev-sysinfo)

Image file:         ev3dev-stretch-ev3-generic-2017-10-24
Kernel version:     4.9.49-ev3dev-1.5.1-ev3
Brickman:           0.10.0
ev3devKit:          0.5.2
Board:              board0
BOARD_INFO_HW_REV=7
BOARD_INFO_MODEL=LEGO MINDSTORMS EV3
BOARD_INFO_ROM_REV=6
BOARD_INFO_SERIAL_NUM=0016535166E2
BOARD_INFO_TYPE=main

The segway is so much fun! Thanks for that Laurens.

laurensvalk commented 7 years ago

Sensor config

You can leave the HT Sensor in nxt-analog mode. That will give you the full resolution. The code is already set up to do the appropriate conversions. We just need to change a scaling constant, as explained below.

Here is the part you'll want to change. Keep in mind that the sensor is automatically correctly set up, but the ev3dev Python library is used to easily find the location of the "value0" file that contains the sensor value.

# Gyro Sensor setup
gyroSensor          = ev3.GyroSensor()          # Replace by something like nxt-analog (not sure about its name)
gyroSensor.mode     = gyroSensor.MODE_GYRO_RATE # Remove this. The HT Gyro can only provide the rate anyway
gyroSensorValueRaw  = open(gyroSensor._path + "/value0", "rb")  # This opens the value0 file containing the sensor value we want. 

If there is nothing like "analog" in the Python library, keep only the last line, and provide the path yourself (/sys/class/lego-sensor/path/to/value/0/file)

Converting the units

The code was designed with support for other sensors in mind. The angular rate is calculated like this:

gyroRate = (gyroRateRaw - gyroOffset)*radiansPerSecondPerRawGyroUnit # Don't change this formula, it's just here to explain it

The offset and the scaling vary between the sensors. The offset is automatically calculated by the program in the calibration step, so you won't have to change that.

The scaling is configured by this constant:

degPerSecondPerRawGyroUnit     = 1   # For the LEGO EV3 Gyro in Rate mode, 1 unit = 1 deg/s

For the HiTechnic sensor, use 0.2084 for this constant.

I think the positive rotation rate was the same for the HT Sensor as for the LEGO Gyro. But if it isn't, you can mount the sensor on the other side of the Brick (swap it with the Touch Sensor.)

BertLindeman commented 7 years ago

Thank you for the to-the-point and as always well documented response. Will try and report back.

laurensvalk commented 7 years ago

Thank you for bringing it up :)

Look forward to hear how it goes.

BertLindeman commented 7 years ago

First short report: Did the software update you indicated and swapped the touch and HiTech gyro as the wheels were turning the wrong way. A bit jerky but stable with all debian services active and using wifi. Stays up for a minute or so and then oscilates out of control and drops. Will do a more detailed report later today.

BertLindeman commented 7 years ago

Status

Running EV3-brick on Image: ev3dev-stretch-ev3-generic-2017-10-24 Updated and added several packages I like; e.g. figlet bc joe bash-completion logwatch and more So it's NOT a clean image anymore.

Modifications

Software change:

Adapt segway.py: Changed this:

# Gyro Sensor setup   /BL 20171030
# gyroSensor          = ev3.GyroSensor()
# gyroSensor.mode     = gyroSensor.MODE_GYRO_RATE
# gyroSensorValueRaw  = open(gyroSensor._path + "/value0", "rb")

Into this:

gyroSensor          = ev3.Sensor(address="ev3-ports:in2")
gyroSensorValueRaw  = open(gyroSensor._path + "/value0", "rb")

Hardware change:

Added touch sensor as building instructions I used did not yet have it :-) . Swap the touch sensor and the gyro sensor as the wheels turn "the wrong way": Touch sensor on the "speaker-side" Gyro sensor on the "sd and USB" side

Seen results:

Question (I am not a python expert - far off even )

The "Platform specific constants and conversions" are within the main loop. Assume they do not change while running. Might it help a tiny bit for speed to move them to the part where the sensors/motors are setup? I ask because this may improve simple usability: The type of giro could be determined in the program without modification and at the same location set the constatns accordingly.

Suggested part of the gyro setup:

# Gyro Sensor setup   /BL 20171030 START Gyro determination
gyroSensor          = ev3.GyroSensor()
if gyroSensor._path == None:
    eprint("No EV3.GyroSensor connected; try an analog sensor")
    gyroSensor          = ev3.Sensor(address="ev3-ports:in2")
    if gyroSensor._path == None:
        eprint("No sensor connected to input port-2; Quitting")
        exit()
    else:
        # check that this *is* a default analog sensor:
        eprint("Path to Gyro=" + str(gyroSensor._path))
        eprint("        Mode=" + str(gyroSensor.mode))
        if gyroSensor.mode != "ANALOG-0":
            eprint("No ANALOG sensor with mode: ANALOG-0 is connected to input port-2; Quitting")
            exit()
        else:
            eprint("Using sensor at '" + gyroSensor.address + "' with mode " + gyroSensor.mode)
            degPerSecondPerRawGyroUnit     = 0.2084                                # For the HiTechnic Gyro in ANALOG-0 mode, 1 unit = 0.2084 deg/s
else:
    gyroSensor.mode     = gyroSensor.MODE_GYRO_RATE
    gyroSensorValueRaw  = open(gyroSensor._path + "/value0", "rb")
    degPerSecondPerRawGyroUnit     = 1                                             # For the LEGO EV3 Gyro in Rate mode, 1 unit = 1 deg/s
    eprint("Using EV3.GyroSensor at '" + gyroSensor.address + "' with mode " + gyroSensor.mode)

#                     /BL 20171030 END Gyro determination

And the variable setting degPerSecondPerRawGyroUnit removed from further down

I can only test the HT-gyro as I do not have any other...

laurensvalk commented 7 years ago

Thanks for the detailed response!

gyroSensor = ev3.Sensor(address="ev3-ports:in2")

Thanks for working this out, that is useful to know. I'll look at adding something like this to the code.

FUN

:thumbsup:

A very slight turn to the left while balancing

Since you've tried the EV3-G version you probably noticed that it compensates for this. Maybe I should add this feature here too. The steering is caused by a slight difference in friction of the motors, which is especially apparent at low speeds.

Swap the touch sensor and the gyro sensor as the wheels turn "the wrong way"

I'll look at implementing the orientation in software. Changing minus signs quickly gets very confusing, so I am not going to suggest you try that.**

The "Platform specific constants and conversions" are within the main loop.

I don't think that's currently the case. Note that there are two loops. The outermost loop defines the constants and resets sensors, prior to starting the balancing loop with the Touch Sensor.


** Just too tempting. Try changing 0.2084 to -0.2084 instead of mounting the sensor on the other side.

BertLindeman commented 7 years ago

Thanks Laurens.

** Just too tempting. Try changing 0.2084 to -0.2084 instead of mounting the sensor on the other side.

Maybe just to make it a bit clearer to the reader: set it as

# Negative value for the HiTechnic sensor to prevent turning the wrong way: 
degPerSecondPerRawGyroUnit     = 0 - 0.2084 
#

Tried this and that works, so there is no hardware mod needed.

I don't think that's currently the case. Note that there are two loops. The outermost loop defines the constants and resets sensors, prior to starting the balancing loop with the Touch Sensor.

Correct of course. I just want to keep the setting of the constants together as best as possible. And the degPerSecondPerRawGyroUnit needs to be set near the gyro setup.

There is not much spare time for me the next days, but if I can test, just ping me.

laurensvalk commented 7 years ago

Tried this and that works, so there is no hardware mod needed.

This was my mistake --- for some reason I mounted the HiTechnic sensor on the other side of the brick in the building instructions, which is rather confusing.

If it is mounted like the EV3 Gyro, no minus sign is needed, as you correctly found out. Both sensor have the same "positive rotation rate" direction.

laurensvalk commented 7 years ago

I updated the code to add support for the HiTechnic sensor. Right now without the minus sign: so the sensor is mounted just like the EV3 Gyro.

BertLindeman commented 7 years ago

Ehrm, @laurensvalk Just downloaded the current segway.py and parameters.py and tested on my EV3 brick with my HiTechnic Gyro. (Latest commit 6c278d4 ) Had to add the negative sign to get the robot balancing. The gyro is mounted on the "speaker" side of the brick. After negating the robot does balance, not perfect but sometime anyway. Maybe add a print about the time "standing"?

laurensvalk commented 7 years ago

Yes, see my note above :smile:

BertLindeman commented 7 years ago

Aaaahhh, right, so my Gyro is on the wrong side :-( "grumble" I did not have the correct "picture" of the build in my mind. Sorry for the noise ;-) Anyway the gyro detection also works for me, thank you.

laurensvalk commented 7 years ago

Thanks for your help and providing the piece of code to enable the HiTechnic Sensor! I'll close this issue then.

After negating the robot does balance, not perfect but sometime anyway.

Feel free to open a new issue for this. It seems to work allright for me. I wonder what might be causing the difference between our robots.

laurensvalk commented 7 years ago

I actually meant a new issue about the "imperfect balancing and only for some time" part, but you're right, I'll have to fix the HT Gyro placement too.