Initial commit of Julian's code

This commit is contained in:
Justin Lewis Salmon 2016-04-23 15:46:24 +02:00
commit f2be3769ef
16 changed files with 4322 additions and 0 deletions

357
Adafruit_10DOF.cpp Normal file
View file

@ -0,0 +1,357 @@
/***************************************************************************
This is a library for the Adafruit 10DOF Breakout
Designed specifically to work with the Adafruit 10DOF Breakout
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
#include <limits.h>
#include <Math.h>
#include "Adafruit_10DOF.h"
#define PI (3.14159265F);
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/***************************************************************************
CONSTRUCTOR
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates a new Adafruit_10DOF class
*/
/**************************************************************************/
Adafruit_10DOF::Adafruit_10DOF(void)
{
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_10DOF::begin()
{
// Enable I2C
Wire.begin();
return true;
}
/**************************************************************************/
/*!
@brief Populates the .pitch/.roll fields in the sensors_vec_t struct
with the right angular data (in degree)
@param event The sensors_event_t variable containing the
data from the accelerometer
@param orientation The sensors_vec_t object that will have it's
.pitch and .roll fields populated
@return Returns true if the operation was successful, false if there
was an error
@code
bool error;
sensors_event_t event;
sensors_vec_t orientation;
...
lsm303accelGetSensorEvent(&event);
error = accelGetOrientation(&event, &orientation);
@endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::accelGetOrientation(sensors_event_t *event, sensors_vec_t *orientation)
{
/* Make sure the input is valid, not null, etc. */
if (event == NULL) return false;
if (orientation == NULL) return false;
float t_pitch;
float t_roll;
float t_heading;
float signOfZ = event->acceleration.z >= 0 ? 1.0F : -1.0F;
/* roll: Rotation around the longitudinal axis (the plane body, 'X axis'). -90<=roll<=90 */
/* roll is positive and increasing when moving downward */
/* */
/* y */
/* roll = atan(-----------------) */
/* sqrt(x^2 + z^2) */
/* where: x, y, z are returned value from accelerometer sensor */
t_roll = event->acceleration.x * event->acceleration.x + event->acceleration.z * event->acceleration.z;
orientation->roll = (float)atan2(event->acceleration.y, sqrt(t_roll)) * 180 / PI;
/* pitch: Rotation around the lateral axis (the wing span, 'Y axis'). -180<=pitch<=180) */
/* pitch is positive and increasing when moving upwards */
/* */
/* x */
/* pitch = atan(-----------------) */
/* sqrt(y^2 + z^2) */
/* where: x, y, z are returned value from accelerometer sensor */
t_pitch = event->acceleration.y * event->acceleration.y + event->acceleration.z * event->acceleration.z;
orientation->pitch = (float)atan2(event->acceleration.x, signOfZ * sqrt(t_pitch)) * 180 / PI;
return true;
}
/**************************************************************************/
/*!
@brief Utilize the sensor data from an accelerometer to compensate
the magnetic sensor measurements when the sensor is tilted
(the pitch and roll angles are not equal 0<EFBFBD>)
@param axis The given axis (SENSOR_AXIS_X/Y/Z) that is
parallel to the gravity of the Earth
@param mag_event The raw magnetometer data to adjust for tilt
@param accel_event The accelerometer event data to use to determine
the tilt when compensating the mag_event values
@code
// Perform tilt compensation with matching accelerometer data
sensors_event_t accel_event;
error = lsm303accelGetSensorEvent(&accel_event);
if (!error)
{
magTiltCompensation(SENSOR_AXIS_Z, &mag_event, &accel_event);
}
@endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magTiltCompensation(sensors_axis_t axis, sensors_event_t *mag_event, sensors_event_t *accel_event)
{
/* Make sure the input is valid, not null, etc. */
if (mag_event == NULL) return false;
if (accel_event == NULL) return false;
float accel_X, accel_Y, accel_Z;
float *mag_X, *mag_Y, *mag_Z;
switch (axis)
{
case SENSOR_AXIS_X:
/* The X-axis is parallel to the gravity */
accel_X = accel_event->acceleration.y;
accel_Y = accel_event->acceleration.z;
accel_Z = accel_event->acceleration.x;
mag_X = &(mag_event->magnetic.y);
mag_Y = &(mag_event->magnetic.z);
mag_Z = &(mag_event->magnetic.x);
break;
case SENSOR_AXIS_Y:
/* The Y-axis is parallel to the gravity */
accel_X = accel_event->acceleration.z;
accel_Y = accel_event->acceleration.x;
accel_Z = accel_event->acceleration.y;
mag_X = &(mag_event->magnetic.z);
mag_Y = &(mag_event->magnetic.x);
mag_Z = &(mag_event->magnetic.y);
break;
case SENSOR_AXIS_Z:
/* The Z-axis is parallel to the gravity */
accel_X = accel_event->acceleration.x;
accel_Y = accel_event->acceleration.y;
accel_Z = accel_event->acceleration.z;
mag_X = &(mag_event->magnetic.x);
mag_Y = &(mag_event->magnetic.y);
mag_Z = &(mag_event->magnetic.z);
break;
default:
return false;
}
float t_roll = accel_X * accel_X + accel_Z * accel_Z;
float rollRadians = (float)atan2(accel_Y, sqrt(t_roll));
float t_pitch = accel_Y * accel_Y + accel_Z * accel_Z;
float pitchRadians = (float)atan2(accel_X, sqrt(t_pitch));
float cosRoll = (float)cos(rollRadians);
float sinRoll = (float)sin(rollRadians);
float cosPitch = (float)cos(-1*pitchRadians);
float sinPitch = (float)sin(-1*pitchRadians);
/* The tilt compensation algorithm */
/* Xh = X.cosPitch + Z.sinPitch */
/* Yh = X.sinRoll.sinPitch + Y.cosRoll - Z.sinRoll.cosPitch */
*mag_X = (*mag_X) * cosPitch + (*mag_Z) * sinPitch;
*mag_Y = (*mag_X) * sinRoll * sinPitch + (*mag_Y) * cosRoll - (*mag_Z) * sinRoll * cosPitch;
return true;
}
/**************************************************************************/
/*!
@brief Populates the .heading fields in the sensors_vec_t
struct with the right angular data (0-359<EFBFBD>)
Heading increases when measuring clockwise
@param axis The given axis (SENSOR_AXIS_X/Y/Z)
@param event The raw magnetometer sensor data to use when
calculating out heading
@param orientation The sensors_vec_t object where we will
assign an 'orientation.heading' value
@code
magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation);
@endcode
*/
/**************************************************************************/
bool Adafruit_10DOF::magGetOrientation(sensors_axis_t axis, sensors_event_t *event, sensors_vec_t *orientation)
{
/* Make sure the input is valid, not null, etc. */
if (event == NULL) return false;
if (orientation == NULL) return false;
switch (axis)
{
case SENSOR_AXIS_X:
/* Sensor rotates around X-axis */
/* "heading" is the angle between the 'Y axis' and magnetic north on the horizontal plane (Oyz) */
/* heading = atan(Mz / My) */
orientation->heading = (float)atan2(event->magnetic.z, event->magnetic.y) * 180 / PI;
break;
case SENSOR_AXIS_Y:
/* Sensor rotates around Y-axis */
/* "heading" is the angle between the 'Z axis' and magnetic north on the horizontal plane (Ozx) */
/* heading = atan(Mx / Mz) */
orientation->heading = (float)atan2(event->magnetic.x, event->magnetic.z) * 180 / PI;
break;
case SENSOR_AXIS_Z:
/* Sensor rotates around Z-axis */
/* "heading" is the angle between the 'X axis' and magnetic north on the horizontal plane (Oxy) */
/* heading = atan(My / Mx) */
orientation->heading = (float)atan2(event->magnetic.y, event->magnetic.x) * 180 / PI;
break;
default:
return false;
}
/* Normalize to 0-359<35> */
if (orientation->heading < 0)
{
orientation->heading = 360 + orientation->heading;
}
return true;
}
/**************************************************************************/
/*!
@brief Populates the .roll/.pitch/.heading fields in the sensors_vec_t
struct with the right angular data (in degree).
The starting position is set by placing the object flat and
pointing northwards (Z-axis pointing upward and X-axis pointing
northwards).
The orientation of the object can be modeled as resulting from
3 consecutive rotations in turn: heading (Z-axis), pitch (Y-axis),
and roll (X-axis) applied to the starting position.
@param accel_event The sensors_event_t variable containing the
data from the accelerometer
@param mag_event The sensors_event_t variable containing the
data from the magnetometer
@param orientation The sensors_vec_t object that will have it's
.roll, .pitch and .heading fields populated
*/
/**************************************************************************/
bool Adafruit_10DOF::fusionGetOrientation(sensors_event_t *accel_event, sensors_event_t *mag_event, sensors_vec_t *orientation)
{
/* Make sure the input is valid, not null, etc. */
if ( accel_event == NULL) return false;
if ( mag_event == NULL) return false;
if ( orientation == NULL) return false;
float const PI_F = 3.14159265F;
/* roll: Rotation around the X-axis. -180 <= roll <= 180 */
/* a positive roll angle is defined to be a clockwise rotation about the positive X-axis */
/* */
/* y */
/* roll = atan2(---) */
/* z */
/* */
/* where: y, z are returned value from accelerometer sensor */
orientation->roll = (float)atan2(accel_event->acceleration.y, accel_event->acceleration.z);
/* pitch: Rotation around the Y-axis. -180 <= roll <= 180 */
/* a positive pitch angle is defined to be a clockwise rotation about the positive Y-axis */
/* */
/* -x */
/* pitch = atan(-------------------------------) */
/* y * sin(roll) + z * cos(roll) */
/* */
/* where: x, y, z are returned value from accelerometer sensor */
if (accel_event->acceleration.y * sin(orientation->roll) + accel_event->acceleration.z * cos(orientation->roll) == 0)
orientation->pitch = accel_event->acceleration.x > 0 ? (PI_F / 2) : (-PI_F / 2);
else
orientation->pitch = (float)atan(-accel_event->acceleration.x / (accel_event->acceleration.y * sin(orientation->roll) + \
accel_event->acceleration.z * cos(orientation->roll)));
/* heading: Rotation around the Z-axis. -180 <= roll <= 180 */
/* a positive heading angle is defined to be a clockwise rotation about the positive Z-axis */
/* */
/* z * sin(roll) - y * cos(roll) */
/* heading = atan2(--------------------------------------------------------------------------) */
/* x * cos(pitch) + y * sin(pitch) * sin(roll) + z * sin(pitch) * cos(roll)) */
/* */
/* where: x, y, z are returned value from magnetometer sensor */
orientation->heading = (float)atan2(mag_event->magnetic.z * sin(orientation->roll) - mag_event->magnetic.y * cos(orientation->roll), \
mag_event->magnetic.x * cos(orientation->pitch) + \
mag_event->magnetic.y * sin(orientation->pitch) * sin(orientation->roll) + \
mag_event->magnetic.z * sin(orientation->pitch) * cos(orientation->roll));
/* Convert angular data to degree */
orientation->roll = orientation->roll * 180 / PI_F;
orientation->pitch = orientation->pitch * 180 / PI_F;
orientation->heading = orientation->heading * 180 / PI_F;
return true;
}

53
Adafruit_10DOF.h Normal file
View file

