Focused on random number generation using native usb
This commit is contained in:
parent
6743f674dd
commit
32c393d035
20 changed files with 604 additions and 3607 deletions
158
Accel.ino
Normal file
158
Accel.ino
Normal file
|
|
@ -0,0 +1,158 @@
|
||||||
|
//This file contains subroutines for the Accelerometer and the Pressure sensor.
|
||||||
|
|
||||||
|
void AccelSetup(){
|
||||||
|
|
||||||
|
uint8_t tmp, val;
|
||||||
|
|
||||||
|
#define FIFO_EN 0x40
|
||||||
|
#define HPIS1 0x02
|
||||||
|
#define HPIS2 0x01
|
||||||
|
|
||||||
|
val = FIFO_EN | HPIS1;
|
||||||
|
// BusWrite(acl_ad, 0x1F, val, 1); // CTRL0
|
||||||
|
|
||||||
|
#define MXYZEN (0x7 << 5) // Enable XYZ interrupt detection
|
||||||
|
#define MIELEN 0x1 // Enable
|
||||||
|
|
||||||
|
val = MXYZEN | MIELEN;
|
||||||
|
// BusWrite(acl_ad, 0x12, val, 1); // INT_CTRL_M
|
||||||
|
|
||||||
|
// val = magnat_event_threshold >> 8; // High
|
||||||
|
// BusWrite(acl_ad, 0x15, val, 1); // INT_THS_H_M
|
||||||
|
// val = magnat_event_threshold & 0xFF; // Low
|
||||||
|
// BusWrite(acl_ad, 0x14, val, 1); // INT_THS_L_M
|
||||||
|
|
||||||
|
#define AXYXEN 0x7
|
||||||
|
#define A50Hz (0x5 << 4)
|
||||||
|
|
||||||
|
val = AXYXEN | A50Hz; // x,y,z enable and 50 Hz
|
||||||
|
//BusWrite(AccelAddr, 0x20, val, 1); // CTRL1
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x20);
|
||||||
|
Wire1.write(val);
|
||||||
|
|
||||||
|
#define GRANGE 2.0
|
||||||
|
#define AFS2G (0x00 << 3)
|
||||||
|
|
||||||
|
val = AFS2G; // +/- 2g Full scale
|
||||||
|
// BusWrite(acl_ad,0x21,val, 1); // CTRL2
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x21);
|
||||||
|
Wire1.write(val);
|
||||||
|
|
||||||
|
#define INT1_DRDY_A 0x4
|
||||||
|
#define INT1_IG1 0x20
|
||||||
|
|
||||||
|
val = INT1_IG1; // Inertial interrupts on INT1 enabled
|
||||||
|
// BusWrite(acl_ad, 0x22, val, 1); // CTRL3
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x22);
|
||||||
|
Wire1.write(val);
|
||||||
|
#define INT2_IGM 0x10
|
||||||
|
#define INT2_DRDY_M 0x4
|
||||||
|
|
||||||
|
val = INT2_IGM | INT2_DRDY_M;
|
||||||
|
// BusWrite(acl_ad, 0x23, val, 1);
|
||||||
|
|
||||||
|
#define LIR1 0x1 // Latch interrupt 1
|
||||||
|
#define MODR (0x4 << 2) // 50Hz
|
||||||
|
#define MRES (0x3 << 5) // High resolution
|
||||||
|
#define TEMPEN 0x80 // Temperature enabled
|
||||||
|
|
||||||
|
val = LIR1 | MODR | MRES | TEMPEN;
|
||||||
|
// BusWrite(acl_ad, 0x24, val, 1); // CTRL5
|
||||||
|
|
||||||
|
#define MFS (0x1 << 5) // +/- 4 Gauss full scale
|
||||||
|
|
||||||
|
val = MFS;
|
||||||
|
// BusWrite(acl_ad, 0x25, val, 1); // CTRL6
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x25);
|
||||||
|
Wire1.write(val);
|
||||||
|
|
||||||
|
#define MD 0x0 // Continuous mode
|
||||||
|
|
||||||
|
val = MD;
|
||||||
|
// BusWrite(acl_ad, 0x26, val, 1); // CTRL7
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x26);
|
||||||
|
Wire1.write(val);
|
||||||
|
#define AI6D 0x80
|
||||||
|
#define ZHIE 0x20
|
||||||
|
#define YHIE 0x08
|
||||||
|
#define XHIE 0x02
|
||||||
|
|
||||||
|
val = AI6D | XHIE | YHIE | ZHIE; // Interrupt on high x,y,z
|
||||||
|
//BusWrite(acl_ad, 0x30, val, 1); // IG_CFG1
|
||||||
|
|
||||||
|
// val = accelr_event_threshold & 0x7F;
|
||||||
|
//BusWrite(acl_ad, 0x32, val, 1); // Ineterial threshold
|
||||||
|
|
||||||
|
val = 1; // Interrupt duration
|
||||||
|
//BusWrite(acl_ad, 0x33, val, 1); // IG1_DUR1
|
||||||
|
|
||||||
|
// val = BusRead(acl_ad, 0x31, 1); // IG_SRC1 read and clear interrupts
|
||||||
|
|
||||||
|
//attachInterrupt(digitalPinToInterrupt(30),Acl_ISR,RISING);
|
||||||
|
//attachInterrupt(digitalPinToInterrupt(29),Mag_ISR,RISING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AccelRead(){
|
||||||
|
|
||||||
|
|
||||||
|
short acl_x=0, acl_y=0, acl_z=0;
|
||||||
|
float acl_fx=0.0, acl_fy=0.0, acl_fz=0.0;
|
||||||
|
uint8_t xlo,xhi,ylo,yhi,zlo,zhi;
|
||||||
|
|
||||||
|
//xlo=BusRead(acl_ad, 0x28, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x28);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
xlo = Wire1.read();
|
||||||
|
|
||||||
|
//xhi=BusRead(acl_ad, 0x29, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x29);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
xhi = Wire1.read();
|
||||||
|
|
||||||
|
//ylo=BusRead(acl_ad, 0x2A, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x2A);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
ylo = Wire1.read();
|
||||||
|
|
||||||
|
//yhi=BusRead(acl_ad, 0x2B, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x2B);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
yhi = Wire1.read();
|
||||||
|
|
||||||
|
//zlo=BusRead(acl_ad, 0x2C, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x2C);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
zlo = Wire1.read();
|
||||||
|
|
||||||
|
|
||||||
|
//zhi=BusRead(acl_ad, 0x2D, acl_bus);
|
||||||
|
Wire1.beginTransmission(AccelAddr);
|
||||||
|
Wire1.write(0x2D);
|
||||||
|
delay(5);
|
||||||
|
Wire1.requestFrom(AccelAddr, 1);
|
||||||
|
xhi = Wire1.read();
|
||||||
|
|
||||||
|
acl_x = (xhi<<8 | xlo);
|
||||||
|
acl_y = (yhi<<8 | ylo);
|
||||||
|
acl_z = (zhi<<8 | zlo);
|
||||||
|
|
||||||
|
acl_fx = (AccelFullScale * GravityEarth) * ((float) (acl_x) / (float) 0x7FFF);
|
||||||
|
acl_fy = (AccelFullScale * GravityEarth) * ((float) (acl_y) / (float) 0x7FFF);
|
||||||
|
acl_fz = (AccelFullScale * GravityEarth) * ((float) (acl_z) / (float) 0x7FFF);
|
||||||
|
}
|
||||||
|
|
@ -1,357 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,53 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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
|
|
||||||
|
|
@ -1,481 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
@ -1,122 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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
500
Adafruit_GPS.cpp
|
|
@ -1,500 +0,0 @@
|
||||||
/***********************************
|
|
||||||
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
168
Adafruit_GPS.h
|
|
@ -1,168 +0,0 @@
|
||||||
/***********************************
|
|
||||||
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
|
|
||||||
|
|
@ -1,98 +0,0 @@
|
||||||
/***************************************************
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*********************************************************************/
|
|
||||||
|
|
@ -1,45 +0,0 @@
|
||||||
/***************************************************
|
|
||||||
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;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
@ -1,364 +0,0 @@
|
||||||
/***************************************************
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -1,104 +0,0 @@
|
||||||
/***************************************************
|
|
||||||
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
|
|
||||||
|
|
@ -1,555 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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);
|
|
||||||
|
|
||||||
// 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**************************************************************************/
|
|
||||||
/*!
|
|
||||||
@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_Mg);
|
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -1,199 +0,0 @@
|
||||||
/***************************************************************************
|
|
||||||
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_Mg = 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*);
|
|
||||||
|
|
||||||
private:
|
|
||||||
lsm303AccelData _accelData; // Last read accelerometer data will be available here
|
|
||||||
int32_t _sensorID;
|
|
||||||
|
|
||||||
void write8(byte address, byte reg, byte value);
|
|
||||||
byte read8(byte address, byte reg);
|
|
||||||
void read(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* 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*);
|
|
||||||
|
|
||||||
private:
|
|
||||||
lsm303MagGain _magGain;
|
|
||||||
lsm303MagData _magData; // Last read magnetometer data will be available here
|
|
||||||
int32_t _sensorID;
|
|
||||||
bool _autoRangeEnabled;
|
|
||||||
|
|
||||||
void write8(byte address, byte reg, byte value);
|
|
||||||
byte read8(byte address, byte reg);
|
|
||||||
void read(void);
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -1,2 +0,0 @@
|
||||||
#include "Adafruit_Sensor.h"
|
|
||||||
#include <avr/pgmspace.h>
|
|
||||||
|
|
@ -1,154 +0,0 @@
|
||||||
/*
|
|
||||||
* 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
|
|
||||||
306
CosmicPiArduino.ino
Normal file
306
CosmicPiArduino.ino
Normal file
|
|
@ -0,0 +1,306 @@
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
//Cosmic Pi Firmware - forked version J.Devine 2017
|
||||||
|
//Bugs: Internal temperature doesn't work when ADC is in free running mode; configuration needs changing in the temp subroutine.
|
||||||
|
|
||||||
|
|
||||||
|
float ADCTempValue = 0; //buffer for the internal temperature
|
||||||
|
String SerialNumberValue = ""; //Buffer for the serial number
|
||||||
|
long PPSLength = 0; //The number of internal clock cycles in a GPS PPS
|
||||||
|
long PPSUptime = 0; //The number of PPS pulses counted since the last reboot.
|
||||||
|
long PreviousPPS = 0; //The value of the previous PPS (to define which second we're in)
|
||||||
|
int EventsThisSecond = 0; //The number of events since the last PPS
|
||||||
|
bool dump = false; //if there's an event, dump the data.
|
||||||
|
|
||||||
|
//SoftSPI pin assignments
|
||||||
|
#define SS_pin 42
|
||||||
|
#define SCK_pin 44
|
||||||
|
#define MISO_pin 22
|
||||||
|
#define MOSI_pin 43
|
||||||
|
|
||||||
|
//Pinout definitions
|
||||||
|
#define Power_LED 11
|
||||||
|
#define Event_LED 12
|
||||||
|
#define Event_Input 5
|
||||||
|
|
||||||
|
|
||||||
|
//I2C Bus 0 Addresses
|
||||||
|
#define I2CPot 0x28
|
||||||
|
#define I2CPot1_PIN 35
|
||||||
|
#define I2CPot2_PIN 36
|
||||||
|
#define I2CPot3_PIN 37
|
||||||
|
|
||||||
|
//I2C Bus 1 Addresses
|
||||||
|
#define HumAddr 0x40
|
||||||
|
#define AccelAddr 0x1D // LMS303D on the main board on i2c bus 1
|
||||||
|
#define ACL_ID 0x49 // LMS303D ID register value
|
||||||
|
#define ACL_ID_REG 0x0F // LMS303D ID register address
|
||||||
|
|
||||||
|
|
||||||
|
#define AccelFullScale 2.0 // +-2g 16 bit 2's compliment
|
||||||
|
#define GravityEarth 9.80665 //The earth's gravity
|
||||||
|
|
||||||
|
|
||||||
|
String StringEventBuf[3] = {"Output String Buffer Event 1", "Output String Buffer Event 2", "Output String Buffer Event 3"};
|
||||||
|
long EventTimestamp[3] = {0,0,0};
|
||||||
|
float Accel[3]; //Accelerometer array, 0 is X, 1 is Y and 2 is Z.
|
||||||
|
unsigned long timeX = 0;
|
||||||
|
unsigned long oldtime = 0;
|
||||||
|
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
|
||||||
|
//Start Wire (I2C comms)
|
||||||
|
Wire.begin();
|
||||||
|
Wire1.begin();
|
||||||
|
//LED output pins
|
||||||
|
pinMode(Power_LED, OUTPUT); //Power LED
|
||||||
|
pinMode(Event_LED, OUTPUT); //Event LED
|
||||||
|
pinMode(Event_Input, INPUT); //Event LED
|
||||||
|
//SoftSPI output pins
|
||||||
|
digitalWrite(SS, HIGH); // Start with SS high
|
||||||
|
pinMode(SS_pin, OUTPUT);
|
||||||
|
pinMode(SCK_pin, OUTPUT);
|
||||||
|
pinMode(MISO_pin, INPUT); //note this is the avalanche output from the MAX1932, but not yet used
|
||||||
|
pinMode(MOSI_pin, OUTPUT);
|
||||||
|
//I2CPot output pins
|
||||||
|
pinMode(I2CPot1_PIN, OUTPUT);
|
||||||
|
pinMode(I2CPot2_PIN, OUTPUT);
|
||||||
|
pinMode(I2CPot3_PIN, OUTPUT);
|
||||||
|
//and write them low
|
||||||
|
digitalWrite(I2CPot1_PIN, LOW);
|
||||||
|
digitalWrite(I2CPot2_PIN, LOW);
|
||||||
|
digitalWrite(I2CPot3_PIN, LOW);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Serial.begin(9600);//we run the serial at 9600 for debugging only.
|
||||||
|
//make sure the LED's are off
|
||||||
|
digitalWrite(Power_LED, 0);
|
||||||
|
digitalWrite(Event_LED, 0);
|
||||||
|
//Temporary positioning; Read the temperature at boot in the Arduino
|
||||||
|
//ADCTempValue = ADCTemp();
|
||||||
|
//Serial.println(ADCTempValue);
|
||||||
|
//Set the Vbias based on the internal temperature at boot
|
||||||
|
VbiasSet(100);
|
||||||
|
ThresholdSet(130,130);
|
||||||
|
|
||||||
|
//ADCSetup();
|
||||||
|
//TimerInit();
|
||||||
|
PowerOn();
|
||||||
|
//AccelSetup();
|
||||||
|
SerialNumberValue = SerialNumberReadout();
|
||||||
|
Serial.println(SerialNumberValue);
|
||||||
|
Serial.println("finished init");
|
||||||
|
timeX = millis();
|
||||||
|
Serial.print("analogue values ");
|
||||||
|
int Ch1 = analogRead(A6);
|
||||||
|
int Ch2 = analogRead(A7);
|
||||||
|
Serial.print(Ch1);
|
||||||
|
Serial.print(" ");
|
||||||
|
Serial.println(Ch2);
|
||||||
|
|
||||||
|
//) + " " + int(analogRead(A7)));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//Serial.println(String(analogRead(A6))+" "+String(analogRead(A7))+" " +int(digitalRead(Event_Input)));
|
||||||
|
|
||||||
|
if (digitalRead(Event_Input)) {
|
||||||
|
Serial.print("Event ");
|
||||||
|
oldtime = timeX;
|
||||||
|
timeX = millis();
|
||||||
|
//prints time since program started
|
||||||
|
Serial.println(timeX - oldtime);
|
||||||
|
EventFlashOn();
|
||||||
|
delay(50);
|
||||||
|
EventFlashOff();
|
||||||
|
}
|
||||||
|
// Serial.println("temp");
|
||||||
|
// Serial.println(HumReadTemp());
|
||||||
|
//delay(1000);
|
||||||
|
|
||||||
|
// Serial.println("Hum");
|
||||||
|
// Serial.println(HumReadHum());
|
||||||
|
//delay(1000);
|
||||||
|
//ThresholdSet(200,20);
|
||||||
|
//Serial.println("Accel");
|
||||||
|
//AccelRead();
|
||||||
|
// Serial.println(String(Accel[0])+" "+ String(Accel[1])+" "+ String(Accel[2]));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void TimerInit() {
|
||||||
|
|
||||||
|
uint32_t config = 0;
|
||||||
|
|
||||||
|
// Set up the power management controller for TC0 and TC2
|
||||||
|
|
||||||
|
pmc_set_writeprotect(false); // Enable write access to power management chip
|
||||||
|
pmc_enable_periph_clk(ID_TC0); // Turn on power for timer block 0 channel 0
|
||||||
|
pmc_enable_periph_clk(ID_TC6); // Turn on power for timer block 2 channel 0
|
||||||
|
|
||||||
|
// Timer block zero channel zero is connected only to the PPS
|
||||||
|
// We set it up to load regester RA on each PPS and reset
|
||||||
|
// So RA will contain the number of clock ticks between two PPS, this
|
||||||
|
// value should be very stable +/- one tick
|
||||||
|
|
||||||
|
config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz
|
||||||
|
TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA0
|
||||||
|
TC_CMR_ABETRG | // Use the TIOA external input line
|
||||||
|
TC_CMR_LDRA_RISING; // Latch counter value into RA
|
||||||
|
|
||||||
|
TC_Configure(TC0, 0, config); // Configure channel 0 of TC0
|
||||||
|
TC_Start(TC0, 0); // Start timer running
|
||||||
|
|
||||||
|
TC0->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS
|
||||||
|
TC0->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources
|
||||||
|
NVIC_EnableIRQ(TC0_IRQn); // Enable interrupt handler for channel 0
|
||||||
|
|
||||||
|
// Timer block 2 channel zero is connected to the OR of the PPS and the RAY event
|
||||||
|
|
||||||
|
config = TC_CMR_TCCLKS_TIMER_CLOCK1 | // Select fast clock MCK/2 = 42 MHz
|
||||||
|
TC_CMR_ETRGEDG_RISING | // External trigger rising edge on TIOA1
|
||||||
|
TC_CMR_ABETRG | // Use the TIOA external input line
|
||||||
|
TC_CMR_LDRA_RISING; // Latch counter value into RA
|
||||||
|
|
||||||
|
TC_Configure(TC2, 0, config); // Configure channel 0 of TC2
|
||||||
|
TC_Start(TC2, 0); // Start timer running
|
||||||
|
|
||||||
|
TC2->TC_CHANNEL[0].TC_IER = TC_IER_LDRAS; // Enable the load AR channel 0 interrupt each PPS
|
||||||
|
TC2->TC_CHANNEL[0].TC_IDR = ~TC_IER_LDRAS; // and disable the rest of the interrupt sources
|
||||||
|
NVIC_EnableIRQ(TC6_IRQn); // Enable interrupt handler for channel 0
|
||||||
|
|
||||||
|
// Set up the PIO controller to route input pins for TC0 and TC2
|
||||||
|
|
||||||
|
PIO_Configure(PIOC,PIO_INPUT,
|
||||||
|
PIO_PB25B_TIOA0, // D2 Input for PPS
|
||||||
|
PIO_DEFAULT);
|
||||||
|
|
||||||
|
PIO_Configure(PIOC,PIO_INPUT,
|
||||||
|
PIO_PC25B_TIOA6, // D5 Input for Trigger
|
||||||
|
PIO_DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TC0_Handler() {
|
||||||
|
//This is called the one second event interrupt in documentation
|
||||||
|
//when the PPS event occurs
|
||||||
|
PPSLength = TC0->TC_CHANNEL[0].TC_RA; // Read the RA reg (PPS period)
|
||||||
|
TC_GetStatus(TC0, 0); // Read status and clear load bits
|
||||||
|
|
||||||
|
PPSUptime++; // PPS count
|
||||||
|
EventsThisSecond=0; //reset the event counter for this second
|
||||||
|
}
|
||||||
|
|
||||||
|
void TC6_Handler() {
|
||||||
|
Serial.println("Cosmic");
|
||||||
|
//rega1 = TC2->TC_CHANNEL[0].TC_RA; // Read the RA on channel 1 (PPS period)
|
||||||
|
//stsr1 =
|
||||||
|
EventTimestamp[EventsThisSecond] = TC0->TC_CHANNEL[0].TC_RA; //read the main clock and copy it to the event register
|
||||||
|
EventsThisSecond++; //increment the event counter for this second
|
||||||
|
TC_GetStatus(TC2, 0); // Read status clear load bits, unlocking this interrupt.
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void ADCSetup() {
|
||||||
|
REG_ADC_MR = 0x10380080; // Free run as fast as you can
|
||||||
|
REG_ADC_CHER = 3; // Channels 0 and 1
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PowerOn(){
|
||||||
|
digitalWrite(Power_LED, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventFlashOn(){
|
||||||
|
digitalWrite(Event_LED, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void EventFlashOff(){
|
||||||
|
digitalWrite(Event_LED, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//This reads out the device serial number.
|
||||||
|
__attribute__ ((section (".ramfunc")))
|
||||||
|
String SerialNumberReadout() {
|
||||||
|
unsigned int status;
|
||||||
|
unsigned int pdwUniqueID[4];
|
||||||
|
|
||||||
|
/* Send the Start Read unique Identifier command (STUI)
|
||||||
|
* by writing the Flash Command Register with the STUI command.
|
||||||
|
*/
|
||||||
|
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_STUI;
|
||||||
|
do {
|
||||||
|
status = EFC1->EEFC_FSR ;
|
||||||
|
} while ((status & EEFC_FSR_FRDY) == EEFC_FSR_FRDY);
|
||||||
|
|
||||||
|
/* The Unique Identifier is located in the first 128 bits of the
|
||||||
|
* Flash memory mapping. So, at the address 0x400000-0x400003.
|
||||||
|
*/
|
||||||
|
pdwUniqueID[0] = *(uint32_t *)IFLASH1_ADDR;
|
||||||
|
pdwUniqueID[1] = *(uint32_t *)(IFLASH1_ADDR + 4);
|
||||||
|
pdwUniqueID[2] = *(uint32_t *)(IFLASH1_ADDR + 8);
|
||||||
|
pdwUniqueID[3] = *(uint32_t *)(IFLASH1_ADDR + 12);
|
||||||
|
|
||||||
|
/* To stop the Unique Identifier mode, the user needs to send the Stop Read unique Identifier
|
||||||
|
* command (SPUI) by writing the Flash Command Register with the SPUI command.
|
||||||
|
*/
|
||||||
|
EFC1->EEFC_FCR = (0x5A << 24) | EFC_FCMD_SPUI ;
|
||||||
|
|
||||||
|
/* When the Stop read Unique Unique Identifier command (SPUI) has been performed, the
|
||||||
|
* FRDY bit in the Flash Programming Status Register (EEFC_FSR) rises.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
status = EFC1->EEFC_FSR ;
|
||||||
|
} while ((status & EEFC_FSR_FRDY) != EEFC_FSR_FRDY);
|
||||||
|
|
||||||
|
|
||||||
|
int uid_ok = 0;
|
||||||
|
String uidtxt;
|
||||||
|
uidtxt = String(pdwUniqueID[0]) + String(pdwUniqueID[1]) + String(pdwUniqueID[2]) + String(pdwUniqueID[3]);
|
||||||
|
return uidtxt;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
float ADCTemp(){
|
||||||
|
//Routine uses the internal temperature sensor in the Arduino DUE
|
||||||
|
//Note this uses the ADC
|
||||||
|
float trans = 3.3/4096;
|
||||||
|
float offset = 0.8;
|
||||||
|
float factor = 0.00256;
|
||||||
|
int fixtemp = 27;
|
||||||
|
uint32_t ulValue = 0;
|
||||||
|
uint32_t ulChannel;
|
||||||
|
//BUG: The ADC needs to be reset using these register values; otherwise the values read out are WRONG.
|
||||||
|
//REG_ADC_MR = 0x00000000; // Void this register
|
||||||
|
//REG_ADC_CHER = 0; // No channels running
|
||||||
|
|
||||||
|
|
||||||
|
// Enable the corresponding channel
|
||||||
|
adc_enable_channel(ADC, ADC_TEMPERATURE_SENSOR);
|
||||||
|
|
||||||
|
// Enable the temperature sensor
|
||||||
|
adc_enable_ts(ADC);
|
||||||
|
|
||||||
|
// Start the ADC
|
||||||
|
adc_start(ADC);
|
||||||
|
|
||||||
|
// Wait for end of conversion
|
||||||
|
while ((adc_get_status(ADC) & ADC_ISR_DRDY) != ADC_ISR_DRDY);
|
||||||
|
|
||||||
|
// Read the value
|
||||||
|
ulValue = adc_get_latest_value(ADC);
|
||||||
|
|
||||||
|
// Disable the corresponding channel
|
||||||
|
adc_disable_channel(ADC, ADC_TEMPERATURE_SENSOR);
|
||||||
|
|
||||||
|
float treal = fixtemp + (( trans * ulValue ) - offset ) / factor;
|
||||||
|
|
||||||
|
return treal;
|
||||||
|
}
|
||||||
|
|
||||||
68
Humidity.ino
Normal file
68
Humidity.ino
Normal file
|
|
@ -0,0 +1,68 @@
|
||||||
|
//This file contains subroutines for the humidity sensor.
|
||||||
|
|
||||||
|
void HumSetup(){
|
||||||
|
//nothing happens here
|
||||||
|
}
|
||||||
|
|
||||||
|
float HumReadTemp(){
|
||||||
|
//note this isn't working yet, no traffic on the I2C1 bus
|
||||||
|
int HumTemp1 = 0;
|
||||||
|
int HumTemp2 = 0;
|
||||||
|
int HumTemp3 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
Serial.println("temp sub");
|
||||||
|
Wire1.beginTransmission(HumAddr);
|
||||||
|
Wire1.write(0xE3);
|
||||||
|
delay(5);
|
||||||
|
|
||||||
|
Wire1.requestFrom(HumAddr, 3);
|
||||||
|
//while (!Wire1.available()) {
|
||||||
|
// if (htu_tmo++ > HTU_TIMEOUT)
|
||||||
|
// break;
|
||||||
|
// else
|
||||||
|
// delay(1);
|
||||||
|
//}
|
||||||
|
HumTemp1 = Wire1.read();
|
||||||
|
HumTemp2 = Wire1.read();
|
||||||
|
HumTemp3 = Wire1.read();
|
||||||
|
//}
|
||||||
|
|
||||||
|
Serial.println("read complete");
|
||||||
|
int Stemp = (HumTemp1 << 8) | HumTemp2;
|
||||||
|
float temp = -46.85 + (175.72 * Stemp / ((float) (unsigned int) 0x10000));
|
||||||
|
return temp;
|
||||||
|
// See data sheet for this formula
|
||||||
|
}
|
||||||
|
|
||||||
|
float HumReadHum(){
|
||||||
|
//note this also isn't working yet, no traffic on the I2C1 bus
|
||||||
|
int HumHum1 = 0;
|
||||||
|
int HumHum2 = 0;
|
||||||
|
int HumHum3 = 0;
|
||||||
|
|
||||||
|
|
||||||
|
Serial.println("hum sub");
|
||||||
|
Wire1.beginTransmission(HumAddr);
|
||||||
|
Wire1.write(0xE5);
|
||||||
|
delay(5);
|
||||||
|
|
||||||
|
Wire1.requestFrom(HumAddr, 3);
|
||||||
|
//while (!Wire1.available()) {
|
||||||
|
// if (htu_tmo++ > HTU_TIMEOUT)
|
||||||
|
// break;
|
||||||
|
// else
|
||||||
|
// delay(1);
|
||||||
|
//}
|
||||||
|
HumHum1 = Wire1.read();
|
||||||
|
HumHum2 = Wire1.read();
|
||||||
|
HumHum3 = Wire1.read();
|
||||||
|
//}
|
||||||
|
|
||||||
|
Serial.println("read complete");
|
||||||
|
int SHumTemp = (HumHum1 << 8) | HumHum2;
|
||||||
|
float temp = -6.0 + (125.0 * SHumTemp / ((float) (unsigned int) 0x10000));
|
||||||
|
return temp;
|
||||||
|
// See data sheet for this formula
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -1,379 +0,0 @@
|
||||||
#include "Adafruit_BMP085_U.h"
|
|
||||||
#include "Adafruit_GPS.h"
|
|
||||||
#include "Adafruit_Sensor.h"
|
|
||||||
#include "Adafruit_L3GD20_U.h"
|
|
||||||
#include "Adafruit_LSM303_U.h"
|
|
||||||
#include "Adafruit_10DOF.h"
|
|
||||||
#include "Adafruit_HTU21DF.h"
|
|
||||||
#include <Wire.h>
|
|
||||||
#include <SPI.h>
|
|
||||||
|
|
||||||
|
|
||||||
//definitions of stuff
|
|
||||||
//GPS serial read on Due serial 2
|
|
||||||
#define mySerial Serial1
|
|
||||||
#define GPSECHO true
|
|
||||||
//SPI device enable pin
|
|
||||||
const int slaveAPin = 52;
|
|
||||||
//integer array for data sampling
|
|
||||||
unsigned int values[200];
|
|
||||||
//byte outputbuffer[1200];
|
|
||||||
//define trigger pin
|
|
||||||
const int eventtrigger = 49;
|
|
||||||
boolean eventhappened = false;
|
|
||||||
|
|
||||||
//How many samples to readback on trigger
|
|
||||||
const int sampledepth = 10;
|
|
||||||
|
|
||||||
//how many events have happened since reset
|
|
||||||
long eventcounter = 0;
|
|
||||||
|
|
||||||
//how many measurement points have been readback in the adcoutput loop
|
|
||||||
int readoutctr = 0;
|
|
||||||
|
|
||||||
//Index counter for the ADC buffer,
|
|
||||||
int adcloopctr = 0;
|
|
||||||
|
|
||||||
//timing second reset signal from GPS
|
|
||||||
const int timeresetpin = 50;
|
|
||||||
|
|
||||||
//define adafruit components
|
|
||||||
Adafruit_10DOF dof = Adafruit_10DOF();
|
|
||||||
Adafruit_LSM303_Accel_Unified accel = Adafruit_LSM303_Accel_Unified(30301);
|
|
||||||
Adafruit_LSM303_Mag_Unified mag = Adafruit_LSM303_Mag_Unified(30302);
|
|
||||||
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(18001);
|
|
||||||
Adafruit_HTU21DF htu = Adafruit_HTU21DF();
|
|
||||||
Adafruit_GPS GPS(&mySerial);
|
|
||||||
|
|
||||||
//define variables
|
|
||||||
String inputString = ""; // a string to hold incoming data
|
|
||||||
boolean stringComplete = false; // whether the string is complete
|
|
||||||
boolean timereset = false; //has an event been detected?
|
|
||||||
String lastgpsread = "";
|
|
||||||
//lastgpsread.reserve(100);
|
|
||||||
int deviceid = random(1, 10000);
|
|
||||||
float temperature;
|
|
||||||
double temperatureh = 0;
|
|
||||||
double humidity = 0;
|
|
||||||
double baroaltitude = 0;
|
|
||||||
double accelx = 0;
|
|
||||||
double accely = 0;
|
|
||||||
double accelz = 0;
|
|
||||||
double magx = 0;
|
|
||||||
double magy = 0;
|
|
||||||
double magz = 0;
|
|
||||||
int currentval = 0xFF;
|
|
||||||
|
|
||||||
//this is the target voltage for the SIPM supply from the MAX1932
|
|
||||||
int stablevoltage = 0x6D;
|
|
||||||
|
|
||||||
long exacttime = 0;
|
|
||||||
int uptime = 0;
|
|
||||||
String outputbuffer = ""; //write all the outputs to a buffer and then fmacro it out
|
|
||||||
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
|
|
||||||
|
|
||||||
//define a reservation for the lastgpsread
|
|
||||||
//didn't work as there's already a reservation
|
|
||||||
|
|
||||||
void setup()
|
|
||||||
{
|
|
||||||
//run the sensor initialisation routine
|
|
||||||
initSensors();
|
|
||||||
|
|
||||||
//init GPS on second serial port
|
|
||||||
GPS.begin(9600);
|
|
||||||
mySerial.begin(9600);
|
|
||||||
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCONLY);
|
|
||||||
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
|
|
||||||
delay(1000);
|
|
||||||
Serial.println(F("GPS online"));
|
|
||||||
inputString.reserve(250);
|
|
||||||
pinMode(timeresetpin, INPUT);
|
|
||||||
attachInterrupt(timeresetpin, timeset, RISING);
|
|
||||||
pinMode(eventtrigger, INPUT);
|
|
||||||
attachInterrupt(eventtrigger, monkey, FALLING);
|
|
||||||
Serial.begin(115200); // initialize the serial port:
|
|
||||||
|
|
||||||
//setup ADC
|
|
||||||
REG_ADC_MR = 0x10380180; // change from 10380200 to 10380180, 1 is the PREESCALER and 8 means FREERUN
|
|
||||||
ADC -> ADC_CHER = 0x03; // enable ADC on pin A6 and A7
|
|
||||||
eventhappened = false;
|
|
||||||
adcloopctr = 0;
|
|
||||||
Serial.println("ADC Alive");
|
|
||||||
|
|
||||||
pinMode (slaveAPin, OUTPUT);
|
|
||||||
digitalWrite(slaveAPin, LOW);
|
|
||||||
SPI.begin();
|
|
||||||
Serial.println(F("ramping start"));
|
|
||||||
ramp(stablevoltage);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void loop() {
|
|
||||||
|
|
||||||
exacttime++; //increment the sub second timer
|
|
||||||
|
|
||||||
unsigned long t = micros(); // init time an elapsed time, in micro seconds
|
|
||||||
|
|
||||||
// instrucction to measure from ADC in rolling mode
|
|
||||||
while ((ADC->ADC_ISR & 0x3) == 0); // wait for conversion
|
|
||||||
values[adcloopctr + 100] = ADC->ADC_CDR[0]; // read value A0
|
|
||||||
values[adcloopctr] = ADC->ADC_CDR[1]; // read value A0
|
|
||||||
adcloopctr++;
|
|
||||||
|
|
||||||
//read out from the GPS if the string has finished
|
|
||||||
if (stringComplete) {
|
|
||||||
lastgpsread = inputString;
|
|
||||||
lastgpsread.trim();
|
|
||||||
//debug printout
|
|
||||||
//Serial.println(inputString);
|
|
||||||
// clear the string:
|
|
||||||
inputString = "";
|
|
||||||
stringComplete = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//if the GPS says it's one second then restart the local clock and echo
|
|
||||||
if (timereset) {
|
|
||||||
Serial.println("Timereset Detection on pin 50");
|
|
||||||
Serial.println(exacttime);
|
|
||||||
exacttime = 0;
|
|
||||||
timereset = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (eventhappened) {
|
|
||||||
readoutctr = 10;
|
|
||||||
sensorreadout();
|
|
||||||
eventcounter++;
|
|
||||||
printdatajson();
|
|
||||||
//Serial.println(F("Event"));
|
|
||||||
eventhappened = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (adcloopctr == sampledepth) {
|
|
||||||
adcloopctr = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//serial event from GPS handling
|
|
||||||
void serialEvent1() {
|
|
||||||
while (Serial1.available()) {
|
|
||||||
// get the new byte:
|
|
||||||
char inChar = (char)Serial1.read();
|
|
||||||
// add it to the inputString:
|
|
||||||
if (inChar != char(10))
|
|
||||||
{
|
|
||||||
inputString += inChar;
|
|
||||||
}
|
|
||||||
// if the incoming character is a newline, set a flag
|
|
||||||
// so the main loop can do something about it:
|
|
||||||
if (inChar == '\n') {
|
|
||||||
stringComplete = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Serial event from GPS interrupt, launches the second routine to avoid a crash
|
|
||||||
void serialEventRun(void)
|
|
||||||
{
|
|
||||||
if (Serial1.available())
|
|
||||||
serialEvent1();
|
|
||||||
}
|
|
||||||
|
|
||||||
//run once to initialise the sensor systems
|
|
||||||
void initSensors()
|
|
||||||
{
|
|
||||||
if (!accel.begin())
|
|
||||||
{
|
|
||||||
/* There was a problem detecting the LSM303 ... check your connections */
|
|
||||||
Serial.println(F("Ooops, no LSM303 detected ... Check your wiring!"));
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
if (!mag.begin())
|
|
||||||
{
|
|
||||||
/* There was a problem detecting the LSM303 ... check your connections */
|
|
||||||
Serial.println("Ooops, no LSM303 detected ... Check your wiring!");
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
if (!bmp.begin())
|
|
||||||
{
|
|
||||||
/* There was a problem detecting the BMP180 ... check your connections */
|
|
||||||
Serial.println("Ooops, no BMP180 detected ... Check your wiring!");
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
if (!htu.begin()) {
|
|
||||||
Serial.println("Couldn't find HTU21DF sensor!");
|
|
||||||
while (1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//print out everything
|
|
||||||
void printdatajson()
|
|
||||||
{
|
|
||||||
//rewritten to use a buffer
|
|
||||||
//start the data output on in json format
|
|
||||||
outputbuffer = "{\"gps\": \"";
|
|
||||||
outputbuffer = outputbuffer + lastgpsread;
|
|
||||||
outputbuffer = outputbuffer + "\" ,\"timing\":";
|
|
||||||
outputbuffer = outputbuffer + exacttime;
|
|
||||||
outputbuffer = outputbuffer +",\"energy\": { \"energy1\": [";
|
|
||||||
|
|
||||||
for (int firsthalf = adcloopctr + 1; firsthalf < sampledepth; firsthalf++)
|
|
||||||
{
|
|
||||||
outputbuffer = outputbuffer + (values[firsthalf]);
|
|
||||||
if (readoutctr != 1) outputbuffer = outputbuffer + (", ");
|
|
||||||
readoutctr--;
|
|
||||||
}
|
|
||||||
for (int secondhalf = 0; secondhalf < adcloopctr + 1; secondhalf++)
|
|
||||||
{
|
|
||||||
outputbuffer = outputbuffer + (values[secondhalf]);
|
|
||||||
if (readoutctr != 1) outputbuffer = outputbuffer + (", ");
|
|
||||||
readoutctr--;
|
|
||||||
}
|
|
||||||
Serial.print((outputbuffer));
|
|
||||||
outputbuffer = "";
|
|
||||||
Serial.print(" ],");
|
|
||||||
Serial.print(" \"energy2\": [");
|
|
||||||
readoutctr = 10;
|
|
||||||
|
|
||||||
for (int firsthalf = adcloopctr + 1; firsthalf < sampledepth; firsthalf++)
|
|
||||||
{
|
|
||||||
Serial.print(values[firsthalf + 100]);
|
|
||||||
if (readoutctr != 1) Serial.print(", ");
|
|
||||||
readoutctr--;
|
|
||||||
}
|
|
||||||
for (int secondhalf = 0; secondhalf < adcloopctr + 1; secondhalf++)
|
|
||||||
{
|
|
||||||
Serial.print(values[secondhalf + 100]);
|
|
||||||
if (readoutctr != 1) Serial.print(", ");
|
|
||||||
readoutctr--;
|
|
||||||
}
|
|
||||||
Serial.print(" ]");
|
|
||||||
Serial.print(" },");
|
|
||||||
|
|
||||||
Serial.print(" \"altitude\": ");
|
|
||||||
Serial.print(baroaltitude);
|
|
||||||
Serial.print(",");
|
|
||||||
|
|
||||||
Serial.print(" \"humidity\": ");
|
|
||||||
Serial.print(humidity);
|
|
||||||
Serial.print(",");
|
|
||||||
|
|
||||||
Serial.print(" \"gravitationalOrientation\": {");
|
|
||||||
Serial.print(" \"x\": ");
|
|
||||||
Serial.print(accelx);
|
|
||||||
Serial.print(",");
|
|
||||||
Serial.print(" \"y\": ");
|
|
||||||
Serial.print(accely);
|
|
||||||
Serial.print(",");
|
|
||||||
Serial.print(" \"z\": ");
|
|
||||||
Serial.print(accelz);
|
|
||||||
Serial.print(" },");
|
|
||||||
|
|
||||||
Serial.print(" \"magneticOrientation\": {");
|
|
||||||
Serial.print(" \"x\": ");
|
|
||||||
Serial.print(magx);
|
|
||||||
Serial.print(",");
|
|
||||||
Serial.print(" \"y\": ");
|
|
||||||
Serial.print(magy);
|
|
||||||
Serial.print(",");
|
|
||||||
Serial.print(" \"z\": ");
|
|
||||||
Serial.print(magz);
|
|
||||||
Serial.print(" },");
|
|
||||||
|
|
||||||
Serial.print(" \"temperature\": {");
|
|
||||||
Serial.print(" \"value1\": ");
|
|
||||||
Serial.print(temperatureh); //val1 is from the humidity sensor
|
|
||||||
Serial.print(",");
|
|
||||||
Serial.print(" \"value2\": ");
|
|
||||||
Serial.print(temperature);
|
|
||||||
Serial.print(" },");
|
|
||||||
|
|
||||||
Serial.print(" \"uptime\": ");
|
|
||||||
Serial.print(uptime);
|
|
||||||
Serial.print(",");
|
|
||||||
|
|
||||||
Serial.print(" \"id\": ");
|
|
||||||
Serial.print(deviceid);
|
|
||||||
Serial.println("}");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void monkey()
|
|
||||||
{
|
|
||||||
//Serial.println("trigger");
|
|
||||||
eventhappened = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void sensorreadout()
|
|
||||||
{
|
|
||||||
sensors_event_t accel_event;
|
|
||||||
sensors_event_t mag_event;
|
|
||||||
sensors_event_t bmp_event;
|
|
||||||
sensors_vec_t orientation;
|
|
||||||
|
|
||||||
/* Calculate pitch and roll from the raw accelerometer data */
|
|
||||||
accel.getEvent(&accel_event);
|
|
||||||
if (dof.accelGetOrientation(&accel_event, &orientation))
|
|
||||||
{
|
|
||||||
accelx = (accel_event.acceleration.x);
|
|
||||||
accely = (accel_event.acceleration.y);
|
|
||||||
accelz = (accel_event.acceleration.z);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the heading using the magnetometer */
|
|
||||||
mag.getEvent(&mag_event);
|
|
||||||
if (dof.magGetOrientation(SENSOR_AXIS_Z, &mag_event, &orientation))
|
|
||||||
{
|
|
||||||
magx = (mag_event.magnetic.x);
|
|
||||||
magy = (mag_event.magnetic.y);
|
|
||||||
magz = (mag_event.magnetic.z);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Calculate the altitude using the barometric pressure sensor */
|
|
||||||
bmp.getEvent(&bmp_event);
|
|
||||||
if (bmp_event.pressure)
|
|
||||||
{
|
|
||||||
/* Get ambient temperature in C */
|
|
||||||
bmp.getTemperature(&temperature);
|
|
||||||
/* Convert atmospheric pressure, SLP and temp to altitude */
|
|
||||||
baroaltitude = (bmp.pressureToAltitude(seaLevelPressure, bmp_event.pressure, temperature));
|
|
||||||
|
|
||||||
temperatureh = (htu.readTemperature());
|
|
||||||
humidity = (htu.readHumidity());
|
|
||||||
}
|
|
||||||
|
|
||||||
// energy1= energy1 + random(-100,100);
|
|
||||||
// energy2= energy2 + random(-100,100);
|
|
||||||
uptime++;
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void timeset()
|
|
||||||
{
|
|
||||||
timereset = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ramp(int target)
|
|
||||||
{
|
|
||||||
//wait 100ms before ramp up
|
|
||||||
int difference = currentval - target;
|
|
||||||
|
|
||||||
while (currentval > target)
|
|
||||||
{
|
|
||||||
digitalWrite(slaveAPin, LOW);
|
|
||||||
SPI.beginTransaction(SPISettings(2000000, MSBFIRST, SPI_MODE0));
|
|
||||||
//digitalWrite(slaveAPin, LOW);
|
|
||||||
delay(180);
|
|
||||||
SPI.transfer(currentval);
|
|
||||||
Serial.println(currentval);
|
|
||||||
delay(180);
|
|
||||||
//digitalWrite(slaveAPin, HIGH);
|
|
||||||
SPI.endTransaction();
|
|
||||||
digitalWrite(slaveAPin, HIGH);
|
|
||||||
currentval = currentval - 2;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
Software License Agreement (BSD License)
|
|
||||||
|
|
||||||
Copyright (c) 2012, Adafruit Industries
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
1. Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
2. Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
3. Neither the name of the copyright holders nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
|
||||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
72
peripherals.ino
Normal file
72
peripherals.ino
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
//This contains subroutines for generic peripherals
|
||||||
|
//MAX5387 Variable resistor
|
||||||
|
//MAX1932 HV PSU
|
||||||
|
|
||||||
|
void ThresholdSet(int ThreshA, int ThreshB) {
|
||||||
|
//This kinda works
|
||||||
|
// Serial.println("Test of threshold setting");
|
||||||
|
// Serial.print(ThreshA);
|
||||||
|
//Serial.println(analogRead(A1)); //internal readback of the DREF value only, not returned to main code.
|
||||||
|
Wire.beginTransmission(0x28); // transmit to device #94 (0x5F)
|
||||||
|
// device address is specified in datasheet
|
||||||
|
Wire.write(0x11); // sends instruction byte
|
||||||
|
Wire.write(ThreshA); // sends potentiometer value byte
|
||||||
|
Wire.endTransmission(); // stop transmitting
|
||||||
|
|
||||||
|
|
||||||
|
// Serial.println(" "+analogRead(A1));
|
||||||
|
// Serial.println("Setting Ch2");
|
||||||
|
// Serial.print(ThreshB);
|
||||||
|
|
||||||
|
//Serial.println(analogRead(A2)); //internal readback of the DREF value only, not returned to main code.
|
||||||
|
Wire.beginTransmission(I2CPot); // transmit to device #94 (0x5F)
|
||||||
|
// device address is specified in datasheet
|
||||||
|
Wire.write(0x12); // sends instruction byte
|
||||||
|
Wire.write(ThreshB); // sends potentiometer value byte
|
||||||
|
Wire.endTransmission(); // stop transmitting
|
||||||
|
// Serial.println(" "+ analogRead(A2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void ThresholdCalc(int ThreshA[1000], int ThreshB[1000]) {
|
||||||
|
//This isn't working right now, need to check the addressing and the way of setting A and B registers
|
||||||
|
// Serial.println("Test of threshold setting");
|
||||||
|
// Serial.print(ThreshA);
|
||||||
|
//Serial.println(analogRead(A1)); //internal readback of the DREF value only, not returned to main code.
|
||||||
|
// Wire.beginTransmission(0x28); // transmit to device #94 (0x5F)
|
||||||
|
// device address is specified in datasheet
|
||||||
|
// Wire.write(0x11); // sends instruction byte
|
||||||
|
// Wire.write(ThreshA); // sends potentiometer value byte
|
||||||
|
// Wire.endTransmission(); // stop transmitting
|
||||||
|
|
||||||
|
|
||||||
|
// Serial.println(" "+analogRead(A1));
|
||||||
|
// Serial.println("Setting Ch2");
|
||||||
|
// Serial.print(ThreshB);
|
||||||
|
|
||||||
|
//Serial.println(analogRead(A2)); //internal readback of the DREF value only, not returned to main code.
|
||||||
|
// Wire.beginTransmission(I2CPot); // transmit to device #94 (0x5F)
|
||||||
|
// device address is specified in datasheet
|
||||||
|
// Wire.write(0x12); // sends instruction byte
|
||||||
|
// Wire.write(ThreshB); // sends potentiometer value byte
|
||||||
|
// Wire.endTransmission(); // stop transmitting
|
||||||
|
// Serial.println(" "+ analogRead(A2));
|
||||||
|
}
|
||||||
|
|
||||||
|
void VbiasSet(int Vbias) {
|
||||||
|
byte _send = byte (Vbias);
|
||||||
|
Serial.print("Set the Vbias to ");
|
||||||
|
Serial.println(Vbias);
|
||||||
|
digitalWrite(SS_pin, LOW); // SS low
|
||||||
|
for (int i = 0; i < 8; i++) // There are 8 bits in a byte
|
||||||
|
{
|
||||||
|
digitalWrite(MOSI_pin, bitRead(_send, i-7)); // Set MOSI
|
||||||
|
digitalWrite(SCK_pin, HIGH); // SCK high
|
||||||
|
//bitWrite(_receive, i, digitalRead(MISO_pin)); // Capture MISO
|
||||||
|
digitalWrite(SCK_pin, LOW); // SCK low
|
||||||
|
}
|
||||||
|
digitalWrite(SS_pin, HIGH); // SS high again
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Loading…
Reference in a new issue