Hi all,
Has anyone written a gyro driver for the Fez yet?
Thanks.
Check back in like a week. I have an IMU on the way.
Nice work, thanks Chris.
No problem. You might have to pick the drive out from some other stuff though. What gyro is it that you want to use?
I am using the sparkfun LISY300AL.
I see… Well, I think a lot of the low level code for me is going to be done on the ATmega328, but this sensor doesn’t look too difficult. Have you already tried making a driver for it?
I have started working on a driver for the gyro, with the help of some C code by a NASA dude.
I’m at the Australian Tech Ed #auteched at the moment, so I’ll finish the driver off when I get home after the event.
The LIS uses an analog output so it wouldn’t take long to extract and calculate. I think I might even have one of them sitting around here somewhere that I can test with.
Just checked - yep I have one. Let me see what I can whip up real quick for you.
Here’s a quickie on this Gyro module. Not a class, but it’s only about 5 lines so you can put it anywhere:
using System;
using System.Threading;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
namespace GyroTest
{
public class Program
{
public static void Main()
{
OutputPort powerDown = new OutputPort((Cpu.Pin)FEZ_Pin.Digital.Di13, false);
AnalogIn gyroReading = new AnalogIn((AnalogIn.Pin)FEZ_Pin.AnalogIn.An0);
gyroReading.SetLinearScale(-300, 300);
while (true)
{
Debug.Print("Gyro Reading: " + gyroReading.Read().ToString());
}
}
}
}
Thanks Greg,
I didn’t think to use the line below, but I think it would be good for other applications.
gyroReading.SetLinearScale(-300, 300);
Your code would only return a rate or degrees at random points in time. The goal of the gyro is to take readings at defined points in time and then calculate the angle turned, thus would work like a compass, except you wouldn’t know which way is north, just what angle you are facing compared to your calibrated point.
So, your example will basically inform me of which direction the gyro is turning.
But I want to take it one step further -
- calibrate the device
- calculate the angle the gyro has turned.
[ulist]
we know that it’s measurement range is ±300°/s (Max).
We know that it’s sensitivity is 3.3mV/°/s
at 88Hz we know that we can safely get a reading every 11ms (approx).
[/ulist]
So as an example I would read from my gyro every 100ms (for an easy example).
After calibration I know that for every 3.3mV that equates to 1°/s.
because I am reading at 1/10th of a second, I divide my calibrated millivolts by 3.3 and then divide by 10. This gives me the approximate angle turned in one tenth of a second.
The equation:
/ 0.33 = Degrees turned in 1/10sec
Keep a track of the degrees turned and you have you heading in degrees relevant to your calibration point.
Hope this helps. I’ll post the code up in the next few days on the .Net micro Projects website.
RJ
If you’re going to do it that way then make sure to set your range to 0,3300 so you get proper readings.
Yep, that’s the plan. Thanks Greg.
Don’t thank me - I learned that trick from the PDF guide GHI has.
Below is my draft c# gyro driver. If you see anything I could fix up please let me know.
The gyro is a LISY300AL on a sparkfun breakout board (Image below code).
The output is like so:
- Time: 56ms, MilliVolts: 1609.40mV (1625.50mV), heading(mV): 16.10mV, Heading:0.05Degrees
- Time: 56ms, MilliVolts: 1624.30mV (1625.50mV), heading(mV): 1.20mV, Heading:0.16Degrees
- Time: 56ms, MilliVolts: 1734.20mV (1625.50mV), heading(mV): -108.70mV, Heading:19.35Degrees
- Time: 56ms, MilliVolts: 1626.40mV (1625.50mV), heading(mV): -0.90mV, Heading:4.32Degrees
using System;
using System.Threading;
using GHIElectronics.NETMF.FEZ;
using GHIElectronics.NETMF.Hardware;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
namespace GyroDriver
{
public class Program
{
public static void Main()
{
var program = new Program();
program.Start();
}
private void Start()
{
//Wait for devices to stabilise
Thread.Sleep(500);
const int sleep = 50;
//3.3mV/Deg/Sec (I needed to calibrate it to 3.2 for better readings)
const float milliVoltPerDeg = 3.2f;
const int avg = 10;
var powerDown = new OutputPort((Cpu.Pin) FEZ_Pin.Digital.Di13, false);
var gyroReading = new AnalogIn((AnalogIn.Pin) FEZ_Pin.AnalogIn.An0);
gyroReading.SetLinearScale(0, 3300);
var gyroZero = 0f;
for (var i = 0; i < avg; i++)
{
Thread.Sleep(sleep/avg);
gyroZero += gyroReading.Read();
}
gyroZero = (gyroZero/avg);
var headingMilliVolts = 0f;
var milliVolts = 0f;
var heading = 0f;
DateTime time;
var lastTime = DateTime.Now;
var count = 0;
while (true)
{
milliVolts = 0;
for (var i = 0; i < avg; i++)
{
Thread.Sleep(sleep/avg);
milliVolts += gyroReading.Read();
}
milliVolts = milliVolts/avg;
time = DateTime.Now;
headingMilliVolts = (gyroZero - milliVolts);
var subheading = (headingMilliVolts/milliVoltPerDeg*time.Subtract(lastTime).Milliseconds/1000);
if (subheading > 0.066 || subheading < -0.066)
{
heading += subheading;
}
if (count > 1000/sleep)
{
Debug.Print("Time: " + time.Subtract(lastTime).Milliseconds + "ms, MilliVolts: " +
milliVolts.ToString("F") + "mV (" + gyroZero.ToString("F") + "mV), heading(mV): " +
headingMilliVolts.ToString("F") + "mV, Heading:" + heading.ToString("F") + "Degrees");
count = 0;
}
lastTime = time;
count++;
}
}
}
}
Awesome work RJ.
I have posted my final gyro driver example on the Project website.
(link removed)