@ -0,0 +1,53 @@
/***************************************************************************
This is a library for the Adafruit 10DOF Breakout
Designed specifically to work with the Adafruit 10DOF Breakout
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#ifndef __ADAFRUIT_10DOF_H__
#define __ADAFRUIT_10DOF_H__
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Adafruit_Sensor.h"
#include "Adafruit_LSM303_U.h"
#include "Adafruit_BMP085_U.h"
#include "Adafruit_L3GD20_U.h"
#include <Wire.h>
/** Sensor axis */
typedef enum
{
SENSOR_AXIS_X = (1),
SENSOR_AXIS_Y = (2),
SENSOR_AXIS_Z = (3)
} sensors_axis_t;
/* Driver for the the 10DOF breakout sensors */
class Adafruit_10DOF
{
public:
Adafruit_10DOF(void);
bool begin(void);
bool accelGetOrientation ( sensors_event_t *event, sensors_vec_t *orientation );
bool magTiltCompensation ( sensors_axis_t axis, sensors_event_t *mag_event, sensors_event_t *accel_event );
bool magGetOrientation ( sensors_axis_t axis, sensors_event_t *event, sensors_vec_t *mag_orientation );
bool fusionGetOrientation ( sensors_event_t *accel_event, sensors_event_t *mag_event, sensors_vec_t *orientation );
private:
};
#endif

481
Adafruit_BMP085_U.cpp Normal file
View file

@ -0,0 +1,481 @@
/***************************************************************************
This is a library for the BMP085 pressure sensor
Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout
----> http://www.adafruit.com/products/391
----> http://www.adafruit.com/products/1603
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#ifdef __AVR_ATtiny85__
#include "TinyWireM.h"
#define Wire TinyWireM
#else
#include <Wire.h>
#endif
#include <math.h>
#include <limits.h>
#include "Adafruit_BMP085_U.h"
static bmp085_calib_data _bmp085_coeffs; // Last read accelerometer data will be available here
static uint8_t _bmp085Mode;
#define BMP085_USE_DATASHEET_VALS (0) /* Set to 1 for sanity check */
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Writes an 8 bit value over I2C
*/
/**************************************************************************/
static void writeCommand(byte reg, byte value)
{
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
Wire.write((uint8_t)value);
#else
Wire.send(reg);
Wire.send(value);
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Reads an 8 bit value over I2C
*/
/**************************************************************************/
static void read8(byte reg, uint8_t *value)
{
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)1);
#if ARDUINO >= 100
*value = Wire.read();
#else
*value = Wire.receive();
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Reads a 16 bit value over I2C
*/
/**************************************************************************/
static void read16(byte reg, uint16_t *value)
{
Wire.beginTransmission((uint8_t)BMP085_ADDRESS);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom((uint8_t)BMP085_ADDRESS, (byte)2);
#if ARDUINO >= 100
*value = (Wire.read() << 8) | Wire.read();
#else
*value = (Wire.receive() << 8) | Wire.receive();
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Reads a signed 16 bit value over I2C
*/
/**************************************************************************/
static void readS16(byte reg, int16_t *value)
{
uint16_t i;
read16(reg, &i);
*value = (int16_t)i;
}
/**************************************************************************/
/*!
@brief Reads the factory-set coefficients
*/
/**************************************************************************/
static void readCoefficients(void)
{
#if BMP085_USE_DATASHEET_VALS
_bmp085_coeffs.ac1 = 408;
_bmp085_coeffs.ac2 = -72;
_bmp085_coeffs.ac3 = -14383;
_bmp085_coeffs.ac4 = 32741;
_bmp085_coeffs.ac5 = 32757;
_bmp085_coeffs.ac6 = 23153;
_bmp085_coeffs.b1 = 6190;
_bmp085_coeffs.b2 = 4;
_bmp085_coeffs.mb = -32768;
_bmp085_coeffs.mc = -8711;
_bmp085_coeffs.md = 2868;
_bmp085Mode = 0;
#else
readS16(BMP085_REGISTER_CAL_AC1, &_bmp085_coeffs.ac1);
readS16(BMP085_REGISTER_CAL_AC2, &_bmp085_coeffs.ac2);
readS16(BMP085_REGISTER_CAL_AC3, &_bmp085_coeffs.ac3);
read16(BMP085_REGISTER_CAL_AC4, &_bmp085_coeffs.ac4);
read16(BMP085_REGISTER_CAL_AC5, &_bmp085_coeffs.ac5);
read16(BMP085_REGISTER_CAL_AC6, &_bmp085_coeffs.ac6);
readS16(BMP085_REGISTER_CAL_B1, &_bmp085_coeffs.b1);
readS16(BMP085_REGISTER_CAL_B2, &_bmp085_coeffs.b2);
readS16(BMP085_REGISTER_CAL_MB, &_bmp085_coeffs.mb);
readS16(BMP085_REGISTER_CAL_MC, &_bmp085_coeffs.mc);
readS16(BMP085_REGISTER_CAL_MD, &_bmp085_coeffs.md);
#endif
}
/**************************************************************************/
/*!
*/
/**************************************************************************/
static void readRawTemperature(int32_t *temperature)
{
#if BMP085_USE_DATASHEET_VALS
*temperature = 27898;
#else
uint16_t t;
writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READTEMPCMD);
delay(5);
read16(BMP085_REGISTER_TEMPDATA, &t);
*temperature = t;
#endif
}
/**************************************************************************/
/*!
*/
/**************************************************************************/
static void readRawPressure(int32_t *pressure)
{
#if BMP085_USE_DATASHEET_VALS
*pressure = 23843;
#else
uint8_t p8;
uint16_t p16;
int32_t p32;
writeCommand(BMP085_REGISTER_CONTROL, BMP085_REGISTER_READPRESSURECMD + (_bmp085Mode << 6));
switch(_bmp085Mode)
{
case BMP085_MODE_ULTRALOWPOWER:
delay(5);
break;
case BMP085_MODE_STANDARD:
delay(8);
break;
case BMP085_MODE_HIGHRES:
delay(14);
break;
case BMP085_MODE_ULTRAHIGHRES:
default:
delay(26);
break;
}
read16(BMP085_REGISTER_PRESSUREDATA, &p16);
p32 = (uint32_t)p16 << 8;
read8(BMP085_REGISTER_PRESSUREDATA+2, &p8);
p32 += p8;
p32 >>= (8 - _bmp085Mode);
*pressure = p32;
#endif
}
/**************************************************************************/
/*!
@brief Compute B5 coefficient used in temperature & pressure calcs.
*/
/**************************************************************************/
int32_t Adafruit_BMP085_Unified::computeB5(int32_t ut) {
int32_t X1 = (ut - (int32_t)_bmp085_coeffs.ac6) * ((int32_t)_bmp085_coeffs.ac5) >> 15;
int32_t X2 = ((int32_t)_bmp085_coeffs.mc << 11) / (X1+(int32_t)_bmp085_coeffs.md);
return X1 + X2;
}
/***************************************************************************
CONSTRUCTOR
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates a new Adafruit_BMP085_Unified class
*/
/**************************************************************************/
Adafruit_BMP085_Unified::Adafruit_BMP085_Unified(int32_t sensorID) {
_sensorID = sensorID;
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_BMP085_Unified::begin(bmp085_mode_t mode)
{
// Enable I2C
Wire.begin();
/* Mode boundary check */
if ((mode > BMP085_MODE_ULTRAHIGHRES) || (mode < 0))
{
mode = BMP085_MODE_ULTRAHIGHRES;
}
/* Make sure we have the right device */
uint8_t id;
read8(BMP085_REGISTER_CHIPID, &id);
if(id != 0x55)
{
return false;
}
/* Set the mode indicator */
_bmp085Mode = mode;
/* Coefficients need to be read once */
readCoefficients();
return true;
}
/**************************************************************************/
/*!
@brief Gets the compensated pressure level in kPa
*/
/**************************************************************************/
void Adafruit_BMP085_Unified::getPressure(float *pressure)
{
int32_t ut = 0, up = 0, compp = 0;
int32_t x1, x2, b5, b6, x3, b3, p;
uint32_t b4, b7;
/* Get the raw pressure and temperature values */
readRawTemperature(&ut);
readRawPressure(&up);
/* Temperature compensation */
b5 = computeB5(ut);
/* Pressure compensation */
b6 = b5 - 4000;
x1 = (_bmp085_coeffs.b2 * ((b6 * b6) >> 12)) >> 11;
x2 = (_bmp085_coeffs.ac2 * b6) >> 11;
x3 = x1 + x2;
b3 = (((((int32_t) _bmp085_coeffs.ac1) * 4 + x3) << _bmp085Mode) + 2) >> 2;
x1 = (_bmp085_coeffs.ac3 * b6) >> 13;
x2 = (_bmp085_coeffs.b1 * ((b6 * b6) >> 12)) >> 16;
x3 = ((x1 + x2) + 2) >> 2;
b4 = (_bmp085_coeffs.ac4 * (uint32_t) (x3 + 32768)) >> 15;
b7 = ((uint32_t) (up - b3) * (50000 >> _bmp085Mode));
if (b7 < 0x80000000)
{
p = (b7 << 1) / b4;
}
else
{
p = (b7 / b4) << 1;
}
x1 = (p >> 8) * (p >> 8);
x1 = (x1 * 3038) >> 16;
x2 = (-7357 * p) >> 16;
compp = p + ((x1 + x2 + 3791) >> 4);
/* Assign compensated pressure value */
*pressure = compp;
}
/**************************************************************************/
/*!
@brief Reads the temperatures in degrees Celsius
*/
/**************************************************************************/
void Adafruit_BMP085_Unified::getTemperature(float *temp)
{
int32_t UT, X1, X2, B5; // following ds convention
float t;
readRawTemperature(&UT);
#if BMP085_USE_DATASHEET_VALS
// use datasheet numbers!
UT = 27898;
_bmp085_coeffs.ac6 = 23153;
_bmp085_coeffs.ac5 = 32757;
_bmp085_coeffs.mc = -8711;
_bmp085_coeffs.md = 2868;
#endif
B5 = computeB5(UT);
t = (B5+8) >> 4;
t /= 10;
*temp = t;
}
/**************************************************************************/
/*!
Calculates the altitude (in meters) from the specified atmospheric
pressure (in hPa), and sea-level pressure (in hPa).
@param seaLevel Sea-level pressure in hPa
@param atmospheric Atmospheric pressure in hPa
*/
/**************************************************************************/
float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric)
{
// Equation taken from BMP180 datasheet (page 16):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
// Note that using the equation from wikipedia can give bad results
// at high altitude. See this thread for more information:
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064
return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
}
/**************************************************************************/
/*!
Calculates the altitude (in meters) from the specified atmospheric
pressure (in hPa), and sea-level pressure (in hPa). Note that this
function just calls the overload of pressureToAltitude which takes
seaLevel and atmospheric pressure--temperature is ignored. The original
implementation of this function was based on calculations from Wikipedia
which are not accurate at higher altitudes. To keep compatibility with
old code this function remains with the same interface, but it calls the
more accurate calculation.
@param seaLevel Sea-level pressure in hPa
@param atmospheric Atmospheric pressure in hPa
@param temp Temperature in degrees Celsius
*/
/**************************************************************************/
float Adafruit_BMP085_Unified::pressureToAltitude(float seaLevel, float atmospheric, float temp)
{
return pressureToAltitude(seaLevel, atmospheric);
}
/**************************************************************************/
/*!
Calculates the pressure at sea level (in hPa) from the specified altitude
(in meters), and atmospheric pressure (in hPa).
@param altitude Altitude in meters
@param atmospheric Atmospheric pressure in hPa
*/
/**************************************************************************/
float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric)
{
// Equation taken from BMP180 datasheet (page 17):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
// Note that using the equation from wikipedia can give bad results
// at high altitude. See this thread for more information:
// http://forums.adafruit.com/viewtopic.php?f=22&t=58064
return atmospheric / pow(1.0 - (altitude/44330.0), 5.255);
}
/**************************************************************************/
/*!
Calculates the pressure at sea level (in hPa) from the specified altitude
(in meters), and atmospheric pressure (in hPa). Note that this
function just calls the overload of seaLevelForAltitude which takes
altitude and atmospheric pressure--temperature is ignored. The original
implementation of this function was based on calculations from Wikipedia
which are not accurate at higher altitudes. To keep compatibility with
old code this function remains with the same interface, but it calls the
more accurate calculation.
@param altitude Altitude in meters
@param atmospheric Atmospheric pressure in hPa
@param temp Temperature in degrees Celsius
*/
/**************************************************************************/
float Adafruit_BMP085_Unified::seaLevelForAltitude(float altitude, float atmospheric, float temp)
{
return seaLevelForAltitude(altitude, atmospheric);
}
/**************************************************************************/
/*!
@brief Provides the sensor_t data for this sensor
*/
/**************************************************************************/
void Adafruit_BMP085_Unified::getSensor(sensor_t *sensor)
{
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy (sensor->name, "BMP085", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name)- 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_PRESSURE;
sensor->min_delay = 0;
sensor->max_value = 300.0F; // 300..1100 hPa
sensor->min_value = 1100.0F;
sensor->resolution = 0.01F; // Datasheet states 0.01 hPa resolution
}
/**************************************************************************/
/*!
@brief Reads the sensor and returns the data as a sensors_event_t
*/
/**************************************************************************/
bool Adafruit_BMP085_Unified::getEvent(sensors_event_t *event)
{
float pressure_kPa;
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_PRESSURE;
event->timestamp = 0;
getPressure(&pressure_kPa);
event->pressure = pressure_kPa / 100.0F;
return true;
}

