194 lines
6.5 KiB
C#
194 lines
6.5 KiB
C#
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; }
|
||
}
|
||
}
|
||
}
|