Focused on random number generation using native usb

This commit is contained in:
James Devine 2017-02-11 12:40:45 +01:00
parent 6743f674dd
commit 32c393d035
20 changed files with 604 additions and 3607 deletions

158
Accel.ino Normal file
View 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);
}

View file

@ -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;
}

View file

@ -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

View file

@ -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;
}

View file

@ -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

View file

@ -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
}
}

View file

@ -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

View file

@ -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;
}
/*********************************************************************/

View file

@ -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;
};

View file

@ -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
}

View file

@ -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

View file

@ -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
}

View file

@ -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

View file

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

View file

@ -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
View 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
View 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
}

View file

@ -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;
}
}

View file

@ -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
View 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
}