122
Adafruit_BMP085_U.h Normal file
View file

@ -0,0 +1,122 @@
/***************************************************************************
This is a library for the BMP085 pressure sensor
Designed specifically to work with the Adafruit BMP085 or BMP180 Breakout
----> http://www.adafruit.com/products/391
----> http://www.adafruit.com/products/1603
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#ifndef __BMP085_H__
#define __BMP085_H__
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Adafruit_Sensor.h"
#ifdef __AVR_ATtiny85__
#include "TinyWireM.h"
#define Wire TinyWireM
#else
#include <Wire.h>
#endif
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define BMP085_ADDRESS (0x77)
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
enum
{
BMP085_REGISTER_CAL_AC1 = 0xAA, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC2 = 0xAC, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC3 = 0xAE, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC4 = 0xB0, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC5 = 0xB2, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_AC6 = 0xB4, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_B1 = 0xB6, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_B2 = 0xB8, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MB = 0xBA, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MC = 0xBC, // R Calibration data (16 bits)
BMP085_REGISTER_CAL_MD = 0xBE, // R Calibration data (16 bits)
BMP085_REGISTER_CHIPID = 0xD0,
BMP085_REGISTER_VERSION = 0xD1,
BMP085_REGISTER_SOFTRESET = 0xE0,
BMP085_REGISTER_CONTROL = 0xF4,
BMP085_REGISTER_TEMPDATA = 0xF6,
BMP085_REGISTER_PRESSUREDATA = 0xF6,
BMP085_REGISTER_READTEMPCMD = 0x2E,
BMP085_REGISTER_READPRESSURECMD = 0x34
};
/*=========================================================================*/
/*=========================================================================
MODE SETTINGS
-----------------------------------------------------------------------*/
typedef enum
{
BMP085_MODE_ULTRALOWPOWER = 0,
BMP085_MODE_STANDARD = 1,
BMP085_MODE_HIGHRES = 2,
BMP085_MODE_ULTRAHIGHRES = 3
} bmp085_mode_t;
/*=========================================================================*/
/*=========================================================================
CALIBRATION DATA
-----------------------------------------------------------------------*/
typedef struct
{
int16_t ac1;
int16_t ac2;
int16_t ac3;
uint16_t ac4;
uint16_t ac5;
uint16_t ac6;
int16_t b1;
int16_t b2;
int16_t mb;
int16_t mc;
int16_t md;
} bmp085_calib_data;
/*=========================================================================*/
class Adafruit_BMP085_Unified : public Adafruit_Sensor
{
public:
Adafruit_BMP085_Unified(int32_t sensorID = -1);
bool begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES);
void getTemperature(float *temp);
void getPressure(float *pressure);
float pressureToAltitude(float seaLvel, float atmospheric);
float seaLevelForAltitude(float altitude, float atmospheric);
// Note that the next two functions are just for compatibility with old
// code that passed the temperature as a third parameter. A newer
// calculation is used which does not need temperature.
float pressureToAltitude(float seaLevel, float atmospheric, float temp);
float seaLevelForAltitude(float altitude, float atmospheric, float temp);
bool getEvent(sensors_event_t*);
void getSensor(sensor_t*);
private:
int32_t computeB5(int32_t ut);
int32_t _sensorID;
};
#endif

500
Adafruit_GPS.cpp Normal file
View file

