NETMF_Autopilot/Hardware/LSM303DLM_Magnetometer.cs

194 lines
6.5 KiB
C#
Raw Permalink Blame History

using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
namespace PlaneOnBoardSoftware
{
public class LSM303DLM_Magnetometer : I2CBase
{
private class Register
{
public const byte CRA_REG_M = 0x00;
public const byte CRB_REG_M = 0x01;
public const byte MR_REG_M = 0x02;
public const byte OUT_X_L_M = 0x04;
public const byte OUT_X_H_M = 0x03;
public const byte OUT_Y_L_M = 0x06;
public const byte OUT_Y_H_M = 0x05;
public const byte OUT_Z_L_M = 0x08;
public const byte OUT_Z_H_M = 0x07;
}
private I2CDevice.Configuration _config;
private bool _PowerDown = false;
public float CalXoffSet = 0;
public float CalYoffSet = 0;
public float CalZoffSet = 0;
public float CalXscale = 1f / 320;
public float CalYscale = 1f / 320;
public float CalZscale = 1f / 320;
private float maxX = 0;
private float minX = 0;
private float maxY = 0;
private float minY = 0;
private float maxZ = 0;
private float minZ = 0;
private bool _calibrationmode = false;
public Vector3D MagValue = new Vector3D();
public bool CalibrationMode
{
get { return _calibrationmode; }
set
{
_calibrationmode = value;
if (_calibrationmode)
{
maxX = 0;
minX = 0;
maxY = 0;
minY = 0;
maxZ = 0;
minZ = 0;
}
else
{
CalXoffSet = (maxX + minX) / 2;
CalYoffSet = (maxY + minY) / 2;
CalZoffSet = (maxZ + minZ) / 2;
CalXscale = 2f / (maxX - minX);
CalYscale = 2f / (maxY - minY);
CalZscale = 2f / (maxZ - minZ);
}
}
}
public LSM303DLM_Magnetometer()
{
_config = new I2CDevice.Configuration(0x1E, 400);
// 0x10 = 00010000 -> 15 Hz update rate
Write(Register.CRA_REG_M, 0x10);
// 0xC0 = 11000000 -> Gain: <20>5.6 Gauss, 320 LSB/Gauss
Write(Register.CRB_REG_M, 0xC0);
// 0x00 = 00000000 Normal mode
Write(Register.MR_REG_M, 0x00);
}
public bool PowerDown
{
get
{
return _PowerDown;
}
set
{
if (value)
Write(Register.MR_REG_M, 0x03); // 0x03 = 00000011 Power-down
else
Write(Register.MR_REG_M, 0x00); // 0x00 = 00000000 Normal mode
_PowerDown = value;
}
}
private float GetMagValue(byte high, byte low)
{
var data = (Int16)((Read(high) << 8) | Read(low));
return (((float)(data)));
}
public int RequestMagValue()
{
float x, y, z;
byte[] bufferXhi = new byte[1];
byte[] bufferYhi = new byte[1];
byte[] bufferZhi = new byte[1];
byte[] bufferXlo = new byte[1];
byte[] bufferYlo = new byte[1];
byte[] bufferZlo = new byte[1];
I2CDevice.I2CTransaction[] readTransaction = new I2CDevice.I2CTransaction[12];
I2CDevice.I2CWriteTransaction write;
I2CDevice.I2CReadTransaction read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_X_H_M });
read = I2CDevice.CreateReadTransaction(bufferXhi);
readTransaction[0] = write;
readTransaction[1] = read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_X_L_M });
read = I2CDevice.CreateReadTransaction(bufferXlo);
readTransaction[2] = write;
readTransaction[3] = read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_Y_H_M });
read = I2CDevice.CreateReadTransaction(bufferYhi);
readTransaction[4] = write;
readTransaction[5] = read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_Y_L_M });
read = I2CDevice.CreateReadTransaction(bufferYlo);
readTransaction[6] = write;
readTransaction[7] = read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_Z_H_M });
read = I2CDevice.CreateReadTransaction(bufferZhi);
readTransaction[8] = write;
readTransaction[9] = read;
write = I2CDevice.CreateWriteTransaction(new Byte[] { Register.OUT_Z_L_M });
read = I2CDevice.CreateReadTransaction(bufferZlo);
readTransaction[10] = write;
readTransaction[11] = read;
var result = I2CBus.Execute(Config, readTransaction, 1000);
x = CombineBytes(bufferXhi[0], bufferXlo[0]);
z = CombineBytes(bufferYhi[0], bufferYlo[0]); // Y <--> Z Exchanged
y = CombineBytes(bufferZhi[0], bufferZlo[0]); // Z <--> Y Exchanged
if (_calibrationmode)
{
if (x > maxX) maxX = x;
if (x < minX) minX = x;
if (y > maxY) maxY = y;
if (y < minY) minY = y;
if (z > maxZ) maxZ = z;
if (z < minZ) minZ = z;
}
MagValue.X = -(x - CalXoffSet) * CalXscale;
MagValue.Z = (z - CalZoffSet) * CalZscale; // Y <--> Z Exchanged
MagValue.Y = -(y - CalYoffSet) * CalYscale; // Z <--> Y Exchanged
return result;
}
public float GetX()
{
return GetMagValue(Register.OUT_X_H_M, Register.OUT_X_L_M) * CalXscale + CalXoffSet;
}
public float GetZ()
{
return GetMagValue(Register.OUT_Y_H_M, Register.OUT_Y_L_M) * CalYscale + CalYoffSet;
}
public float GetY()
{
return GetMagValue(Register.OUT_Z_H_M, Register.OUT_Z_L_M) * CalZscale + CalZoffSet;
}
public override I2CDevice.Configuration Config
{
get { return _config; }
}
}
}