EV3-Gyro

advertisement
Eric Zielinski
Dr. Bi
CMPS 358
16, February 2014
Assignment 1
The Gyro Sensor is a part usable with the LEGO Mindstorm Real Time System that enables it to
detect both the position of the system (relative to its starting position) and the rate at which its direction
is changing (in degrees-per-second). These readings are accurate to within three degrees. Knowing
this rate of change, referred to as “angular velocity,” and the current orientation of the system are of
incredible use in constructing a moving robot. The uses of these features are extremely important in
many areas, such as trying to keep a system moving in a straight line at a steady pace, having it turn in
a way that will keep it from crashing, or following a specified path properly.
The physical Sensor is relatively easy to find and connect to the rest of the system. It is a sensor,
and thus must be connected to the 1/2/3/4 ports (rather than the a/b/c/d ports used for motors and other
actuators) via the standard wires used for all
attachments to the brick. Below is a picture of the
Gyro Sensor for your convenience:
The Gyro Sensor. Note the distinct pattern
on the Dark Gray bit. The pattern varies
between models, but generally has the same
basic shape.
Mounting the gyroscope on the robot so
that the arrow pattern is parallel to the
ground will result in left/right angle
readings.
In order to measure up/down angles (if one
wanted to measure the steepness of an
incline, for example), the gyro sensor must
be turned on its side, but not in a way that
results in the arrow pattern being
perpendicular to the ground, or the readings
will be inaccurate.
On the software end of things, using the Gyro Sensor is relatively straightforward. Only two
packages need to be imported: the ports that the brick is connected to and the Gyro Sensor itself. The
import statements to import these are
import lejos.hardware.port.Port;
and
import lejos.hardware.sensor.EV3GyroSensor;
To construct the Gyro Sensor, you simply have to declare an instance of it as you would any object in
Java: EV3GyroSensor *nameOfInstanceVariable* = new
EV3GyroSensor(*portThatPhysicalGyroSensorIsConnectedTo*);
It should be noted that the description of the port that is entered as the parameter for the constructor can
be either a standard port or a “UART port.” UART stands for “Universal Asynchronous
Receiver/Transmitter, and UART ports are used when translating data between parallel form (in which
many bits of data are communicated between two processes at the same time) and serial form (in which
data is communicated one bit at a time).
The process of initializing and declaring the Gyro Sensor is roughly the same as it is for any
other sensor. You follow the syntax EV3GyroSensor *name* = new EV3GyroSensor(*port you’re
using*). An example is shown below,
EV3GyroSensor Gyro = new EV3GyroSensor(SensorPort.S1);
The Gyro Sensor as it appears in EV3 has 3 modes. “Gyro.getAngleMode()” returns the
orientation of the sensor in whole degrees. Counter-intuitively, Clockwise rotations will return
negative degrees, while counterclockwise rotations will return positive degrees. This measurement is
taken with respect to its start orientation. “Gyro.getRateMode()” returns the current angular velocity of
the system in degrees-per-second. Once again, a clockwise motion will result in a negative angular
velocity, while a counterclockwise motion will result in a positive angular velocity.
Finally, ”Gyro.getAngleAndRateMode()” is a method that combines both the angle mode and the rate
mode. The first two modes may seem redundant, but testing shows that it operates at almost the exact
same speed as either of the individual measurements. In extremely time-sensitive situations it will
likely prove extremely beneficial to have a means of avoiding any unwanted operations.
Each of these three methods sets the sensor to the appropriate mode. To actually obtain a
reading, you must declare an array of long numbers and pass it as a parameter to the "fetch sample"
method of the sample provider the methods create. For example:
float[] AngleSamples = new float[2];
. . .
Gyro.getAngleMode().fetchSample(AngleSamples, 0);
The fetch sample method returns its readings based on exactly one reading in the case of the Gyro
Sensor. This is dangerous, given that any given reading can potentially be three degrees off. However,
the relatively high sample rate (rate at which the sensor can take readings) of 1 KHz suggests that
readings can be gathered quickly, so it may be wise to have the scanner take multiple readings and
simply pass the average of them to other functions in the program. The sample code I’ve designed to
go along with this guide demonstrates this, as it is able to accumulate 1000 readings, far more than you
would need to ensure accuracy, in roughly 5 seconds.
Calibrating the Gyro Sensor is incredibly simple. There is a void method called “Gyro.reset()”
which, as the name implies, resets the position and angular velocity of the sensor to zero. This method
should probably be used at the beginning of any operation involving the Gyro Sensor, to absolutely
ensure that no faulty readings will be lingering in the Sensor before readings begin. It should be noted
that the Gyro Sensor must remain completely motionless while the recalibration is taking place.
A Sample Program
package Gyro_Tester;
import lejos.hardware.sensor.EV3GyroSensor;
import lejos.hardware.port.SensorPort;
import lejos.hardware.lcd.*;
import lejos.utility.Delay;
public class Gyro_Tester {
public static void main(String[] args) throws InterruptedException
{
EV3GyroSensor Gyro = new EV3GyroSensor(SensorPort.S1);
Gyro.reset();
LCD.drawString("Sample size = "+Gyro.sampleSize(), 0, 2);
Delay.msDelay(2000);
LCD.clear();
long startTime;
long result = 0;
float[] AngleSamples = new float[2];
float[] RateSamples = new float[2];
float[] AngleRateSamples = new float[2];
Delay.msDelay(2000);
//Get the Angle.
for(int i = 0; i < 1000; i = i + 1){
startTime = System.currentTimeMillis();
Gyro.getAngleMode().fetchSample(AngleSamples, 0);
LCD.drawString("Angle = ", 0, 2);
LCD.drawString("= " + AngleSamples[0], 0, 3);
Delay.msDelay(10);
result = result + System.currentTimeMillis() - startTime - 10;
}
LCD.drawString("Average run time", 0, 5);
LCD.drawString("= "+(result / 1000), 0, 6);
Delay.msDelay(2000);
LCD.clear();
Delay.msDelay(2000);
//During the wait, begin manually changing the position of the
//Gyro Sensor.
//Get the Angular Velocity.
result = 0;
for(int i = 0; i < 1000; i = i + 1){
startTime = System.currentTimeMillis();
Gyro.getRateMode().fetchSample(RateSamples, 0);
LCD.drawString("Anglular Velocity", 0, 2);
LCD.drawString("= " + RateSamples[0], 0, 3);
Delay.msDelay(10);
result = result + System.currentTimeMillis() - startTime - 10;
}
LCD.drawString("Average run time", 0, 5);
LCD.drawString("= " + (result / 1000), 0, 6);
Delay.msDelay(2000);
LCD.clear();
Delay.msDelay(2000);
//Get both.
result = 0;
for(int i = 0; i < 1000; i = i + 1){
startTime = System.currentTimeMillis();
Gyro.getAngleAndRateMode().fetchSample(AngleRateSamples, 0);
LCD.drawString("Both", 0, 2);
LCD.drawString("= " + AngleRateSamples[0]+ ", "+
AngleRateSamples[1], 0, 3);
Delay.msDelay(10);
result = result + System.currentTimeMillis() - startTime - 10;
}
LCD.drawString("Average run time", 0, 5);
LCD.drawString("= " + (result / 1000), 0, 6);
Delay.msDelay(2000);
//Let the last message display
before ending the program.
}
}
Sources:
Lejos EV3 API: http://www.lejos.org/ev3/docs/lejos/hardware/sensor/EV3GyroSensor.html
Explanation of a Gyro Sensor: http://www5.epsondevice.com/en/sensing_device/gyroportal/about.html
Explanation of a Gyroscope in general: http://en.wikipedia.org/wiki/Gyroscope
Blog Post focusing on The Gyro Sensor in EV3: https://lejosnews.wordpress.com/2014/06/05/gettingheading-from-a-gyro/
Information on UART ports:
http://en.wikipedia.org/wiki/Universal_asynchronous_receiver/transmitter
Hardware specifications on the GyroSensor: http://education.lego.com/en-us/lego-education-productdatabase/mindstorms-ev3/45505-gyro-sensor/
Download