@ -0,0 +1,500 @@
/***********************************
This is our GPS library
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
****************************************/
#ifdef __AVR__
// Only include software serial on AVR platforms (i.e. not on Due).
#include <SoftwareSerial.h>
#endif
#include "Adafruit_GPS.h"
// how long are max NMEA lines to parse?
#define MAXLINELENGTH 120
// we double buffer: read one line in and leave one for the main program
volatile char line1[MAXLINELENGTH];
volatile char line2[MAXLINELENGTH];
// our index into filling the current line
volatile uint8_t lineidx=0;
// pointers to the double buffers
volatile char *currentline;
volatile char *lastline;
volatile boolean recvdflag;
volatile boolean inStandbyMode;
boolean Adafruit_GPS::parse(char *nmea) {
// do checksum check
// first look if we even have one
if (nmea[strlen(nmea)-4] == '*') {
uint16_t sum = parseHex(nmea[strlen(nmea)-3]) * 16;
sum += parseHex(nmea[strlen(nmea)-2]);
// check checksum
for (uint8_t i=1; i < (strlen(nmea)-4); i++) {
sum ^= nmea[i];
}
if (sum != 0) {
// bad checksum :(
//return false;
}
}
int32_t degree;
long minutes;
char degreebuff[10];
// look for a few common sentences
if (strstr(nmea, "$GPGGA")) {
// found GGA
char *p = nmea;
// get time
p = strchr(p, ',')+1;
float timef = atof(p);
uint32_t time = timef;
hour = time / 10000;
minute = (time % 10000) / 100;
seconds = (time % 100);
milliseconds = fmod(timef, 1.0) * 1000;
// parse out latitude
p = strchr(p, ',')+1;
if (',' != *p)
{
strncpy(degreebuff, p, 2);
p += 2;
degreebuff[2] = '\0';
degree = atol(degreebuff) * 10000000;
strncpy(degreebuff, p, 2); // minutes
p += 3; // skip decimal point
strncpy(degreebuff + 2, p, 4);
degreebuff[6] = '\0';
minutes = 50 * atol(degreebuff) / 3;
latitude_fixed = degree + minutes;
latitude = degree / 100000 + minutes * 0.000006F;
latitudeDegrees = (latitude-100*int(latitude/100))/60.0;
latitudeDegrees += int(latitude/100);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
if (p[0] == 'S') latitudeDegrees *= -1.0;
if (p[0] == 'N') lat = 'N';
else if (p[0] == 'S') lat = 'S';
else if (p[0] == ',') lat = 0;
else return false;
}
// parse out longitude
p = strchr(p, ',')+1;
if (',' != *p)
{
strncpy(degreebuff, p, 3);
p += 3;
degreebuff[3] = '\0';
degree = atol(degreebuff) * 10000000;
strncpy(degreebuff, p, 2); // minutes
p += 3; // skip decimal point
strncpy(degreebuff + 2, p, 4);
degreebuff[6] = '\0';
minutes = 50 * atol(degreebuff) / 3;
longitude_fixed = degree + minutes;
longitude = degree / 100000 + minutes * 0.000006F;
longitudeDegrees = (longitude-100*int(longitude/100))/60.0;
longitudeDegrees += int(longitude/100);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
if (p[0] == 'W') longitudeDegrees *= -1.0;
if (p[0] == 'W') lon = 'W';
else if (p[0] == 'E') lon = 'E';
else if (p[0] == ',') lon = 0;
else return false;
}
p = strchr(p, ',')+1;
if (',' != *p)
{
fixquality = atoi(p);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
satellites = atoi(p);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
HDOP = atof(p);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
altitude = atof(p);
}
p = strchr(p, ',')+1;
p = strchr(p, ',')+1;
if (',' != *p)
{
geoidheight = atof(p);
}
return true;
}
if (strstr(nmea, "$GPRMC")) {
// found RMC
char *p = nmea;
// get time
p = strchr(p, ',')+1;
float timef = atof(p);
uint32_t time = timef;
hour = time / 10000;
minute = (time % 10000) / 100;
seconds = (time % 100);
milliseconds = fmod(timef, 1.0) * 1000;
p = strchr(p, ',')+1;
// Serial.println(p);
if (p[0] == 'A')
fix = true;
else if (p[0] == 'V')
fix = false;
else
return false;
// parse out latitude
p = strchr(p, ',')+1;
if (',' != *p)
{
strncpy(degreebuff, p, 2);
p += 2;
degreebuff[2] = '\0';
long degree = atol(degreebuff) * 10000000;
strncpy(degreebuff, p, 2); // minutes
p += 3; // skip decimal point
strncpy(degreebuff + 2, p, 4);
degreebuff[6] = '\0';
long minutes = 50 * atol(degreebuff) / 3;
latitude_fixed = degree + minutes;
latitude = degree / 100000 + minutes * 0.000006F;
latitudeDegrees = (latitude-100*int(latitude/100))/60.0;
latitudeDegrees += int(latitude/100);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
if (p[0] == 'S') latitudeDegrees *= -1.0;
if (p[0] == 'N') lat = 'N';
else if (p[0] == 'S') lat = 'S';
else if (p[0] == ',') lat = 0;
else return false;
}
// parse out longitude
p = strchr(p, ',')+1;
if (',' != *p)
{
strncpy(degreebuff, p, 3);
p += 3;
degreebuff[3] = '\0';
degree = atol(degreebuff) * 10000000;
strncpy(degreebuff, p, 2); // minutes
p += 3; // skip decimal point
strncpy(degreebuff + 2, p, 4);
degreebuff[6] = '\0';
minutes = 50 * atol(degreebuff) / 3;
longitude_fixed = degree + minutes;
longitude = degree / 100000 + minutes * 0.000006F;
longitudeDegrees = (longitude-100*int(longitude/100))/60.0;
longitudeDegrees += int(longitude/100);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
if (p[0] == 'W') longitudeDegrees *= -1.0;
if (p[0] == 'W') lon = 'W';
else if (p[0] == 'E') lon = 'E';
else if (p[0] == ',') lon = 0;
else return false;
}
// speed
p = strchr(p, ',')+1;
if (',' != *p)
{
speed = atof(p);
}
// angle
p = strchr(p, ',')+1;
if (',' != *p)
{
angle = atof(p);
}
p = strchr(p, ',')+1;
if (',' != *p)
{
uint32_t fulldate = atof(p);
day = fulldate / 10000;
month = (fulldate % 10000) / 100;
year = (fulldate % 100);
}
// we dont parse the remaining, yet!
return true;
}
return false;
}
char Adafruit_GPS::read(void) {
char c = 0;
if (paused) return c;
#ifdef __AVR__
if(gpsSwSerial) {
if(!gpsSwSerial->available()) return c;
c = gpsSwSerial->read();
} else
#endif
{
if(!gpsHwSerial->available()) return c;
c = gpsHwSerial->read();
}
//Serial.print(c);
// if (c == '$') { //please don't eat the dollar sign - rdl 9/15/14
// currentline[lineidx] = 0;
// lineidx = 0;
// }
if (c == '\n') {
currentline[lineidx] = 0;
if (currentline == line1) {
currentline = line2;
lastline = line1;
} else {
currentline = line1;
lastline = line2;
}
//Serial.println("----");
//Serial.println((char *)lastline);
//Serial.println("----");
lineidx = 0;
recvdflag = true;
}
currentline[lineidx++] = c;
if (lineidx >= MAXLINELENGTH)
lineidx = MAXLINELENGTH-1;
return c;
}
#ifdef __AVR__
// Constructor when using SoftwareSerial or NewSoftSerial
#if ARDUINO >= 100
Adafruit_GPS::Adafruit_GPS(SoftwareSerial *ser)
#else
Adafruit_GPS::Adafruit_GPS(NewSoftSerial *ser)
#endif
{
common_init(); // Set everything to common state, then...
gpsSwSerial = ser; // ...override gpsSwSerial with value passed.
}
#endif
// Constructor when using HardwareSerial
Adafruit_GPS::Adafruit_GPS(HardwareSerial *ser) {
common_init(); // Set everything to common state, then...
gpsHwSerial = ser; // ...override gpsHwSerial with value passed.
}
// Initialization code used by all constructor types
void Adafruit_GPS::common_init(void) {
#ifdef __AVR__
gpsSwSerial = NULL; // Set both to NULL, then override correct
#endif
gpsHwSerial = NULL; // port pointer in corresponding constructor
recvdflag = false;
paused = false;
lineidx = 0;
currentline = line1;
lastline = line2;
hour = minute = seconds = year = month = day =
fixquality = satellites = 0; // uint8_t
lat = lon = mag = 0; // char
fix = false; // boolean
milliseconds = 0; // uint16_t
latitude = longitude = geoidheight = altitude =
speed = angle = magvariation = HDOP = 0.0; // float
}
void Adafruit_GPS::begin(uint16_t baud)
{
#ifdef __AVR__
if(gpsSwSerial)
gpsSwSerial->begin(baud);
else
gpsHwSerial->begin(baud);
#endif
delay(10);
}
void Adafruit_GPS::sendCommand(const char *str) {
#ifdef __AVR__
if(gpsSwSerial)
gpsSwSerial->println(str);
else
#endif
gpsHwSerial->println(str);
}
boolean Adafruit_GPS::newNMEAreceived(void) {
return recvdflag;
}
void Adafruit_GPS::pause(boolean p) {
paused = p;
}
char *Adafruit_GPS::lastNMEA(void) {
recvdflag = false;
return (char *)lastline;
}
// read a Hex value and return the decimal equivalent
uint8_t Adafruit_GPS::parseHex(char c) {
if (c < '0')
return 0;
if (c <= '9')
return c - '0';
if (c < 'A')
return 0;
if (c <= 'F')
return (c - 'A')+10;
// if (c > 'F')
return 0;
}
boolean Adafruit_GPS::waitForSentence(const char *wait4me, uint8_t max) {
char str[20];
uint8_t i=0;
while (i < max) {
if (newNMEAreceived()) {
char *nmea = lastNMEA();
strncpy(str, nmea, 20);
str[19] = 0;
i++;
if (strstr(str, wait4me))
return true;
}
}
return false;
}
boolean Adafruit_GPS::LOCUS_StartLogger(void) {
sendCommand(PMTK_LOCUS_STARTLOG);
recvdflag = false;
return waitForSentence(PMTK_LOCUS_STARTSTOPACK);
}
boolean Adafruit_GPS::LOCUS_StopLogger(void) {
sendCommand(PMTK_LOCUS_STOPLOG);
recvdflag = false;
return waitForSentence(PMTK_LOCUS_STARTSTOPACK);
}
boolean Adafruit_GPS::LOCUS_ReadStatus(void) {
sendCommand(PMTK_LOCUS_QUERY_STATUS);
if (! waitForSentence("$PMTKLOG"))
return false;
char *response = lastNMEA();
uint16_t parsed[10];
uint8_t i;
for (i=0; i<10; i++) parsed[i] = -1;
response = strchr(response, ',');
for (i=0; i<10; i++) {
if (!response || (response[0] == 0) || (response[0] == '*'))
break;
response++;
parsed[i]=0;
while ((response[0] != ',') &&
(response[0] != '*') && (response[0] != 0)) {
parsed[i] *= 10;
char c = response[0];
if (isDigit(c))
parsed[i] += c - '0';
else
parsed[i] = c;
response++;
}
}
LOCUS_serial = parsed[0];
LOCUS_type = parsed[1];
if (isAlpha(parsed[2])) {
parsed[2] = parsed[2] - 'a' + 10;
}
LOCUS_mode = parsed[2];
LOCUS_config = parsed[3];
LOCUS_interval = parsed[4];
LOCUS_distance = parsed[5];
LOCUS_speed = parsed[6];
LOCUS_status = !parsed[7];
LOCUS_records = parsed[8];
LOCUS_percent = parsed[9];
return true;
}
// Standby Mode Switches
boolean Adafruit_GPS::standby(void) {
if (inStandbyMode) {
return false; // Returns false if already in standby mode, so that you do not wake it up by sending commands to GPS
}
else {
inStandbyMode = true;
sendCommand(PMTK_STANDBY);
//return waitForSentence(PMTK_STANDBY_SUCCESS); // don't seem to be fast enough to catch the message, or something else just is not working
return true;
}
}
boolean Adafruit_GPS::wakeup(void) {
if (inStandbyMode) {
inStandbyMode = false;
sendCommand(""); // send byte to wake it up
return waitForSentence(PMTK_AWAKE);
}
else {
return false; // Returns false if not in standby mode, nothing to wakeup
}
}

168
Adafruit_GPS.h Normal file
View file

@ -0,0 +1,168 @@
/***********************************
This is the Adafruit GPS library - the ultimate GPS library
for the ultimate GPS module!
Tested and works great with the Adafruit Ultimate GPS module
using MTK33x9 chipset
------> http://www.adafruit.com/products/746
Pick one up today at the Adafruit electronics shop
and help support open source hardware & software! -ada
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
****************************************/
// Fllybob added lines 34,35 and 40,41 to add 100mHz logging capability
#ifndef _ADAFRUIT_GPS_H
#define _ADAFRUIT_GPS_H
#ifdef __AVR__
#if ARDUINO >= 100
#include <SoftwareSerial.h>
#else
#include <NewSoftSerial.h>
#endif
#endif
// different commands to set the update rate from once a second (1 Hz) to 10 times a second (10Hz)
// Note that these only control the rate at which the position is echoed, to actually speed up the
// position fix you must also send one of the position fix rate commands below too.
#define PMTK_SET_NMEA_UPDATE_100_MILLIHERTZ "$PMTK220,10000*2F" // Once every 10 seconds, 100 millihertz.
#define PMTK_SET_NMEA_UPDATE_200_MILLIHERTZ "$PMTK220,5000*1B" // Once every 5 seconds, 200 millihertz.
#define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F"
#define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C"
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F"
// Position fix update rate commands.
#define PMTK_API_SET_FIX_CTL_100_MILLIHERTZ "$PMTK300,10000,0,0,0,0*2C" // Once every 10 seconds, 100 millihertz.
#define PMTK_API_SET_FIX_CTL_200_MILLIHERTZ "$PMTK300,5000,0,0,0,0*18" // Once every 5 seconds, 200 millihertz.
#define PMTK_API_SET_FIX_CTL_1HZ "$PMTK300,1000,0,0,0,0*1C"
#define PMTK_API_SET_FIX_CTL_5HZ "$PMTK300,200,0,0,0,0*2F"
// Can't fix position faster than 5 times a second!
#define PMTK_SET_BAUD_57600 "$PMTK251,57600*2C"
#define PMTK_SET_BAUD_9600 "$PMTK251,9600*17"
// turn on only the second sentence (GPRMC)
#define PMTK_SET_NMEA_OUTPUT_RMCONLY "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29"
// turn on GPRMC and GGA
#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn on ALL THE DATA
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// turn off output
#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28"
// to generate your own sentences, check out the MTK command datasheet and use a checksum calculator
// such as the awesome http://www.hhhh.org/wiml/proj/nmeaxor.html
#define PMTK_LOCUS_STARTLOG "$PMTK185,0*22"
#define PMTK_LOCUS_STOPLOG "$PMTK185,1*23"
#define PMTK_LOCUS_STARTSTOPACK "$PMTK001,185,3*3C"
#define PMTK_LOCUS_QUERY_STATUS "$PMTK183*38"
#define PMTK_LOCUS_ERASE_FLASH "$PMTK184,1*22"
#define LOCUS_OVERLAP 0
#define LOCUS_FULLSTOP 1
#define PMTK_ENABLE_SBAS "$PMTK313,1*2E"
#define PMTK_ENABLE_WAAS "$PMTK301,2*2E"
// standby command & boot successful message
#define PMTK_STANDBY "$PMTK161,0*28"
#define PMTK_STANDBY_SUCCESS "$PMTK001,161,3*36" // Not needed currently
#define PMTK_AWAKE "$PMTK010,002*2D"
// ask for the release and version
#define PMTK_Q_RELEASE "$PMTK605*31"
// request for updates on antenna status
#define PGCMD_ANTENNA "$PGCMD,33,1*6C"
#define PGCMD_NOANTENNA "$PGCMD,33,0*6D"
// how long to wait when we're looking for a response
#define MAXWAITSENTENCE 5
#if ARDUINO >= 100
#include "Arduino.h"
#if defined (__AVR__) && !defined(__AVR_ATmega32U4__)
#include "SoftwareSerial.h"
#endif
#else
#include "WProgram.h"
#include "NewSoftSerial.h"
#endif
class Adafruit_GPS {
public:
void begin(uint16_t baud);
#ifdef __AVR__
#if ARDUINO >= 100
Adafruit_GPS(SoftwareSerial *ser); // Constructor when using SoftwareSerial
#else
Adafruit_GPS(NewSoftSerial *ser); // Constructor when using NewSoftSerial
#endif
#endif
Adafruit_GPS(HardwareSerial *ser); // Constructor when using HardwareSerial
char *lastNMEA(void);
boolean newNMEAreceived();
void common_init(void);
void sendCommand(const char *);
void pause(boolean b);
boolean parseNMEA(char *response);
uint8_t parseHex(char c);
char read(void);
boolean parse(char *);
void interruptReads(boolean r);
boolean wakeup(void);
boolean standby(void);
uint8_t hour, minute, seconds, year, month, day;
uint16_t milliseconds;
// Floating point latitude and longitude value in degrees.
float latitude, longitude;
// Fixed point latitude and longitude value with degrees stored in units of 1/100000 degrees,
// and minutes stored in units of 1/100000 degrees. See pull #13 for more details:
// https://github.com/adafruit/Adafruit-GPS-Library/pull/13
int32_t latitude_fixed, longitude_fixed;
float latitudeDegrees, longitudeDegrees;
float geoidheight, altitude;
float speed, angle, magvariation, HDOP;
char lat, lon, mag;
boolean fix;
uint8_t fixquality, satellites;
boolean waitForSentence(const char *wait, uint8_t max = MAXWAITSENTENCE);
boolean LOCUS_StartLogger(void);
boolean LOCUS_StopLogger(void);
boolean LOCUS_ReadStatus(void);
uint16_t LOCUS_serial, LOCUS_records;
uint8_t LOCUS_type, LOCUS_mode, LOCUS_config, LOCUS_interval, LOCUS_distance, LOCUS_speed, LOCUS_status, LOCUS_percent;
private:
boolean paused;
uint8_t parseResponse(char *response);
#ifdef __AVR__
#if ARDUINO >= 100
SoftwareSerial *gpsSwSerial;
#else
NewSoftSerial *gpsSwSerial;
#endif
#endif
HardwareSerial *gpsHwSerial;
};
#endif

98
Adafruit_HTU21DF.cpp Normal file
View file

@ -0,0 +1,98 @@
/***************************************************
This is a library for the HTU21DF Humidity & Temp Sensor
Designed specifically to work with the HTU21DF sensor from Adafruit
----> https://www.adafruit.com/products/1899
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#include "Adafruit_HTU21DF.h"
//#include <util/delay.h>
Adafruit_HTU21DF::Adafruit_HTU21DF() {
}
boolean Adafruit_HTU21DF::begin(void) {
Wire1.begin();
reset();
Wire1.beginTransmission(HTU21DF_I2CADDR);
Wire1.write(HTU21DF_READREG);
Wire1.endTransmission();
Wire1.requestFrom(HTU21DF_I2CADDR, 1);
return (Wire1.read() == 0x2); // after reset should be 0x2
}
void Adafruit_HTU21DF::reset(void) {
Wire1.beginTransmission(HTU21DF_I2CADDR);
Wire1.write(HTU21DF_RESET);
Wire1.endTransmission();
delay(15);
}
float Adafruit_HTU21DF::readTemperature(void) {
// OK lets ready!
Wire1.beginTransmission(HTU21DF_I2CADDR);
Wire1.write(HTU21DF_READTEMP);
Wire1.endTransmission();
delay(50); // add delay between request and actual read!
Wire1.requestFrom(HTU21DF_I2CADDR, 3);
while (!Wire1.available()) {}
uint16_t t = Wire1.read();
t <<= 8;
t |= Wire1.read();
uint8_t crc = Wire1.read();
float temp = t;
temp *= 175.72;
temp /= 65536;
temp -= 46.85;
return temp;
}
float Adafruit_HTU21DF::readHumidity(void) {
// OK lets ready!
Wire1.beginTransmission(HTU21DF_I2CADDR);
Wire1.write(HTU21DF_READHUM);
Wire1.endTransmission();
delay(50); // add delay between request and actual read!
Wire1.requestFrom(HTU21DF_I2CADDR, 3);
while (!Wire1.available()) {}
uint16_t h = Wire1.read();
h <<= 8;
h |= Wire1.read();
uint8_t crc = Wire1.read();
float hum = h;
hum *= 125;
hum /= 65536;
hum -= 6;
return hum;
}
/*********************************************************************/

45
Adafruit_HTU21DF.h Normal file
View file

@ -0,0 +1,45 @@
/***************************************************
This is a library for the HTU21D-F Humidity & Temp Sensor
Designed specifically to work with the HTU21D-F sensor from Adafruit
----> https://www.adafruit.com/products/1899
These displays use I2C to communicate, 2 pins are required to
interface
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Limor Fried/Ladyada for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Wire.h"
extern TwoWire Wire1;
#define HTU21DF_I2CADDR 0x40
#define HTU21DF_READTEMP 0xE3
#define HTU21DF_READHUM 0xE5
#define HTU21DF_WRITEREG 0xE6
#define HTU21DF_READREG 0xE7
#define HTU21DF_RESET 0xFE
class Adafruit_HTU21DF {
public:
Adafruit_HTU21DF();
boolean begin(void);
float readTemperature(void);
float readHumidity(void);
void reset(void);
private:
boolean readData(void);
float humidity, temp;
};

364
Adafruit_L3GD20_U.cpp Normal file
View file

@ -0,0 +1,364 @@
/***************************************************
This is a library for the L3GD20 GYROSCOPE
Designed specifically to work with the Adafruit L3GD20 Breakout
----> https://www.adafruit.com/products/1032
These sensors use I2C or SPI to communicate, 2 pins (I2C)
or 4 pins (SPI) are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Kevin "KTOWN" Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Wire.h>
#include <limits.h>
#include "Adafruit_L3GD20_U.h"
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
void Adafruit_L3GD20_Unified::write8(byte reg, byte value)
{
Wire.beginTransmission(L3GD20_ADDRESS);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
Wire.write((uint8_t)value);
#else
Wire.send(reg);
Wire.send(value);
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
byte Adafruit_L3GD20_Unified::read8(byte reg)
{
byte value;
Wire.beginTransmission((byte)L3GD20_ADDRESS);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom((byte)L3GD20_ADDRESS, (byte)1);
while (!Wire.available()); // Wait for data to arrive.
#if ARDUINO >= 100
value = Wire.read();
#else
value = Wire.receive();
#endif
Wire.endTransmission();
return value;
}
/***************************************************************************
CONSTRUCTOR
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates a new Adafruit_L3GD20_Unified class
*/
/**************************************************************************/
Adafruit_L3GD20_Unified::Adafruit_L3GD20_Unified(int32_t sensorID) {
_sensorID = sensorID;
_autoRangeEnabled = false;
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_L3GD20_Unified::begin(gyroRange_t rng)
{
/* Enable I2C */
Wire.begin();
/* Set the range the an appropriate value */
_range = rng;
/* Make sure we have the correct chip ID since this checks
for correct address and that the IC is properly connected */
uint8_t id = read8(GYRO_REGISTER_WHO_AM_I);
//Serial.println(id, HEX);
if ((id != L3GD20_ID) && (id != L3GD20H_ID))
{
return false;
}
/* Set CTRL_REG1 (0x20)
====================================================================
BIT Symbol Description Default
--- ------ --------------------------------------------- -------
7-6 DR1/0 Output data rate 00
5-4 BW1/0 Bandwidth selection 00
3 PD 0 = Power-down mode, 1 = normal/sleep mode 0
2 ZEN Z-axis enable (0 = disabled, 1 = enabled) 1
1 YEN Y-axis enable (0 = disabled, 1 = enabled) 1
0 XEN X-axis enable (0 = disabled, 1 = enabled) 1 */
/* Reset then switch to normal mode and enable all three channels */
write8(GYRO_REGISTER_CTRL_REG1, 0x00);
write8(GYRO_REGISTER_CTRL_REG1, 0x0F);
/* ------------------------------------------------------------------ */
/* Set CTRL_REG2 (0x21)
====================================================================
BIT Symbol Description Default
--- ------ --------------------------------------------- -------
5-4 HPM1/0 High-pass filter mode selection 00
3-0 HPCF3..0 High-pass filter cutoff frequency selection 0000 */
/* Nothing to do ... keep default values */
/* ------------------------------------------------------------------ */
/* Set CTRL_REG3 (0x22)
====================================================================
BIT Symbol Description Default
--- ------ --------------------------------------------- -------
7 I1_Int1 Interrupt enable on INT1 (0=disable,1=enable) 0
6 I1_Boot Boot status on INT1 (0=disable,1=enable) 0
5 H-Lactive Interrupt active config on INT1 (0=high,1=low) 0
4 PP_OD Push-Pull/Open-Drain (0=PP, 1=OD) 0
3 I2_DRDY Data ready on DRDY/INT2 (0=disable,1=enable) 0
2 I2_WTM FIFO wtrmrk int on DRDY/INT2 (0=dsbl,1=enbl) 0
1 I2_ORun FIFO overrun int on DRDY/INT2 (0=dsbl,1=enbl) 0
0 I2_Empty FIFI empty int on DRDY/INT2 (0=dsbl,1=enbl) 0 */
/* Nothing to do ... keep default values */
/* ------------------------------------------------------------------ */
/* Set CTRL_REG4 (0x23)
====================================================================
BIT Symbol Description Default
--- ------ --------------------------------------------- -------
7 BDU Block Data Update (0=continuous, 1=LSB/MSB) 0
6 BLE Big/Little-Endian (0=Data LSB, 1=Data MSB) 0
5-4 FS1/0 Full scale selection 00
00 = 250 dps
01 = 500 dps
10 = 2000 dps
11 = 2000 dps
0 SIM SPI Mode (0=4-wire, 1=3-wire) 0 */
/* Adjust resolution if requested */
switch(_range)
{
case GYRO_RANGE_250DPS:
write8(GYRO_REGISTER_CTRL_REG4, 0x00);
break;
case GYRO_RANGE_500DPS:
write8(GYRO_REGISTER_CTRL_REG4, 0x10);
break;
case GYRO_RANGE_2000DPS:
write8(GYRO_REGISTER_CTRL_REG4, 0x20);
break;
}
/* ------------------------------------------------------------------ */
/* Set CTRL_REG5 (0x24)
====================================================================
BIT Symbol Description Default
--- ------ --------------------------------------------- -------
7 BOOT Reboot memory content (0=normal, 1=reboot) 0
6 FIFO_EN FIFO enable (0=FIFO disable, 1=enable) 0
4 HPen High-pass filter enable (0=disable,1=enable) 0
3-2 INT1_SEL INT1 Selection config 00
1-0 OUT_SEL Out selection config 00 */
/* Nothing to do ... keep default values */
/* ------------------------------------------------------------------ */
return true;
}
/**************************************************************************/
/*!
@brief Enables or disables auto-ranging
*/
/**************************************************************************/
void Adafruit_L3GD20_Unified::enableAutoRange(bool enabled)
{
_autoRangeEnabled = enabled;
}
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
*/
/**************************************************************************/
bool Adafruit_L3GD20_Unified::getEvent(sensors_event_t* event)
{
bool readingValid = false;
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_GYROSCOPE;
while(!readingValid)
{
event->timestamp = millis();
/* Read 6 bytes from the sensor */
Wire.beginTransmission((byte)L3GD20_ADDRESS);
#if ARDUINO >= 100
Wire.write(GYRO_REGISTER_OUT_X_L | 0x80);
#else
Wire.send(GYRO_REGISTER_OUT_X_L | 0x80);
#endif
Wire.endTransmission();
Wire.requestFrom((byte)L3GD20_ADDRESS, (byte)6);
/* Wait around until enough data is available */
while (Wire.available() < 6);
#if ARDUINO >= 100
uint8_t xlo = Wire.read();
uint8_t xhi = Wire.read();
uint8_t ylo = Wire.read();
uint8_t yhi = Wire.read();
uint8_t zlo = Wire.read();
uint8_t zhi = Wire.read();
#else
uint8_t xlo = Wire.receive();
uint8_t xhi = Wire.receive();
uint8_t ylo = Wire.receive();
uint8_t yhi = Wire.receive();
uint8_t zlo = Wire.receive();
uint8_t zhi = Wire.receive();
#endif
/* Shift values to create properly formed integer (low byte first) */
event->gyro.x = (int16_t)(xlo | (xhi << 8));
event->gyro.y = (int16_t)(ylo | (yhi << 8));
event->gyro.z = (int16_t)(zlo | (zhi << 8));
/* Make sure the sensor isn't saturating if auto-ranging is enabled */
if (!_autoRangeEnabled)
{
readingValid = true;
}
else
{
/* Check if the sensor is saturating or not */
if ( (event->gyro.x >= 32760) | (event->gyro.x <= -32760) |
(event->gyro.y >= 32760) | (event->gyro.y <= -32760) |
(event->gyro.z >= 32760) | (event->gyro.z <= -32760) )
{
/* Saturating .... increase the range if we can */
switch(_range)
{
case GYRO_RANGE_500DPS:
/* Push the range up to 2000dps */
_range = GYRO_RANGE_2000DPS;
write8(GYRO_REGISTER_CTRL_REG1, 0x00);
write8(GYRO_REGISTER_CTRL_REG1, 0x0F);
write8(GYRO_REGISTER_CTRL_REG4, 0x20);
write8(GYRO_REGISTER_CTRL_REG5, 0x80);
readingValid = false;
// Serial.println("Changing range to 2000DPS");
break;
case GYRO_RANGE_250DPS:
/* Push the range up to 500dps */
_range = GYRO_RANGE_500DPS;
write8(GYRO_REGISTER_CTRL_REG1, 0x00);
write8(GYRO_REGISTER_CTRL_REG1, 0x0F);
write8(GYRO_REGISTER_CTRL_REG4, 0x10);
write8(GYRO_REGISTER_CTRL_REG5, 0x80);
readingValid = false;
// Serial.println("Changing range to 500DPS");
break;
default:
readingValid = true;
break;
}
}
else
{
/* All values are withing range */
readingValid = true;
}
}
}
/* Compensate values depending on the resolution */
switch(_range)
{
case GYRO_RANGE_250DPS:
event->gyro.x *= GYRO_SENSITIVITY_250DPS;
event->gyro.y *= GYRO_SENSITIVITY_250DPS;
event->gyro.z *= GYRO_SENSITIVITY_250DPS;
break;
case GYRO_RANGE_500DPS:
event->gyro.x *= GYRO_SENSITIVITY_500DPS;
event->gyro.y *= GYRO_SENSITIVITY_500DPS;
event->gyro.z *= GYRO_SENSITIVITY_500DPS;
break;
case GYRO_RANGE_2000DPS:
event->gyro.x *= GYRO_SENSITIVITY_2000DPS;
event->gyro.y *= GYRO_SENSITIVITY_2000DPS;
event->gyro.z *= GYRO_SENSITIVITY_2000DPS;
break;
}
/* Convert values to rad/s */
event->gyro.x *= SENSORS_DPS_TO_RADS;
event->gyro.y *= SENSORS_DPS_TO_RADS;
event->gyro.z *= SENSORS_DPS_TO_RADS;
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
*/
/**************************************************************************/
void Adafruit_L3GD20_Unified::getSensor(sensor_t* sensor)
{
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy (sensor->name, "L3GD20", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name)- 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_GYROSCOPE;
sensor->min_delay = 0;
sensor->max_value = (float)this->_range * SENSORS_DPS_TO_RADS;
sensor->min_value = (this->_range * -1.0) * SENSORS_DPS_TO_RADS;
sensor->resolution = 0.0F; // TBD
}

104
Adafruit_L3GD20_U.h Normal file
View file

@ -0,0 +1,104 @@
/***************************************************
This is a library for the L3GD20 GYROSCOPE
Designed specifically to work with the Adafruit L3GD20 Breakout
----> https://www.adafruit.com/products/1032
These sensors use I2C or SPI to communicate, 2 pins (I2C)
or 4 pins (SPI) are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit and open-source hardware by purchasing
products from Adafruit!
Written by Kevin "KTOWN" Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
****************************************************/
#ifndef __L3GD20_H__
#define __L3GD20_H__
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Adafruit_Sensor.h"
#include <Wire.h>
/*=========================================================================
I2C ADDRESS/BITS AND SETTINGS
-----------------------------------------------------------------------*/
#define L3GD20_ADDRESS (0x6B) // 1101011
#define L3GD20_POLL_TIMEOUT (100) // Maximum number of read attempts
#define L3GD20_ID 0xD4
#define L3GD20H_ID 0xD7
#define GYRO_SENSITIVITY_250DPS (0.00875F) // Roughly 22/256 for fixed point match
#define GYRO_SENSITIVITY_500DPS (0.0175F) // Roughly 45/256
#define GYRO_SENSITIVITY_2000DPS (0.070F) // Roughly 18/256
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
typedef enum
{ // DEFAULT TYPE
GYRO_REGISTER_WHO_AM_I = 0x0F, // 11010100 r
GYRO_REGISTER_CTRL_REG1 = 0x20, // 00000111 rw
GYRO_REGISTER_CTRL_REG2 = 0x21, // 00000000 rw
GYRO_REGISTER_CTRL_REG3 = 0x22, // 00000000 rw
GYRO_REGISTER_CTRL_REG4 = 0x23, // 00000000 rw
GYRO_REGISTER_CTRL_REG5 = 0x24, // 00000000 rw
GYRO_REGISTER_REFERENCE = 0x25, // 00000000 rw
GYRO_REGISTER_OUT_TEMP = 0x26, // r
GYRO_REGISTER_STATUS_REG = 0x27, // r
GYRO_REGISTER_OUT_X_L = 0x28, // r
GYRO_REGISTER_OUT_X_H = 0x29, // r
GYRO_REGISTER_OUT_Y_L = 0x2A, // r
GYRO_REGISTER_OUT_Y_H = 0x2B, // r
GYRO_REGISTER_OUT_Z_L = 0x2C, // r
GYRO_REGISTER_OUT_Z_H = 0x2D, // r
GYRO_REGISTER_FIFO_CTRL_REG = 0x2E, // 00000000 rw
GYRO_REGISTER_FIFO_SRC_REG = 0x2F, // r
GYRO_REGISTER_INT1_CFG = 0x30, // 00000000 rw
GYRO_REGISTER_INT1_SRC = 0x31, // r
GYRO_REGISTER_TSH_XH = 0x32, // 00000000 rw
GYRO_REGISTER_TSH_XL = 0x33, // 00000000 rw
GYRO_REGISTER_TSH_YH = 0x34, // 00000000 rw
GYRO_REGISTER_TSH_YL = 0x35, // 00000000 rw
GYRO_REGISTER_TSH_ZH = 0x36, // 00000000 rw
GYRO_REGISTER_TSH_ZL = 0x37, // 00000000 rw
GYRO_REGISTER_INT1_DURATION = 0x38 // 00000000 rw
} gyroRegisters_t;
/*=========================================================================*/
/*=========================================================================
OPTIONAL SPEED SETTINGS
-----------------------------------------------------------------------*/
typedef enum
{
GYRO_RANGE_250DPS = 250,
GYRO_RANGE_500DPS = 500,
GYRO_RANGE_2000DPS = 2000
} gyroRange_t;
/*=========================================================================*/
class Adafruit_L3GD20_Unified : public Adafruit_Sensor
{
public:
Adafruit_L3GD20_Unified(int32_t sensorID = -1);
bool begin ( gyroRange_t rng = GYRO_RANGE_250DPS );
void enableAutoRange ( bool enabled );
bool getEvent ( sensors_event_t* );
void getSensor ( sensor_t* );
private:
void write8 ( byte reg, byte value );
byte read8 ( byte reg );
gyroRange_t _range;
int32_t _sensorID;
bool _autoRangeEnabled;
};
#endif

569
Adafruit_LSM303_U.cpp Normal file
View file

@ -0,0 +1,569 @@
/***************************************************************************
This is a library for the LSM303 Accelerometer and magnentometer/compass
Designed specifically to work with the Adafruit LSM303DLHC Breakout
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#if ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#ifdef __AVR_ATtiny85__
#include "TinyWireM.h"
#define Wire TinyWireM
#else
#include <Wire.h>
#endif
#include <limits.h>
#include "Adafruit_LSM303_U.h"
/* enabling this #define will enable the debug print blocks
#define LSM303_DEBUG
*/
static float _lsm303Accel_MG_LSB = 0.001F; // 1, 2, 4 or 12 mg per lsb
static float _lsm303Mag_Gauss_LSB_XY = 1100.0F; // Varies with gain
static float _lsm303Mag_Gauss_LSB_Z = 980.0F; // Varies with gain
/***************************************************************************
ACCELEROMETER
***************************************************************************/
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
void Adafruit_LSM303_Accel_Unified::write8(byte address, byte reg, byte value)
{
Wire.beginTransmission(address);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
Wire.write((uint8_t)value);
#else
Wire.send(reg);
Wire.send(value);
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
byte Adafruit_LSM303_Accel_Unified::read8(byte address, byte reg)
{
byte value;
Wire.beginTransmission(address);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom(address, (byte)1);
#if ARDUINO >= 100
value = Wire.read();
#else
value = Wire.receive();
#endif
Wire.endTransmission();
return value;
}
/**************************************************************************/
/*!
@brief Reads the raw data from the sensor
*/
/**************************************************************************/
void Adafruit_LSM303_Accel_Unified::read()
{
// Read the accelerometer
Wire.beginTransmission((byte)LSM303_ADDRESS_ACCEL);
#if ARDUINO >= 100
Wire.write(LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80);
#else
Wire.send(LSM303_REGISTER_ACCEL_OUT_X_L_A | 0x80);
#endif
Wire.endTransmission();
Wire.requestFrom((byte)LSM303_ADDRESS_ACCEL, (byte)6);
// Wait around until enough data is available
while (Wire.available() < 6);
#if ARDUINO >= 100
uint8_t xlo = Wire.read();
uint8_t xhi = Wire.read();
uint8_t ylo = Wire.read();
uint8_t yhi = Wire.read();
uint8_t zlo = Wire.read();
uint8_t zhi = Wire.read();
#else
uint8_t xlo = Wire.receive();
uint8_t xhi = Wire.receive();
uint8_t ylo = Wire.receive();
uint8_t yhi = Wire.receive();
uint8_t zlo = Wire.receive();
uint8_t zhi = Wire.receive();
#endif
// Shift values to create properly formed integer (low byte first)
_accelData.x = (int16_t)(xlo | (xhi << 8)) >> 4;
_accelData.y = (int16_t)(ylo | (yhi << 8)) >> 4;
_accelData.z = (int16_t)(zlo | (zhi << 8)) >> 4;
}
/***************************************************************************
CONSTRUCTOR
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates a new Adafruit_LSM303 class
*/
/**************************************************************************/
Adafruit_LSM303_Accel_Unified::Adafruit_LSM303_Accel_Unified(int32_t sensorID) {
_sensorID = sensorID;
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_LSM303_Accel_Unified::begin()
{
// Enable I2C
Wire.begin();
// Enable the accelerometer (100Hz)
write8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A, 0x57);
// LSM303DLHC has no WHOAMI register so read CTRL_REG1_A back to check
// if we are connected or not
uint8_t reg1_a = read8(LSM303_ADDRESS_ACCEL, LSM303_REGISTER_ACCEL_CTRL_REG1_A);
if (reg1_a != 0x57)
{
return false;
}
return true;
}
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
*/
/**************************************************************************/
bool Adafruit_LSM303_Accel_Unified::getEvent(sensors_event_t *event) {
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
/* Read new data */
read();
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_ACCELEROMETER;
event->timestamp = millis();
event->acceleration.x = _accelData.x * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD;
event->acceleration.y = _accelData.y * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD;
event->acceleration.z = _accelData.z * _lsm303Accel_MG_LSB * SENSORS_GRAVITY_STANDARD;
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
*/
/**************************************************************************/
void Adafruit_LSM303_Accel_Unified::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name)- 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_ACCELEROMETER;
sensor->min_delay = 0;
sensor->max_value = 0.0F; // TBD
sensor->min_value = 0.0F; // TBD
sensor->resolution = 0.0F; // TBD
}
/***************************************************************************
MAGNETOMETER
***************************************************************************/
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::write8(byte address, byte reg, byte value)
{
Wire.beginTransmission(address);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
Wire.write((uint8_t)value);
#else
Wire.send(reg);
Wire.send(value);
#endif
Wire.endTransmission();
}
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
byte Adafruit_LSM303_Mag_Unified::read8(byte address, byte reg)
{
byte value;
Wire.beginTransmission(address);
#if ARDUINO >= 100
Wire.write((uint8_t)reg);
#else
Wire.send(reg);
#endif
Wire.endTransmission();
Wire.requestFrom(address, (byte)1);
#if ARDUINO >= 100
value = Wire.read();
#else
value = Wire.receive();
#endif
Wire.endTransmission();
return value;
}
/**************************************************************************/
/*!
@brief Reads the raw data from the sensor
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::read()
{
// Read the magnetometer
Wire.beginTransmission((byte)LSM303_ADDRESS_MAG);
#if ARDUINO >= 100
Wire.write(LSM303_REGISTER_MAG_OUT_X_H_M);
#else
Wire.send(LSM303_REGISTER_MAG_OUT_X_H_M);
#endif
Wire.endTransmission();
Wire.requestFrom((byte)LSM303_ADDRESS_MAG, (byte)6);
// Wait around until enough data is available
while (Wire.available() < 6);
// Note high before low (different than accel)
#if ARDUINO >= 100
uint8_t xhi = Wire.read();
uint8_t xlo = Wire.read();
uint8_t zhi = Wire.read();
uint8_t zlo = Wire.read();
uint8_t yhi = Wire.read();
uint8_t ylo = Wire.read();
#else
uint8_t xhi = Wire.receive();
uint8_t xlo = Wire.receive();
uint8_t zhi = Wire.receive();
uint8_t zlo = Wire.receive();
uint8_t yhi = Wire.receive();
uint8_t ylo = Wire.receive();
#endif
// Shift values to create properly formed integer (low byte first)
_magData.x = (int16_t)(xlo | ((int16_t)xhi << 8));
_magData.y = (int16_t)(ylo | ((int16_t)yhi << 8));
_magData.z = (int16_t)(zlo | ((int16_t)zhi << 8));
// ToDo: Calculate orientation
// _magData.orientation = 0.0;
}
/***************************************************************************
CONSTRUCTOR
***************************************************************************/
/**************************************************************************/
/*!
@brief Instantiates a new Adafruit_LSM303 class
*/
/**************************************************************************/
Adafruit_LSM303_Mag_Unified::Adafruit_LSM303_Mag_Unified(int32_t sensorID) {
_sensorID = sensorID;
_autoRangeEnabled = false;
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_LSM303_Mag_Unified::begin()
{
// Enable I2C
Wire.begin();
// Enable the magnetometer
write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_MR_REG_M, 0x00);
#ifdef RUBBISH
// LSM303DLHC has no WHOAMI register so read CRA_REG_M to check
// the default value (0b00010000/0x10)
uint8_t reg1_a = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M);
if (reg1_a != 0x10)
{
return false;
}
// Set the gain to a known level
setMagGain(LSM303_MAGGAIN_1_3);
return true;
#else
uint8_t ira=0, irb=0, irc=0;
ira = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_IRA_REG_M);
irb = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_IRB_REG_M);
irc = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_IRC_REG_M);
if ((ira = 0x48) && (irb == 0x34) && (irc == 0x33)) {
setMagGain(LSM303_MAGGAIN_1_3);
return true;
}
return false;
#endif
}
/**************************************************************************/
/*!
@brief Enables or disables auto-ranging
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::enableAutoRange(bool enabled)
{
_autoRangeEnabled = enabled;
}
/**************************************************************************/
/*!
@brief Sets the magnetometer's gain
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::setMagGain(lsm303MagGain gain)
{
write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRB_REG_M, (byte)gain);
_magGain = gain;
switch(gain)
{
case LSM303_MAGGAIN_1_3:
_lsm303Mag_Gauss_LSB_XY = 1100;
_lsm303Mag_Gauss_LSB_Z = 980;
break;
case LSM303_MAGGAIN_1_9:
_lsm303Mag_Gauss_LSB_XY = 855;
_lsm303Mag_Gauss_LSB_Z = 760;
break;
case LSM303_MAGGAIN_2_5:
_lsm303Mag_Gauss_LSB_XY = 670;
_lsm303Mag_Gauss_LSB_Z = 600;
break;
case LSM303_MAGGAIN_4_0:
_lsm303Mag_Gauss_LSB_XY = 450;
_lsm303Mag_Gauss_LSB_Z = 400;
break;
case LSM303_MAGGAIN_4_7:
_lsm303Mag_Gauss_LSB_XY = 400;
_lsm303Mag_Gauss_LSB_Z = 355;
break;
case LSM303_MAGGAIN_5_6:
_lsm303Mag_Gauss_LSB_XY = 330;
_lsm303Mag_Gauss_LSB_Z = 295;
break;
case LSM303_MAGGAIN_8_1:
_lsm303Mag_Gauss_LSB_XY = 230;
_lsm303Mag_Gauss_LSB_Z = 205;
break;
}
}
/**************************************************************************/
/*!
@brief Sets the magnetometer's update rate
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::setMagRate(lsm303MagRate rate)
{
byte reg_m = ((byte)rate & 0x07) << 2;
write8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_CRA_REG_M, reg_m);
}
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
*/
/**************************************************************************/
bool Adafruit_LSM303_Mag_Unified::getEvent(sensors_event_t *event) {
bool readingValid = false;
/* Clear the event */
memset(event, 0, sizeof(sensors_event_t));
while(!readingValid)
{
uint8_t reg_mg = read8(LSM303_ADDRESS_MAG, LSM303_REGISTER_MAG_SR_REG_M);
if (!(reg_mg & 0x1)) {
return false;
}
/* Read new data */
read();
/* Make sure the sensor isn't saturating if auto-ranging is enabled */
if (!_autoRangeEnabled)
{
readingValid = true;
}
else
{
#ifdef LSM303_DEBUG
Serial.print(_magData.x); Serial.print(" ");
Serial.print(_magData.y); Serial.print(" ");
Serial.print(_magData.z); Serial.println(" ");
#endif
/* Check if the sensor is saturating or not */
if ( (_magData.x >= 2040) | (_magData.x <= -2040) |
(_magData.y >= 2040) | (_magData.y <= -2040) |
(_magData.z >= 2040) | (_magData.z <= -2040) )
{
/* Saturating .... increase the range if we can */
switch(_magGain)
{
case LSM303_MAGGAIN_5_6:
setMagGain(LSM303_MAGGAIN_8_1);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 8.1");
#endif
break;
case LSM303_MAGGAIN_4_7:
setMagGain(LSM303_MAGGAIN_5_6);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 5.6");
#endif
break;
case LSM303_MAGGAIN_4_0:
setMagGain(LSM303_MAGGAIN_4_7);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 4.7");
#endif
break;
case LSM303_MAGGAIN_2_5:
setMagGain(LSM303_MAGGAIN_4_0);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 4.0");
#endif
break;
case LSM303_MAGGAIN_1_9:
setMagGain(LSM303_MAGGAIN_2_5);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 2.5");
#endif
break;
case LSM303_MAGGAIN_1_3:
setMagGain(LSM303_MAGGAIN_1_9);
readingValid = false;
#ifdef LSM303_DEBUG
Serial.println("Changing range to +/- 1.9");
#endif
break;
default:
readingValid = true;
break;
}
}
else
{
/* All values are withing range */
readingValid = true;
}
}
}
event->version = sizeof(sensors_event_t);
event->sensor_id = _sensorID;
event->type = SENSOR_TYPE_MAGNETIC_FIELD;
event->timestamp = millis();
event->magnetic.x = _magData.x / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
event->magnetic.y = _magData.y / _lsm303Mag_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
event->magnetic.z = _magData.z / _lsm303Mag_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA;
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
*/
/**************************************************************************/
void Adafruit_LSM303_Mag_Unified::getSensor(sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy (sensor->name, "LSM303", sizeof(sensor->name) - 1);
sensor->name[sizeof(sensor->name)- 1] = 0;
sensor->version = 1;
sensor->sensor_id = _sensorID;
sensor->type = SENSOR_TYPE_MAGNETIC_FIELD;
sensor->min_delay = 0;
sensor->max_value = 0.0F; // TBD
sensor->min_value = 0.0F; // TBD
sensor->resolution = 0.0F; // TBD
}

200
Adafruit_LSM303_U.h Normal file
View file

@ -0,0 +1,200 @@
/***************************************************************************
This is a library for the LSM303 Accelerometer and magnentometer/compass
Designed specifically to work with the Adafruit LSM303DLHC Breakout
These displays use I2C to communicate, 2 pins are required to interface.
Adafruit invests time and resources providing this open source code,
please support Adafruit andopen-source hardware by purchasing products
from Adafruit!
Written by Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#ifndef __LSM303_H__
#define __LSM303_H__
#if (ARDUINO >= 100)
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include "Adafruit_Sensor.h"
#ifdef __AVR_ATtiny85__
#include "TinyWireM.h"
#define Wire TinyWireM
#else
#include <Wire.h>
#endif
/*=========================================================================
I2C ADDRESS/BITS
-----------------------------------------------------------------------*/
#define LSM303_ADDRESS_ACCEL (0x32 >> 1) // 0011001x
#define LSM303_ADDRESS_MAG (0x3C >> 1) // 0011110x
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
typedef enum
{ // DEFAULT TYPE
LSM303_REGISTER_ACCEL_CTRL_REG1_A = 0x20, // 00000111 rw
LSM303_REGISTER_ACCEL_CTRL_REG2_A = 0x21, // 00000000 rw
LSM303_REGISTER_ACCEL_CTRL_REG3_A = 0x22, // 00000000 rw
LSM303_REGISTER_ACCEL_CTRL_REG4_A = 0x23, // 00000000 rw
LSM303_REGISTER_ACCEL_CTRL_REG5_A = 0x24, // 00000000 rw
LSM303_REGISTER_ACCEL_CTRL_REG6_A = 0x25, // 00000000 rw
LSM303_REGISTER_ACCEL_REFERENCE_A = 0x26, // 00000000 r
LSM303_REGISTER_ACCEL_STATUS_REG_A = 0x27, // 00000000 r
LSM303_REGISTER_ACCEL_OUT_X_L_A = 0x28,
LSM303_REGISTER_ACCEL_OUT_X_H_A = 0x29,
LSM303_REGISTER_ACCEL_OUT_Y_L_A = 0x2A,
LSM303_REGISTER_ACCEL_OUT_Y_H_A = 0x2B,
LSM303_REGISTER_ACCEL_OUT_Z_L_A = 0x2C,
LSM303_REGISTER_ACCEL_OUT_Z_H_A = 0x2D,
LSM303_REGISTER_ACCEL_FIFO_CTRL_REG_A = 0x2E,
LSM303_REGISTER_ACCEL_FIFO_SRC_REG_A = 0x2F,
LSM303_REGISTER_ACCEL_INT1_CFG_A = 0x30,
LSM303_REGISTER_ACCEL_INT1_SOURCE_A = 0x31,
LSM303_REGISTER_ACCEL_INT1_THS_A = 0x32,
LSM303_REGISTER_ACCEL_INT1_DURATION_A = 0x33,
LSM303_REGISTER_ACCEL_INT2_CFG_A = 0x34,
LSM303_REGISTER_ACCEL_INT2_SOURCE_A = 0x35,
LSM303_REGISTER_ACCEL_INT2_THS_A = 0x36,
LSM303_REGISTER_ACCEL_INT2_DURATION_A = 0x37,
LSM303_REGISTER_ACCEL_CLICK_CFG_A = 0x38,
LSM303_REGISTER_ACCEL_CLICK_SRC_A = 0x39,
LSM303_REGISTER_ACCEL_CLICK_THS_A = 0x3A,
LSM303_REGISTER_ACCEL_TIME_LIMIT_A = 0x3B,
LSM303_REGISTER_ACCEL_TIME_LATENCY_A = 0x3C,
LSM303_REGISTER_ACCEL_TIME_WINDOW_A = 0x3D
} lsm303AccelRegisters_t;
typedef enum
{
LSM303_REGISTER_MAG_CRA_REG_M = 0x00,
LSM303_REGISTER_MAG_CRB_REG_M = 0x01,
LSM303_REGISTER_MAG_MR_REG_M = 0x02,
LSM303_REGISTER_MAG_OUT_X_H_M = 0x03,
LSM303_REGISTER_MAG_OUT_X_L_M = 0x04,
LSM303_REGISTER_MAG_OUT_Z_H_M = 0x05,
LSM303_REGISTER_MAG_OUT_Z_L_M = 0x06,
LSM303_REGISTER_MAG_OUT_Y_H_M = 0x07,
LSM303_REGISTER_MAG_OUT_Y_L_M = 0x08,
LSM303_REGISTER_MAG_SR_REG_M = 0x09,
LSM303_REGISTER_MAG_IRA_REG_M = 0x0A,
LSM303_REGISTER_MAG_IRB_REG_M = 0x0B,
LSM303_REGISTER_MAG_IRC_REG_M = 0x0C,
LSM303_REGISTER_MAG_TEMP_OUT_H_M = 0x31,
LSM303_REGISTER_MAG_TEMP_OUT_L_M = 0x32
} lsm303MagRegisters_t;
/*=========================================================================*/
/*=========================================================================
MAGNETOMETER GAIN SETTINGS
-----------------------------------------------------------------------*/
typedef enum
{
LSM303_MAGGAIN_1_3 = 0x20, // +/- 1.3
LSM303_MAGGAIN_1_9 = 0x40, // +/- 1.9
LSM303_MAGGAIN_2_5 = 0x60, // +/- 2.5
LSM303_MAGGAIN_4_0 = 0x80, // +/- 4.0
LSM303_MAGGAIN_4_7 = 0xA0, // +/- 4.7
LSM303_MAGGAIN_5_6 = 0xC0, // +/- 5.6
LSM303_MAGGAIN_8_1 = 0xE0 // +/- 8.1
} lsm303MagGain;
/*=========================================================================*/
/*=========================================================================
MAGNETOMETER UPDATE RATE SETTINGS
-----------------------------------------------------------------------*/
typedef enum
{
LSM303_MAGRATE_0_7 = 0x00, // 0.75 Hz
LSM303_MAGRATE_1_5 = 0x01, // 1.5 Hz
LSM303_MAGRATE_3_0 = 0x62, // 3.0 Hz
LSM303_MAGRATE_7_5 = 0x03, // 7.5 Hz
LSM303_MAGRATE_15 = 0x04, // 15 Hz
LSM303_MAGRATE_30 = 0x05, // 30 Hz
LSM303_MAGRATE_75 = 0x06, // 75 Hz
LSM303_MAGRATE_220 = 0x07 // 200 Hz
} lsm303MagRate;
/*=========================================================================*/
/*=========================================================================
INTERNAL MAGNETOMETER DATA TYPE
-----------------------------------------------------------------------*/
typedef struct lsm303MagData_s
{
float x;
float y;
float z;
} lsm303MagData;
/*=========================================================================*/
/*=========================================================================
INTERNAL ACCELERATION DATA TYPE
-----------------------------------------------------------------------*/
typedef struct lsm303AccelData_s
{
float x;
float y;
float z;
} lsm303AccelData;
/*=========================================================================*/
/*=========================================================================
CHIP ID
-----------------------------------------------------------------------*/
#define LSM303_ID (0b11010100)
/*=========================================================================*/
/* Unified sensor driver for the accelerometer */
class Adafruit_LSM303_Accel_Unified : public Adafruit_Sensor
{
public:
Adafruit_LSM303_Accel_Unified(int32_t sensorID = -1);
bool begin(void);
bool getEvent(sensors_event_t*);
void getSensor(sensor_t*);
void write8(byte address, byte reg, byte value);
byte read8(byte address, byte reg);
void read(void);
private:
lsm303AccelData _accelData; // Last read accelerometer data will be available here
int32_t _sensorID;
};
/* Unified sensor driver for the magnetometer */
class Adafruit_LSM303_Mag_Unified : public Adafruit_Sensor
{
public:
Adafruit_LSM303_Mag_Unified(int32_t sensorID = -1);
bool begin(void);
void enableAutoRange(bool enable);
void setMagGain(lsm303MagGain gain);
void setMagRate(lsm303MagRate rate);
bool getEvent(sensors_event_t*);
void getSensor(sensor_t*);
void write8(byte address, byte reg, byte value);
byte read8(byte address, byte reg);
void read(void);
private:
lsm303MagGain _magGain;
lsm303MagData _magData; // Last read magnetometer data will be available here
int32_t _sensorID;
bool _autoRangeEnabled;
};
#endif

2
Adafruit_Sensor.cpp Normal file
View file

@ -0,0 +1,2 @@
#include "Adafruit_Sensor.h"
#include <avr/pgmspace.h>

154
Adafruit_Sensor.h Normal file
View file

@ -0,0 +1,154 @@
/*
* Copyright (C) 2008 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software< /span>
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and
* extended sensor support to include color, voltage and current */
#ifndef _ADAFRUIT_SENSOR_H
#define _ADAFRUIT_SENSOR_H
#if ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#else
#include "WProgram.h"
#endif
/* Intentionally modeled after sensors.h in the Android API:
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h */
/* Constants */
#define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */
#define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */
#define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */
#define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH)
#define SENSORS_MAGFIELD_EARTH_MAX (60.0F) /**< Maximum magnetic field on Earth's surface */
#define SENSORS_MAGFIELD_EARTH_MIN (30.0F) /**< Minimum magnetic field on Earth's surface */
#define SENSORS_PRESSURE_SEALEVELHPA (1013.25F) /**< Average sea level pressure is 1013.25 hPa */
#define SENSORS_DPS_TO_RADS (0.017453293F) /**< Degrees/s to rad/s multiplier */
#define SENSORS_GAUSS_TO_MICROTESLA (100) /**< Gauss to micro-Tesla multiplier */
/** Sensor types */
typedef enum
{
SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */
SENSOR_TYPE_MAGNETIC_FIELD = (2),
SENSOR_TYPE_ORIENTATION = (3),
SENSOR_TYPE_GYROSCOPE = (4),
SENSOR_TYPE_LIGHT = (5),
SENSOR_TYPE_PRESSURE = (6),
SENSOR_TYPE_PROXIMITY = (8),
SENSOR_TYPE_GRAVITY = (9),
SENSOR_TYPE_LINEAR_ACCELERATION = (10), /**< Acceleration not including gravity */
SENSOR_TYPE_ROTATION_VECTOR = (11),
SENSOR_TYPE_RELATIVE_HUMIDITY = (12),
SENSOR_TYPE_AMBIENT_TEMPERATURE = (13),
SENSOR_TYPE_VOLTAGE = (15),
SENSOR_TYPE_CURRENT = (16),
SENSOR_TYPE_COLOR = (17)
} sensors_type_t;
/** struct sensors_vec_s is used to return a vector in a common format. */
typedef struct {
union {
float v[3];
struct {
float x;
float y;
float z;
};
/* Orientation sensors */
struct {
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
};
};
int8_t status;
uint8_t reserved[3];
} sensors_vec_t;
/** struct sensors_color_s is used to return color data in a common format. */
typedef struct {
union {
float c[3];
/* RGB color space */
struct {
float r; /**< Red component */
float g; /**< Green component */
float b; /**< Blue component */
};
};
uint32_t rgba; /**< 24-bit RGBA value */
} sensors_color_t;
/* Sensor event (36 bytes) */
/** struct sensor_event_s is used to provide a single sensor event in a common format. */
typedef struct
{
int32_t version; /**< must be sizeof(struct sensors_event_t) */
int32_t sensor_id; /**< unique sensor identifier */
int32_t type; /**< sensor type */
int32_t reserved0; /**< reserved */
int32_t timestamp; /**< time is in milliseconds */
union
{
float data[4];
sensors_vec_t acceleration; /**< acceleration values are in meter per second per second (m/s^2) */
sensors_vec_t magnetic; /**< magnetic vector values are in micro-Tesla (uT) */
sensors_vec_t orientation; /**< orientation values are in degrees */
sensors_vec_t gyro; /**< gyroscope values are in rad/s */
float temperature; /**< temperature is in degrees centigrade (Celsius) */
float distance; /**< distance in centimeters */
float light; /**< light in SI lux units */
float pressure; /**< pressure in hectopascal (hPa) */
float relative_humidity; /**< relative humidity in percent */
float current; /**< current in milliamps (mA) */
float voltage; /**< voltage in volts (V) */
sensors_color_t color; /**< color in RGB component values */
};
} sensors_event_t;
/* Sensor details (40 bytes) */
/** struct sensor_s is used to describe basic information about a specific sensor. */
typedef struct
{
char name[12]; /**< sensor name */
int32_t version; /**< version of the hardware + driver */
int32_t sensor_id; /**< unique sensor identifier */
int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */
float max_value; /**< maximum value of this sensor's value in SI units */
float min_value; /**< minimum value of this sensor's value in SI units */
float resolution; /**< smallest difference between two values reported by this sensor */
int32_t min_delay; /**< min delay in microseconds between events. zero = not a constant rate */
} sensor_t;
class Adafruit_Sensor {
public:
// Constructor(s)
Adafruit_Sensor() {}
virtual ~Adafruit_Sensor() {}
// These must be defined by the subclass
virtual void enableAutoRange(bool enabled) {};
virtual bool getEvent(sensors_event_t*) = 0;
virtual void getSensor(sensor_t*) = 0;
private:
bool _autoRange;
};
#endif

1
cosmicpi-arduino.cc Symbolic link
View file

@ -0,0 +1 @@
cosmicpi-arduino.ino

1104
cosmicpi-arduino.ino Normal file

File diff suppressed because it is too large Load diff