✈️ Adds barometer to imu service

This commit is contained in:
Rune Harlyk
2024-06-01 23:55:44 +02:00
committed by Rune Harlyk
parent d1567fa2dd
commit f6ca10846f
28 changed files with 12894 additions and 10318 deletions
+8 -2
View File
@@ -5,7 +5,10 @@ let imu_data = {
x: <number[]>[],
y: <number[]>[],
z: <number[]>[],
temp: <number[]>[]
imu_temp: <number[]>[],
altitude: <number[]>[],
pressure: <number[]>[],
bmp_temp: <number[]>[]
};
const maxIMUData = 100;
@@ -21,7 +24,10 @@ function createIMU() {
x: [...imu_data.x, content.x].slice(-maxIMUData),
y: [...imu_data.y, content.y].slice(-maxIMUData),
z: [...imu_data.z, content.z].slice(-maxIMUData),
temp: [...imu_data.temp, content.temp].slice(-maxIMUData)
imu_temp: [...imu_data.imu_temp, content.imu_temp].slice(-maxIMUData),
altitude: [...imu_data.altitude, content.altitude].slice(-maxIMUData),
pressure: [...imu_data.pressure, content.pressure].slice(-maxIMUData),
bmp_temp: [...imu_data.bmp_temp, content.bmp_temp].slice(-maxIMUData)
}));
}
};
+4 -1
View File
@@ -140,5 +140,8 @@ export type IMU = {
x: number;
y: number;
z: number;
temp: number;
imu_temp: number;
altitude: number;
bmp_temp: number;
pressure: number;
};
+1 -1
View File
@@ -69,7 +69,7 @@
title: 'IMU',
icon: Rotate3d,
href: '/peripherals/imu',
feature: $page.data.features.imu,
feature: $page.data.features.imu || $page.data.features.mag || $page.data.features.bmp,
}
]
},
+185 -24
View File
@@ -1,7 +1,6 @@
<script lang="ts">
import SettingsCard from "$lib/components/SettingsCard.svelte";
import Rotate3d from '~icons/mdi/rotate-3d';
import IMUSetting from './imuSetting.svelte';
import { imu } from '$lib/stores/imu';
import { Chart, registerables } from 'chart.js';
import { cubicOut } from "svelte/easing";
@@ -13,18 +12,26 @@
Chart.register(...registerables);
let heapChartElement: HTMLCanvasElement;
let heapChart: Chart;
let angleChartElement: HTMLCanvasElement;
let angleChart: Chart;
const handleImu = (data: IMU) => imu.addData(data);
let tempChartElement: HTMLCanvasElement;
let tempChart: Chart;
let altitudeChartElement: HTMLCanvasElement;
let altitudeChart: Chart;
const handleImu = (data: IMU) => {
console.log(data);
imu.addData(data);
}
onMount(() => {
socket.on('imu', handleImu);
heapChart = new Chart(heapChartElement, {
angleChart = new Chart(angleChartElement, {
type: 'line',
data: {
// labels: $imu.x,
datasets: [
{
label: 'x',
@@ -32,7 +39,7 @@
backgroundColor: daisyColor('--p', 50),
borderWidth: 2,
data: $imu.x,
yAxisID: 'x'
yAxisID: 'y'
},
{
label: 'y',
@@ -48,7 +55,7 @@
backgroundColor: daisyColor('--a', 50),
borderWidth: 2,
data: $imu.z,
yAxisID: 'z'
yAxisID: 'y'
}
]
},
@@ -100,6 +107,138 @@
}
}
});
tempChart = new Chart(tempChartElement, {
type: 'line',
data: {
datasets: [
{
label: 'IMU temperature',
borderColor: daisyColor('--p'),
backgroundColor: daisyColor('--p', 50),
borderWidth: 2,
data: $imu.imu_temp,
yAxisID: 'y'
},
{
label: 'Barometer temperature',
borderColor: daisyColor('--s'),
backgroundColor: daisyColor('--s', 50),
borderWidth: 2,
data: $imu.bmp_temp,
yAxisID: 'y'
}
]
},
options: {
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: {
display: true
},
tooltip: {
mode: 'index',
intersect: false
}
},
elements: {
point: {
radius: 1
}
},
scales: {
x: {
grid: {
color: daisyColor('--bc', 10)
},
ticks: {
color: daisyColor('--bc')
},
display: false
},
y: {
type: 'linear',
title: {
display: true,
text: 'Temperature [C°]',
color: daisyColor('--bc'),
font: {
size: 16,
weight: 'bold'
}
},
position: 'left',
min: 0,
max: 10,
grid: { color: daisyColor('--bc', 10) },
ticks: { color: daisyColor('--bc') },
border: { color: daisyColor('--bc', 10) }
}
}
}
});
altitudeChart = new Chart(altitudeChartElement, {
type: 'line',
data: {
datasets: [
{
label: 'Altitude',
borderColor: daisyColor('--p'),
backgroundColor: daisyColor('--p', 50),
borderWidth: 2,
data: $imu.altitude,
yAxisID: 'y'
}
]
},
options: {
maintainAspectRatio: false,
responsive: true,
plugins: {
legend: {
display: true
},
tooltip: {
mode: 'index',
intersect: false
}
},
elements: {
point: {
radius: 1
}
},
scales: {
x: {
grid: {
color: daisyColor('--bc', 10)
},
ticks: {
color: daisyColor('--bc')
},
display: false
},
y: {
type: 'linear',
title: {
display: true,
text: 'Altitude [M]',
color: daisyColor('--bc'),
font: {
size: 16,
weight: 'bold'
}
},
position: 'left',
min: 0,
max: 10,
grid: { color: daisyColor('--bc', 10) },
ticks: { color: daisyColor('--bc') },
border: { color: daisyColor('--bc', 10) }
}
}
}
});
setInterval(() => {
updateData(), 200;
});
@@ -110,13 +249,26 @@
})
const updateData = () => {
// heapChart.data.labels = $imu.x;
heapChart.options.scales!.y!.min = Math.min(Math.min(...$imu.x), Math.min(...$imu.y), Math.min(...$imu.z));
heapChart.options.scales!.y!.max = Math.max(Math.max(...$imu.x), Math.max(...$imu.y), Math.max(...$imu.z));
heapChart.data.datasets[0].data = $imu.x;
heapChart.data.datasets[1].data = $imu.y;
heapChart.data.datasets[2].data = $imu.z;
heapChart.update('none');
angleChart.data.labels = $imu.x;
angleChart.data.datasets[0].data = $imu.x;
angleChart.data.datasets[1].data = $imu.y;
angleChart.data.datasets[2].data = $imu.z;
angleChart.options.scales!.y!.min = Math.min(Math.min(...$imu.x), Math.min(...$imu.y), Math.min(...$imu.z)) - 1;
angleChart.options.scales!.y!.max = Math.max(Math.max(...$imu.x), Math.max(...$imu.y), Math.max(...$imu.z)) + 1;
angleChart.update('none');
tempChart.data.labels = $imu.imu_temp;
tempChart.data.datasets[0].data = $imu.imu_temp;
tempChart.data.datasets[1].data = $imu.bmp_temp;
tempChart.options.scales!.y!.min = Math.min(Math.min(...$imu.imu_temp), Math.min(...$imu.bmp_temp)) - 1;
tempChart.options.scales!.y!.max = Math.max(Math.max(...$imu.imu_temp), Math.max(...$imu.bmp_temp)) + 1;
tempChart.update('none');
altitudeChart.data.labels = $imu.imu_temp;
altitudeChart.data.datasets[0].data = $imu.altitude;
altitudeChart.options.scales!.y!.min = Math.min(Math.min(...$imu.altitude)) - 1;
altitudeChart.options.scales!.y!.max = Math.max(Math.max(...$imu.altitude)) + 1;
altitudeChart.update('none');
}
</script>
@@ -124,19 +276,28 @@
<SettingsCard collapsible={false}>
<Rotate3d slot="icon" class="lex-shrink-0 mr-2 h-6 w-6 self-end" />
<span slot="title">IMU</span>
<!-- <div class="flex flex-col">
{#if $imu.x.length > 0}
{#each Object.entries($imu) as [key, value]}
<div>{key}: {value[value.length-1]}</div>
{/each}
{/if}
</div> -->
<div class="w-full overflow-x-auto">
<div
class="flex w-full flex-col space-y-1 h-60"
transition:slide|local={{ duration: 300, easing: cubicOut }}
>
<canvas bind:this={heapChartElement} />
<canvas bind:this={angleChartElement} />
</div>
</div>
<div class="w-full overflow-x-auto">
<div
class="flex w-full flex-col space-y-1 h-60"
transition:slide|local={{ duration: 300, easing: cubicOut }}
>
<canvas bind:this={tempChartElement} />
</div>
</div>
<div class="w-full overflow-x-auto">
<div
class="flex w-full flex-col space-y-1 h-60"
transition:slide|local={{ duration: 300, easing: cubicOut }}
>
<canvas bind:this={altitudeChartElement} />
</div>
</div>
<!-- <IMUSetting /> -->
+3
View File
@@ -9,3 +9,6 @@ build_flags =
-D FT_DOWNLOAD_FIRMWARE=0
-D FT_ANALYTICS=1
-D FT_IMU=1
-D FT_MAG=1
-D FT_BMP=1
-D FT_GPS=1
@@ -0,0 +1,478 @@
/*!
* @file Adafruit_BMP085_U.cpp
*
* @mainpage Adafruit BMP085 Pressure Sensor
*
* @section intro_sec Introduction
*
* 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!
*
* @section author Author
*
* Written by Kevin Townsend for Adafruit Industries.
*
* @section license License
* 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 <math.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, when true, will use values from datasheet
/***************************************************************************
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, 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(adafruit_sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(adafruit_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 = 1100.0F; // 300..1100 hPa
sensor->min_value = 300.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;
}
@@ -0,0 +1,154 @@
/*!
* @file Adafruit_BMP085_U.h
*/
#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
/*!
* @brief BMP085 I2C address/bits
*/
#define BMP085_ADDRESS (0x77)
/*!
* @brief BMP085 I2C 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, //!< Register that contains the chip ID
BMP085_REGISTER_VERSION = 0xD1, //!< Register that contains the chip version
BMP085_REGISTER_SOFTRESET = 0xE0, //!< Register for doing a soft reset
BMP085_REGISTER_CONTROL = 0xF4, //!< Control register
BMP085_REGISTER_TEMPDATA = 0xF6, //!< Temperature data register
BMP085_REGISTER_PRESSUREDATA = 0xF6, //!< Pressure data register
BMP085_REGISTER_READTEMPCMD =
0x2E, //!< Read temperature control register value
BMP085_REGISTER_READPRESSURECMD =
0x34 //!< Read pressure control register value
};
/*!
* @brief BMP085 mode settings
*/
typedef enum {
BMP085_MODE_ULTRALOWPOWER = 0,
BMP085_MODE_STANDARD = 1,
BMP085_MODE_HIGHRES = 2,
BMP085_MODE_ULTRAHIGHRES = 3
} bmp085_mode_t;
/*=========================================================================*/
/*!
* @brief Calibration data
*/
typedef struct {
int16_t ac1; //!< R calibration coefficient (16-bits)
int16_t ac2; //!< R calibration coefficient (16-bits)
int16_t ac3; //!< R calibration coefficient (16-bits)
uint16_t ac4; //!< R calibration coefficient (16-bits)
uint16_t ac5; //!< R calibration coefficient (16-bits)
uint16_t ac6; //!< R calibration coefficient (16-bits)
int16_t b1; //!< R calibration coefficient (16-bits)
int16_t b2; //!< R calibration coefficient (16-bits)
int16_t mb; //!< R calibration coefficient (16-bits)
int16_t mc; //!< R calibration coefficient (16-bits)
int16_t md; //!< R calibration coefficient (16-bits)
} bmp085_calib_data;
/*!
* @brief Class that stores state and functions for interacting with BMP183
*/
class Adafruit_BMP085_Unified : public Adafruit_Sensor {
public:
Adafruit_BMP085_Unified(
int32_t sensorID = -1); //!< @param sensorID ID of the BMP085 sensor
/*!
* @brief Starts I2C connection
* @param mode Mode to set, ultra high-res by default
* @return Returns true if successful
*/
bool begin(bmp085_mode_t mode = BMP085_MODE_ULTRAHIGHRES);
/*!
* @brief Gets the temperature over I2C from the BMP085
* @param temp Temperature
* @return Returns the temperature
*/
void getTemperature(float *temp);
/*!
* @brief Gets the pressure over I2C from the BMP085
* @param pressure Pressure
* @return Returns the pressure
*/
void getPressure(float *pressure);
/*!
* @brief Calculates absolute pressure
* @param seaLevel Pressure at sea level
* @param atmospheric measured pressure
* @return Absolute altitude
*/
float pressureToAltitude(float seaLevel, float atmospheric);
/*!
* @brief Calculates pressure at sea level
* @param altitude Altitude
* @param atmospheric measured pressure
* @return Pressure at sea level
*/
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.
/*!
* @brief Calculates absolute pressure
* @param seaLevel Pressure at sea level
* @param atmospheric Measured pressure
* @param temp Temperature
* @return Absolute altitude
*/
float pressureToAltitude(float seaLevel, float atmospheric, float temp);
/*!
* @brief Calculates pressure at sea level
* @param altitude Altitude
* @param atmospheric measured pressure
* @param temp Temperature
* @return Pressure at sea level
*/
float seaLevelForAltitude(float altitude, float atmospheric, float temp);
/*!
* @brief Used to read the sensor
* @return Returns an event
*/
bool getEvent(sensors_event_t *);
void getSensor(adafruit_sensor_t *);
private:
int32_t computeB5(int32_t ut);
int32_t _sensorID;
};
#endif
@@ -0,0 +1,27 @@
# Adafruit Unified BMP085/BMP180 Driver (Barometric Pressure Sensor) [![Build Status](https://github.com/adafruit/Adafruit_BMP085_Unified/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BMP085_Unified/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BMP085_Unified/html/index.html)
This driver is for the Adafruit BMP085 Breakout (http://www.adafruit.com/products/391) or BMP180 breakout (http://www.adafruit.com/products/1603), and is based on Adafruit's Unified Sensor Library (Adafruit_Sensor).
## About the BMP085 / BMP180 ##
This precision sensor from Bosch is the best low-cost sensing solution for measuring barometric pressure and temperature. Because pressure changes with altitude you can also use it as an altimeter!
## What is the Adafruit Unified Sensor Library? ##
The Adafruit Unified Sensor Library ([Adafruit_Sensor](https://github.com/adafruit/Adafruit_Sensor)) provides a common interface and data type for any supported sensor. It defines some basic information about the sensor (sensor limits, etc.), and returns standard SI units of a specific type and scale for each supported sensor type.
It provides a simple abstraction layer between your application and the actual sensor HW, allowing you to drop in any comparable sensor with only one or two lines of code to change in your project (essentially the constructor since the functions to read sensor data and get information about the sensor are defined in the base Adafruit_Sensor class).
This is imporant useful for two reasons:
1.) You can use the data right away because it's already converted to SI units that you understand and can compare, rather than meaningless values like 0..1023.
2.) Because SI units are standardised in the sensor library, you can also do quick sanity checks when working with new sensors, or drop in any comparable sensor if you need better sensitivity or if a lower cost unit becomes available, etc.
Light sensors will always report units in lux, gyroscopes will always report units in rad/s, etc. ... freeing you up to focus on the data, rather than digging through the datasheet to understand what the sensor's raw numbers really mean.
## About this Driver ##
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.
@@ -0,0 +1,132 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
/* This driver uses the Adafruit unified sensor library (Adafruit_Sensor),
which provides a common 'type' for sensor data and some helper functions.
To use this driver you will also need to download the Adafruit_Sensor
library and include it in your libraries folder.
You should also assign a unique ID to this sensor for use with
the Adafruit Sensor API so that you can identify this particular
sensor in any data logs, etc. To assign a unique ID, simply
provide an appropriate value in the constructor below (12345
is used by default in this example).
Connections
===========
Connect SCL to analog 5
Connect SDA to analog 4
Connect VDD to 3.3V DC
Connect GROUND to common ground
History
=======
2013/JUN/17 - Updated altitude calculations (KTOWN)
2013/FEB/13 - First version (KTOWN)
*/
Adafruit_BMP085_Unified bmp = Adafruit_BMP085_Unified(10085);
/**************************************************************************/
/*
Displays some basic information on this sensor from the unified
sensor API sensor_t type (see Adafruit_Sensor for more information)
*/
/**************************************************************************/
void displaySensorDetails(void)
{
sensor_t sensor;
bmp.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" hPa");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" hPa");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" hPa");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
/**************************************************************************/
/*
Arduino setup function (automatically called at startup)
*/
/**************************************************************************/
void setup(void)
{
Serial.begin(9600);
Serial.println("Pressure Sensor Test"); Serial.println("");
/* Initialise the sensor */
if(!bmp.begin())
{
/* There was a problem detecting the BMP085 ... check your connections */
Serial.print("Ooops, no BMP085 detected ... Check your wiring or I2C ADDR!");
while(1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
}
/**************************************************************************/
/*
Arduino loop function, called once 'setup' is complete (your own code
should go here)
*/
/**************************************************************************/
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
bmp.getEvent(&event);
/* Display the results (barometric pressure is measure in hPa) */
if (event.pressure)
{
/* Display atmospheric pressue in hPa */
Serial.print("Pressure: ");
Serial.print(event.pressure);
Serial.println(" hPa");
/* Calculating altitude with reasonable accuracy requires pressure *
* sea level pressure for your position at the moment the data is *
* converted, as well as the ambient temperature in degress *
* celcius. If you don't have these values, a 'generic' value of *
* 1013.25 hPa can be used (defined as SENSORS_PRESSURE_SEALEVELHPA *
* in sensors.h), but this isn't ideal and will give variable *
* results from one day to the next. *
* *
* You can usually find the current SLP value by looking at weather *
* websites or from environmental information centers near any major *
* airport. *
* *
* For example, for Paris, France you can check the current mean *
* pressure and sea level at: http://bit.ly/16Au8ol */
/* First we get the current temperature from the BMP085 */
float temperature;
bmp.getTemperature(&temperature);
Serial.print("Temperature: ");
Serial.print(temperature);
Serial.println(" C");
/* Then convert the atmospheric pressure, and SLP to altitude */
/* Update this next line with the current SLP for better results */
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
Serial.print("Altitude: ");
Serial.print(bmp.pressureToAltitude(seaLevelPressure,
event.pressure));
Serial.println(" m");
Serial.println("");
}
else
{
Serial.println("Sensor error");
}
delay(1000);
}
@@ -0,0 +1,10 @@
name=Adafruit BMP085 Unified
version=1.1.3
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Unified sensor driver for Adafruit's BMP085 & BMP180 breakouts
paragraph=Unified sensor driver for Adafruit's BMP085 & BMP180 breakouts
category=Sensors
url=https://github.com/adafruit/Adafruit_BMP085_Unified
architectures=*
depends=Adafruit Unified Sensor
@@ -0,0 +1,262 @@
/*!
* @file Adafruit_HMC5883_U.cpp
*
* @mainpage Adafruit HMC5883 Unified Library
*
* @section intro_sec Introduction
*
* This is a library for the HMC5883 magnentometer/compass
*
* Designed specifically to work with the Adafruit HMC5883 Breakout
* http://www.adafruit.com/products/1746
*
* 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!
*
* @section author Author
*
* Written by Kevin Townsend for Adafruit Industries.
*
* @section license License
*
* 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_HMC5883_U.h"
static float _hmc5883_Gauss_LSB_XY = 1100.0F; // Varies with gain
static float _hmc5883_Gauss_LSB_Z = 980.0F; // Varies with gain
/***************************************************************************
MAGNETOMETER
***************************************************************************/
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Abstract away platform differences in Arduino wire library
*/
/**************************************************************************/
void Adafruit_HMC5883_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_HMC5883_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_HMC5883_Unified::read() {
// Read the magnetometer
Wire.beginTransmission((byte)HMC5883_ADDRESS_MAG);
#if ARDUINO >= 100
Wire.write(HMC5883_REGISTER_MAG_OUT_X_H_M);
#else
Wire.send(HMC5883_REGISTER_MAG_OUT_X_H_M);
#endif
Wire.endTransmission(false);
Wire.requestFrom((byte)HMC5883_ADDRESS_MAG, (byte)6, true);
// 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_HMC5883 class
*/
/**************************************************************************/
Adafruit_HMC5883_Unified::Adafruit_HMC5883_Unified(int32_t sensorID) {
_sensorID = sensorID;
}
/***************************************************************************
PUBLIC FUNCTIONS
***************************************************************************/
/**************************************************************************/
/*!
@brief Setups the HW
*/
/**************************************************************************/
bool Adafruit_HMC5883_Unified::begin() {
// Enable I2C
Wire.begin();
// Enable the magnetometer
write8(HMC5883_ADDRESS_MAG, HMC5883_REGISTER_MAG_MR_REG_M, 0x00);
// Set the gain to a known level
setMagGain(HMC5883_MAGGAIN_1_3);
return true;
}
/**************************************************************************/
/*!
@brief Sets the magnetometer's gain
*/
/**************************************************************************/
void Adafruit_HMC5883_Unified::setMagGain(hmc5883MagGain gain) {
write8(HMC5883_ADDRESS_MAG, HMC5883_REGISTER_MAG_CRB_REG_M, (byte)gain);
_magGain = gain;
switch (gain) {
case HMC5883_MAGGAIN_1_3:
_hmc5883_Gauss_LSB_XY = 1100;
_hmc5883_Gauss_LSB_Z = 980;
break;
case HMC5883_MAGGAIN_1_9:
_hmc5883_Gauss_LSB_XY = 855;
_hmc5883_Gauss_LSB_Z = 760;
break;
case HMC5883_MAGGAIN_2_5:
_hmc5883_Gauss_LSB_XY = 670;
_hmc5883_Gauss_LSB_Z = 600;
break;
case HMC5883_MAGGAIN_4_0:
_hmc5883_Gauss_LSB_XY = 450;
_hmc5883_Gauss_LSB_Z = 400;
break;
case HMC5883_MAGGAIN_4_7:
_hmc5883_Gauss_LSB_XY = 400;
_hmc5883_Gauss_LSB_Z = 255;
break;
case HMC5883_MAGGAIN_5_6:
_hmc5883_Gauss_LSB_XY = 330;
_hmc5883_Gauss_LSB_Z = 295;
break;
case HMC5883_MAGGAIN_8_1:
_hmc5883_Gauss_LSB_XY = 230;
_hmc5883_Gauss_LSB_Z = 205;
break;
}
}
/**************************************************************************/
/*!
@brief Gets the most recent sensor event
*/
/**************************************************************************/
bool Adafruit_HMC5883_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_MAGNETIC_FIELD;
event->timestamp = 0;
event->magnetic.x =
_magData.x / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
event->magnetic.y =
_magData.y / _hmc5883_Gauss_LSB_XY * SENSORS_GAUSS_TO_MICROTESLA;
event->magnetic.z =
_magData.z / _hmc5883_Gauss_LSB_Z * SENSORS_GAUSS_TO_MICROTESLA;
return true;
}
/**************************************************************************/
/*!
@brief Gets the sensor_t data
*/
/**************************************************************************/
void Adafruit_HMC5883_Unified::getSensor(adafruit_sensor_t *sensor) {
/* Clear the sensor_t object */
memset(sensor, 0, sizeof(adafruit_sensor_t));
/* Insert the sensor name in the fixed length char array */
strncpy(sensor->name, "HMC5883", 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 = 800; // 8 gauss == 800 microTesla
sensor->min_value = -800; // -8 gauss == -800 microTesla
sensor->resolution = 0.2; // 2 milligauss == 0.2 microTesla
}
@@ -0,0 +1,100 @@
/*!
* @file Adafruit_HMC5883_U.h
*/
#ifndef __HMC5883_H__
#define __HMC5883_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
/*!
* @brief I2C address/bits
*/
#define HMC5883_ADDRESS_MAG (0x3C >> 1) // 0011110x
/*!
@brief Registers
*/
typedef enum {
HMC5883_REGISTER_MAG_CRA_REG_M = 0x00,
HMC5883_REGISTER_MAG_CRB_REG_M = 0x01,
HMC5883_REGISTER_MAG_MR_REG_M = 0x02,
HMC5883_REGISTER_MAG_OUT_X_H_M = 0x03,
HMC5883_REGISTER_MAG_OUT_X_L_M = 0x04,
HMC5883_REGISTER_MAG_OUT_Z_H_M = 0x05,
HMC5883_REGISTER_MAG_OUT_Z_L_M = 0x06,
HMC5883_REGISTER_MAG_OUT_Y_H_M = 0x07,
HMC5883_REGISTER_MAG_OUT_Y_L_M = 0x08,
HMC5883_REGISTER_MAG_SR_REG_Mg = 0x09,
HMC5883_REGISTER_MAG_IRA_REG_M = 0x0A,
HMC5883_REGISTER_MAG_IRB_REG_M = 0x0B,
HMC5883_REGISTER_MAG_IRC_REG_M = 0x0C,
HMC5883_REGISTER_MAG_TEMP_OUT_H_M = 0x31,
HMC5883_REGISTER_MAG_TEMP_OUT_L_M = 0x32
} hmc5883MagRegisters_t;
/*!
* @brief Magnetometer gain settings
*/
typedef enum {
HMC5883_MAGGAIN_1_3 = 0x20, // +/- 1.3
HMC5883_MAGGAIN_1_9 = 0x40, // +/- 1.9
HMC5883_MAGGAIN_2_5 = 0x60, // +/- 2.5
HMC5883_MAGGAIN_4_0 = 0x80, // +/- 4.0
HMC5883_MAGGAIN_4_7 = 0xA0, // +/- 4.7
HMC5883_MAGGAIN_5_6 = 0xC0, // +/- 5.6
HMC5883_MAGGAIN_8_1 = 0xE0 // +/- 8.1
} hmc5883MagGain;
/*!
* @brief Internal magnetometer data type
*/
typedef struct hmc5883MagData_s {
float x; //!< Magnetometer x value
float y; //!< Magnetometer y value
float z; //!< Magnetometer z value
float orientation; //!< Magnetometer orientation
} hmc5883MagData;
/*!
* @brief Chip ID
*/
#define HMC5883_ID (0b11010100)
//! Unified sensor driver for the magnetometer ///
class Adafruit_HMC5883_Unified : public Adafruit_Sensor {
public:
/*!
* @param sensorID sensor ID, -1 by default
*/
Adafruit_HMC5883_Unified(int32_t sensorID = -1);
bool begin(void); //!< @return Returns whether connection was successful
void setMagGain(hmc5883MagGain gain); //!< @param gain Desired magnetic gain
bool
getEvent(sensors_event_t *); //!< @return Returns the most recent sensor event
void getSensor(adafruit_sensor_t *);
private:
hmc5883MagGain _magGain;
hmc5883MagData _magData; // Last read magnetometer 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);
};
#endif
@@ -0,0 +1,29 @@
# Adafruit HMC5883L Driver (3-Axis Magnetometer) [![Build Status](https://github.com/adafruit/Adafruit_HMC5883_Unified/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_HMC5883_Unified/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_HMC5883_Unified/html/index.html)
This driver is for the Adafruit HMC5883L Breakout (http://www.adafruit.com/products/1746), and is based on Adafruit's Unified Sensor Library (Adafruit_Sensor).
## About the HMC5883 ##
The HMC5883L is a digital (I2C) compass (magnetometer). The magnetometer measure magnetic force, which is useful to detect magnetic north.
More information on the HMC5883L can be found in the datasheet: http://www.adafruit.com/datasheets/HMC5883L_3-Axis_Digital_Compass_IC.pdf
## What is the Adafruit Unified Sensor Library? ##
The Adafruit Unified Sensor Library (**Adafruit_Sensor**) provides a common interface and data type for any supported sensor. It defines some basic information about the sensor (sensor limits, etc.), and returns standard SI units of a specific type and scale for each supported sensor type.
It provides a simple abstraction layer between your application and the actual sensor HW, allowing you to drop in any comparable sensor with only one or two lines of code to change in your project (essentially the constructor since the functions to read sensor data and get information about the sensor are defined in the base Adafruit_Sensor class).
This is imporant useful for two reasons:
1.) You can use the data right away because it's already converted to SI units that you understand and can compare, rather than meaningless values like 0..1023.
2.) Because SI units are standardised in the sensor library, you can also do quick sanity checks working with new sensors, or drop in any comparable sensor if you need better sensitivity or if a lower cost unit becomes available, etc.
Light sensors will always report units in lux, gyroscopes will always report units in rad/s, etc. ... freeing you up to focus on the data, rather than digging through the datasheet to understand what the sensor's raw numbers really mean.
## About this Driver ##
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.
@@ -0,0 +1,108 @@
/***************************************************************************
This is a library example for the HMC5883 magnentometer/compass
Designed specifically to work with the Adafruit HMC5883 Breakout
http://www.adafruit.com/products/1746
*** You will also need to install the Adafruit_Sensor library! ***
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 with some heading example from
Love Electronics (loveelectronics.co.uk)
This program is free software: you can redistribute it and/or modify
it under the terms of the version 3 GNU General Public License as
published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
***************************************************************************/
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_HMC5883_U.h>
/* Assign a unique ID to this sensor at the same time */
Adafruit_HMC5883_Unified mag = Adafruit_HMC5883_Unified(12345);
void displaySensorDetails(void)
{
sensor_t sensor;
mag.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" uT");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" uT");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" uT");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
void setup(void)
{
Serial.begin(9600);
Serial.println("HMC5883 Magnetometer Test"); Serial.println("");
/* Initialise the sensor */
if(!mag.begin())
{
/* There was a problem detecting the HMC5883 ... check your connections */
Serial.println("Ooops, no HMC5883 detected ... Check your wiring!");
while(1);
}
/* Display some basic information on this sensor */
displaySensorDetails();
}
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
mag.getEvent(&event);
/* Display the results (magnetic vector values are in micro-Tesla (uT)) */
Serial.print("X: "); Serial.print(event.magnetic.x); Serial.print(" ");
Serial.print("Y: "); Serial.print(event.magnetic.y); Serial.print(" ");
Serial.print("Z: "); Serial.print(event.magnetic.z); Serial.print(" ");Serial.println("uT");
// Hold the module so that Z is pointing 'up' and you can measure the heading with x&y
// Calculate heading when the magnetometer is level, then correct for signs of axis.
float heading = atan2(event.magnetic.y, event.magnetic.x);
// Once you have your heading, you must then add your 'Declination Angle', which is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Mine is: -13* 2' W, which is ~13 Degrees, or (which we need) 0.22 radians
// If you cannot find your Declination, comment out these two lines, your compass will be slightly off.
float declinationAngle = 0.22;
heading += declinationAngle;
// Correct for when signs are reversed.
if(heading < 0)
heading += 2*PI;
// Check for wrap due to addition of declination.
if(heading > 2*PI)
heading -= 2*PI;
// Convert radians to degrees for readability.
float headingDegrees = heading * 180/M_PI;
Serial.print("Heading (degrees): "); Serial.println(headingDegrees);
delay(500);
}
@@ -0,0 +1,10 @@
name=Adafruit HMC5883 Unified
version=1.2.3
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Adafruit HMC5883L 3-Axis Magnetometer Breakout library using Adafruit's Unified Sensor Library.
paragraph=Adafruit HMC5883L 3-Axis Magnetometer Breakout library using Adafruit's Unified Sensor Library.
category=Sensors
url=https://github.com/adafruit/Adafruit_HMC5883_Unified
architectures=*
depends=Adafruit Unified Sensor
@@ -0,0 +1,120 @@
#include "Adafruit_Sensor.h"
/**************************************************************************/
/*!
@brief Prints sensor information to serial console
*/
/**************************************************************************/
void Adafruit_Sensor::printSensorDetails(void) {
adafruit_sensor_t sensor;
getSensor(&sensor);
Serial.println(F("------------------------------------"));
Serial.print(F("Sensor: "));
Serial.println(sensor.name);
Serial.print(F("Type: "));
switch ((sensors_type_t)sensor.type) {
case SENSOR_TYPE_ACCELEROMETER:
Serial.print(F("Acceleration (m/s2)"));
break;
case SENSOR_TYPE_MAGNETIC_FIELD:
Serial.print(F("Magnetic (uT)"));
break;
case SENSOR_TYPE_ORIENTATION:
Serial.print(F("Orientation (degrees)"));
break;
case SENSOR_TYPE_GYROSCOPE:
Serial.print(F("Gyroscopic (rad/s)"));
break;
case SENSOR_TYPE_LIGHT:
Serial.print(F("Light (lux)"));
break;
case SENSOR_TYPE_PRESSURE:
Serial.print(F("Pressure (hPa)"));
break;
case SENSOR_TYPE_PROXIMITY:
Serial.print(F("Distance (cm)"));
break;
case SENSOR_TYPE_GRAVITY:
Serial.print(F("Gravity (m/s2)"));
break;
case SENSOR_TYPE_LINEAR_ACCELERATION:
Serial.print(F("Linear Acceleration (m/s2)"));
break;
case SENSOR_TYPE_ROTATION_VECTOR:
Serial.print(F("Rotation vector"));
break;
case SENSOR_TYPE_RELATIVE_HUMIDITY:
Serial.print(F("Relative Humidity (%)"));
break;
case SENSOR_TYPE_AMBIENT_TEMPERATURE:
Serial.print(F("Ambient Temp (C)"));
break;
case SENSOR_TYPE_OBJECT_TEMPERATURE:
Serial.print(F("Object Temp (C)"));
break;
case SENSOR_TYPE_VOLTAGE:
Serial.print(F("Voltage (V)"));
break;
case SENSOR_TYPE_CURRENT:
Serial.print(F("Current (mA)"));
break;
case SENSOR_TYPE_COLOR:
Serial.print(F("Color (RGBA)"));
break;
case SENSOR_TYPE_TVOC:
Serial.print(F("Total Volatile Organic Compounds (ppb)"));
break;
case SENSOR_TYPE_VOC_INDEX:
Serial.print(F("Volatile Organic Compounds (Index)"));
break;
case SENSOR_TYPE_NOX_INDEX:
Serial.print(F("Nitrogen Oxides (Index)"));
break;
case SENSOR_TYPE_CO2:
Serial.print(F("Carbon Dioxide (ppm)"));
break;
case SENSOR_TYPE_ECO2:
Serial.print(F("Equivalent/estimated CO2 (ppm)"));
break;
case SENSOR_TYPE_PM10_STD:
Serial.print(F("Standard Particulate Matter 1.0 (ppm)"));
break;
case SENSOR_TYPE_PM25_STD:
Serial.print(F("Standard Particulate Matter 2.5 (ppm)"));
break;
case SENSOR_TYPE_PM100_STD:
Serial.print(F("Standard Particulate Matter 10.0 (ppm)"));
break;
case SENSOR_TYPE_PM10_ENV:
Serial.print(F("Environmental Particulate Matter 1.0 (ppm)"));
break;
case SENSOR_TYPE_PM25_ENV:
Serial.print(F("Environmental Particulate Matter 2.5 (ppm)"));
break;
case SENSOR_TYPE_PM100_ENV:
Serial.print(F("Environmental Particulate Matter 10.0 (ppm)"));
break;
case SENSOR_TYPE_GAS_RESISTANCE:
Serial.print(F("Gas Resistance (ohms)"));
break;
case SENSOR_TYPE_UNITLESS_PERCENT:
Serial.print(F("Unitless Percent (%)"));
break;
case SENSOR_TYPE_ALTITUDE:
Serial.print(F("Altitude (m)"));
break;
}
Serial.println();
Serial.print(F("Driver Ver: "));
Serial.println(sensor.version);
Serial.print(F("Unique ID: "));
Serial.println(sensor.sensor_id);
Serial.print(F("Min Value: "));
Serial.println(sensor.min_value);
Serial.print(F("Max Value: "));
Serial.println(sensor.max_value);
Serial.print(F("Resolution: "));
Serial.println(sensor.resolution);
Serial.println(F("------------------------------------\n"));
}
@@ -0,0 +1,224 @@
/*
* 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
#ifndef ARDUINO
#include <stdint.h>
#elif ARDUINO >= 100
#include "Arduino.h"
#include "Print.h"
#else
#include "WProgram.h"
#endif
/* 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_RADS_TO_DPS \
(57.29577793F) /**< Rad/s to degrees/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_OBJECT_TEMPERATURE = (14),
SENSOR_TYPE_VOLTAGE = (15),
SENSOR_TYPE_CURRENT = (16),
SENSOR_TYPE_COLOR = (17),
SENSOR_TYPE_TVOC = (18),
SENSOR_TYPE_VOC_INDEX = (19),
SENSOR_TYPE_NOX_INDEX = (20),
SENSOR_TYPE_CO2 = (21),
SENSOR_TYPE_ECO2 = (22),
SENSOR_TYPE_PM10_STD = (23),
SENSOR_TYPE_PM25_STD = (24),
SENSOR_TYPE_PM100_STD = (25),
SENSOR_TYPE_PM10_ENV = (26),
SENSOR_TYPE_PM25_ENV = (27),
SENSOR_TYPE_PM100_ENV = (28),
SENSOR_TYPE_GAS_RESISTANCE = (29),
SENSOR_TYPE_UNITLESS_PERCENT = (30),
SENSOR_TYPE_ALTITUDE = (31)
} sensors_type_t;
/** struct sensors_vec_s is used to return a vector in a common format. */
typedef struct {
union {
float v[3]; ///< 3D vector elements
struct {
float x; ///< X component of vector
float y; ///< Y component of vector
float z; ///< Z component of vector
}; ///< Struct for holding XYZ component
/* Orientation sensors */
struct {
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X
axis'). Roll is positive and increasing when moving
downward. -90 degrees <= roll <= 90 degrees */
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y
axis'). Pitch is positive and increasing when moving
upwards. -180 degrees <= pitch <= 180 degrees) */
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 degrees */
}; ///< Struct for holding roll/pitch/heading
}; ///< Union that can hold 3D vector array, XYZ components or
///< roll/pitch/heading
int8_t status; ///< Status byte
uint8_t reserved[3]; ///< Reserved
} sensors_vec_t;
/** struct sensors_color_s is used to return color data in a common format. */
typedef struct {
union {
float c[3]; ///< Raw 3-element data
/* RGB color space */
struct {
float r; /**< Red component */
float g; /**< Green component */
float b; /**< Blue component */
}; ///< RGB data in floating point notation
}; ///< Union of various ways to describe RGB colorspace
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]; ///< Raw data */
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) */
float tvoc; /**< Total Volatile Organic Compounds, in ppb */
float voc_index; /**< VOC (Volatile Organic Compound) index where 100 is
normal (unitless) */
float nox_index; /**< NOx (Nitrogen Oxides) index where 100 is normal
(unitless) */
float CO2; /**< Measured CO2 in parts per million (ppm) */
float eCO2; /**< equivalent/estimated CO2 in parts per million (ppm
estimated from some other measurement) */
float pm10_std; /**< Standard Particulate Matter <=1.0 in parts per million
(ppm) */
float pm25_std; /**< Standard Particulate Matter <=2.5 in parts per million
(ppm) */
float pm100_std; /**< Standard Particulate Matter <=10.0 in parts per
million (ppm) */
float pm10_env; /**< Environmental Particulate Matter <=1.0 in parts per
million (ppm) */
float pm25_env; /**< Environmental Particulate Matter <=2.5 in parts per
million (ppm) */
float pm100_env; /**< Environmental Particulate Matter <=10.0 in parts per
million (ppm) */
float gas_resistance; /**< Proportional to the amount of VOC particles in
the air (Ohms) */
float unitless_percent; /**<Percentage, unit-less (%) */
sensors_color_t color; /**< color in RGB component values */
float altitude; /**< Distance between a reference datum and a point or
object, in meters. */
}; ///< Union for the wide ranges of data we can carry
} 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 */
} adafruit_sensor_t;
/** @brief Common sensor interface to unify various sensors.
* Intentionally modeled after sensors.h in the Android API:
* https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h
*/
class Adafruit_Sensor {
public:
// Constructor(s)
Adafruit_Sensor() {}
virtual ~Adafruit_Sensor() {}
// These must be defined by the subclass
/*! @brief Whether we should automatically change the range (if possible) for
higher precision
@param enabled True if we will try to autorange */
virtual void enableAutoRange(bool enabled) {
(void)enabled; /* suppress unused warning */
};
/*! @brief Get the latest sensor event
@returns True if able to fetch an event */
virtual bool getEvent(sensors_event_t *) = 0;
/*! @brief Get info about the sensor itself */
virtual void getSensor(adafruit_sensor_t *) = 0;
void printSensorDetails(void);
};
#endif
@@ -0,0 +1,202 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
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
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.
@@ -0,0 +1,271 @@
# Adafruit Unified Sensor Driver #
Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing.
One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road.
Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement.
By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse.
The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire.
## Unified Sensor Drivers ##
The following drivers are based on the Adafruit Unified Sensor Driver:
**Accelerometers**
- [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345)
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
- [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library)
**Gyroscope**
- [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U)
**Light**
- [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561)
- [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library)
**Magnetometers**
- [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC)
- [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified)
**Barometric Pressure**
- [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified)
- [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library)
**Humidity & Temperature**
- [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library)
**Humidity, Temperature, & Barometric Pressure**
- [Adafruit_BME280_Library](https://github.com/adafruit/Adafruit_BME280_Library/)
**Orientation**
- [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055)
**All in one device**
- [Adafruit_LSM9DS0](https://github.com/adafruit/Adafruit_LSM9DS0_Library) (accelerometer, gyroscope, magnetometer)
- [Adafruit_LSM9DS1](https://github.com/adafruit/Adafruit_LSM9DS1/) (accelerometer, gyroscope, magnetometer)
## How Does it Work? ##
Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values:
## Sensor Types (`sensors_type_t`)
These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc.
```c++
/** Sensor types */
typedef enum
{
SENSOR_TYPE_ACCELEROMETER = (1),
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),
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),
SENSOR_TYPE_TVOC = (18),
SENSOR_TYPE_VOC_INDEX = (19),
SENSOR_TYPE_NOX_INDEX = (20),
SENSOR_TYPE_CO2 = (21),
SENSOR_TYPE_ECO2 = (22),
SENSOR_TYPE_PM10_STD = (23),
SENSOR_TYPE_PM25_STD = (24),
SENSOR_TYPE_PM100_STD = (25),
SENSOR_TYPE_PM10_ENV = (26),
SENSOR_TYPE_PM25_ENV = (27),
SENSOR_TYPE_PM100_ENV = (28),
SENSOR_TYPE_GAS_RESISTANCE = (29),
SENSOR_TYPE_UNITLESS_PERCENT = (30),
SENSOR_TYPE_ALTITUDE = (31),
} sensors_type_t;
```
## Sensor Details (`sensor_t`)
This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer.
```c++
/* Sensor details (40 bytes) */
/** struct sensor_s is used to describe basic information about a specific sensor. */
typedef struct
{
char name[12];
int32_t version;
int32_t sensor_id;
int32_t type;
float max_value;
float min_value;
float resolution;
int32_t min_delay;
} sensor_t;
```
The individual fields are intended to be used as follows:
- **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2")
- **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network
- **type**: The sensor type, based on **sensors\_type\_t** in sensors.h
- **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit)
- **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit)
- **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit)
- **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate
## Sensor Data/Events (`sensors_event_t`)
This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales.
```c++
/* 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;
int32_t sensor_id;
int32_t type;
int32_t reserved0;
int32_t timestamp;
union
{
float data[4];
sensors_vec_t acceleration;
sensors_vec_t magnetic;
sensors_vec_t orientation;
sensors_vec_t gyro;
float temperature;
float distance;
float light;
float pressure;
float relative_humidity;
float current;
float voltage;
float tvoc;
float voc_index;
float nox_index;
float CO2,
float eCO2,
float pm10_std,
float pm25_std,
float pm100_std,
float pm10_env,
float pm25_env,
float pm100_env,
float gas_resistance,
float unitless_percent,
float altitude,
sensors_color_t color;
};
} sensors_event_t;
```
It includes the following fields:
- **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future
- **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!)
- **type**: the sensor type, based on **sensors\_type\_t** in sensors.h
- **timestamp**: time in milliseconds when the sensor value was read
- **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below)
## Required Functions
In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions:
```c++
bool getEvent(sensors_event_t*);
```
Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data.
```c++
void getSensor(sensor_t*);
```
Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc.
## Standardised SI values for `sensors_event_t`
A key part of the abstraction layer is the standardization of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales:
- **acceleration**: values are in **meter per second per second** (m/s^2)
- **magnetic**: values are in **micro-Tesla** (uT)
- **orientation**: values are in **degrees**
- **gyro**: values are in **rad/s**
- **temperature**: values in **degrees centigrade** (Celsius)
- **distance**: values are in **centimeters**
- **light**: values are in **SI lux** units
- **pressure**: values are in **hectopascal** (hPa)
- **relative\_humidity**: values are in **percent**
- **current**: values are in **milliamps** (mA)
- **voltage**: values are in **volts** (V)
- **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format
- **tvoc**: values are in **parts per billion** (ppb)
- **voc_index**: values are an **index** from 1-500 with 100 being normal
- **nox_index**: values are an **index** from 1-500 with 100 being normal
- **CO2**: values are in **parts per million** (ppm)
- **eCO2**: values are in **parts per million** (ppm)
- **pm10_std**: values are in **parts per million** (ppm)
- **pm25_std**: values are in **parts per million** (ppm)
- **pm100_std**: values are in **parts per million** (ppm)
- **pm10_env**: values are in **parts per million** (ppm)
- **pm25_env**: values are in **parts per million** (ppm)
- **pm100_env**: values are in **parts per million** (ppm)
- **gas_resistance**: values are in **ohms**
- **unitless_percent**: values are in **%**
- **altitude**: values are in **meters** (m)
## The Unified Driver Abstraction Layer in Practice ##
Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created.
Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardized way of interrogating a sensor about its specific capabilities (via sensor\_t).
An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below:
```c++
Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345);
...
/* Get a new sensor event */
sensors_event_t event;
tsl.getEvent(&event);
/* Display the results (light is measured in lux) */
if (event.light)
{
Serial.print(event.light); Serial.println(" lux");
}
else
{
/* If event.light = 0 lux the sensor is probably saturated
and no reliable data could be generated! */
Serial.println("Sensor overload");
}
```
Similarly, we can get the basic technical capabilities of this sensor with the following code:
```c++
sensor_t sensor;
sensor_t sensor;
tsl.getSensor(&sensor);
/* Display the sensor details */
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux");
Serial.println("------------------------------------");
Serial.println("");
```
@@ -0,0 +1,153 @@
#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_ADXL343.h>
/* Assign a unique ID to this sensor at the same time */
/* Uncomment following line for default Wire bus */
Adafruit_ADXL343 accel = Adafruit_ADXL343(12345);
/* NeoTrellis M4, etc. */
/* Uncomment following line for Wire1 bus */
//Adafruit_ADXL343 accel = Adafruit_ADXL343(12345, &Wire1);
void displaySensorDetails(void)
{
adafruit_sensor_t sensor;
accel.getSensor(&sensor);
Serial.println("------------------------------------");
Serial.print ("Sensor: "); Serial.println(sensor.name);
Serial.print ("Driver Ver: "); Serial.println(sensor.version);
Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id);
Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2");
Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2");
Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2");
Serial.println("------------------------------------");
Serial.println("");
delay(500);
}
void displayDataRate(void)
{
Serial.print ("Data Rate: ");
switch(accel.getDataRate())
{
case ADXL343_DATARATE_3200_HZ:
Serial.print ("3200 ");
break;
case ADXL343_DATARATE_1600_HZ:
Serial.print ("1600 ");
break;
case ADXL343_DATARATE_800_HZ:
Serial.print ("800 ");
break;
case ADXL343_DATARATE_400_HZ:
Serial.print ("400 ");
break;
case ADXL343_DATARATE_200_HZ:
Serial.print ("200 ");
break;
case ADXL343_DATARATE_100_HZ:
Serial.print ("100 ");
break;
case ADXL343_DATARATE_50_HZ:
Serial.print ("50 ");
break;
case ADXL343_DATARATE_25_HZ:
Serial.print ("25 ");
break;
case ADXL343_DATARATE_12_5_HZ:
Serial.print ("12.5 ");
break;
case ADXL343_DATARATE_6_25HZ:
Serial.print ("6.25 ");
break;
case ADXL343_DATARATE_3_13_HZ:
Serial.print ("3.13 ");
break;
case ADXL343_DATARATE_1_56_HZ:
Serial.print ("1.56 ");
break;
case ADXL343_DATARATE_0_78_HZ:
Serial.print ("0.78 ");
break;
case ADXL343_DATARATE_0_39_HZ:
Serial.print ("0.39 ");
break;
case ADXL343_DATARATE_0_20_HZ:
Serial.print ("0.20 ");
break;
case ADXL343_DATARATE_0_10_HZ:
Serial.print ("0.10 ");
break;
default:
Serial.print ("???? ");
break;
}
Serial.println(" Hz");
}
void displayRange(void)
{
Serial.print ("Range: +/- ");
switch(accel.getRange())
{
case ADXL343_RANGE_16_G:
Serial.print ("16 ");
break;
case ADXL343_RANGE_8_G:
Serial.print ("8 ");
break;
case ADXL343_RANGE_4_G:
Serial.print ("4 ");
break;
case ADXL343_RANGE_2_G:
Serial.print ("2 ");
break;
default:
Serial.print ("?? ");
break;
}
Serial.println(" g");
}
void setup(void)
{
Serial.begin(9600);
while (!Serial);
Serial.println("Accelerometer Test"); Serial.println("");
/* Initialise the sensor */
if(!accel.begin())
{
/* There was a problem detecting the ADXL343 ... check your connections */
Serial.println("Ooops, no ADXL343 detected ... Check your wiring!");
while(1);
}
/* Set the range to whatever is appropriate for your project */
accel.setRange(ADXL343_RANGE_16_G);
// accel.setRange(ADXL343_RANGE_8_G);
// accel.setRange(ADXL343_RANGE_4_G);
// accel.setRange(ADXL343_RANGE_2_G);
/* Display some basic information on this sensor */
displaySensorDetails();
displayDataRate();
displayRange();
Serial.println("");
}
void loop(void)
{
/* Get a new sensor event */
sensors_event_t event;
accel.getEvent(&event);
/* Display the results (acceleration is measured in m/s^2) */
Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print(" ");
Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" ");
Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print(" ");Serial.println("m/s^2 ");
delay(500);
}
@@ -0,0 +1,11 @@
name=Adafruit Unified Sensor
version=1.1.14
author=Adafruit <info@adafruit.com>
maintainer=Adafruit <info@adafruit.com>
sentence=Required for all Adafruit Unified Sensor based libraries.
paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries.
category=Sensors
url=https://github.com/adafruit/Adafruit_Sensor
architectures=*
includes=Adafruit_Sensor.h
+1 -1
View File
@@ -91,7 +91,7 @@ void ESP32SvelteKit::begin() {
void ESP32SvelteKit::setupServer() {
_server->config.max_uri_handlers = _numberEndpoints;
_server->listen(100);
_server->listen(80);
#ifdef EMBED_WWW
ESP_LOGV("ESP32SvelteKit",
+9
View File
@@ -67,4 +67,13 @@
#define FT_IMU 1
#endif
// ESP32 magnetometer off by default
#ifndef FT_MAG
#define FT_MAG 0
#endif
// ESP32 barometer off by default
#ifndef FT_BMP
#define FT_BMP 0
#endif
#endif
@@ -32,6 +32,8 @@ void FeaturesService::begin() {
root["analytics"] = FT_ANALYTICS;
root["camera"] = FT_CAMERA;
root["imu"] = FT_IMU;
root["mag"] = FT_MAG;
root["bmp"] = FT_BMP;
root["firmware_version"] = APP_VERSION;
root["firmware_name"] = APP_NAME;
root["firmware_built_target"] = BUILD_TARGET;
+107 -13
View File
@@ -1,29 +1,59 @@
#pragma once
#include <MPU6050_light.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BMP085_U.h>
#include <Adafruit_HMC5883_U.h>
#include <ArduinoJson.h>
#include <EventSocket.h>
#define IMU_INTERVAL 200
#define MAX_ESP_IMU_SIZE 250
#define IMU_INTERVAL 500
#define MAX_ESP_IMU_SIZE 500
#define EVENT_IMU "imu"
class IMUService
{
public:
IMUService(EventSocket *socket) : _socket(socket), _imu(Wire) {};
IMUService(EventSocket *socket)
:
#if FT_ENABLED(FT_IMU)
_imu(Wire),
#endif
#if FT_ENABLED(FT_MAG)
_mag(12345),
#endif
#if FT_ENABLED(FT_BMP)
_bmp(10085),
#endif
_socket(socket)
{};
void begin()
{
_socket->registerEvent(EVENT_IMU);
#if FT_ENABLED(FT_IMU)
byte status = _imu.begin();
imu_success = status == 0;
if(status != 0) {
ESP_LOGE("IMUService", "MPU initialize failed: %d", status);
}
_socket->registerEvent(EVENT_IMU);
calibrate();
#endif
#if FT_ENABLED(FT_MAG)
mag_success = _mag.begin();
if(!mag_success) {
ESP_LOGE("IMUService", "MAG initialize failed");
}
#endif
#if FT_ENABLED(FT_BMP)
bmp_success = _bmp.begin();
if(!bmp_success) {
ESP_LOGE("IMUService", "BMP initialize failed");
}
#endif
};
#if FT_ENABLED(FT_IMU)
bool isIMUSuccess() {
return imu_success;
}
@@ -37,11 +67,11 @@ public:
}
float getAngleY() {
return imu_success ? _imu.getAngleX() : -1;
return imu_success ? _imu.getAngleY() : -1;
}
float getAngleZ() {
return imu_success ? _imu.getAngleZ() : -1;
return imu_success ? _imu.getGyroZ() : -1;
}
void calibrate() {
@@ -49,6 +79,45 @@ public:
_imu.calcOffsets(true, true);
}
}
#endif
#if FT_ENABLED(FT_MAG)
float getHeading() {
sensors_event_t event;
_mag.getEvent(&event);
float heading = atan2(event.magnetic.y, event.magnetic.x);
float declinationAngle = 0.22;
heading += declinationAngle;
if(heading < 0) heading += 2 * PI;
if(heading > 2 * PI) heading -= 2 * PI;
return heading * 180/M_PI;
}
#endif
#if FT_ENABLED(FT_BMP)
bool isBMPSuccess() {
return bmp_success;
}
float getAltitude() {
sensors_event_t event;
_bmp.getEvent(&event);
float seaLevelPressure = SENSORS_PRESSURE_SEALEVELHPA;
return bmp_success && event.pressure ? _bmp.pressureToAltitude(seaLevelPressure, event.pressure) : -1;
}
float getPressure() {
sensors_event_t event;
_bmp.getEvent(&event);
return bmp_success && event.pressure ? event.pressure : -1;
}
float getTemperature() {
float temperature;
_bmp.getTemperature(&temperature);
return bmp_success ? temperature : -1;
}
#endif
double round2(double value) {
return (int)(value * 100 + 0.5) / 100.0;
@@ -69,22 +138,47 @@ protected:
JsonDocument doc;
void updateImu() {
_imu.update();
doc.clear();
doc["x"] = round2(getAngleX());
doc["y"] = round2(getAngleY());
doc["z"] = round2(getAngleZ());
doc["temp"] = round2(getTemp());
#if FT_ENABLED(FT_IMU)
if (imu_success){
_imu.update();
doc["x"] = round2(getAngleX());
doc["y"] = round2(getAngleY());
doc["z"] = round2(getAngleZ());
doc["imu_temp"] = round2(getTemp());
}
#endif
#if FT_ENABLED(FT_MAG)
if (mag_success) {
doc["heading"] = round2(getHeading());
}
#endif
#if FT_ENABLED(FT_BMP)
if (bmp_success) {
doc["pressure"] = round2(getPressure());
doc["altitude"] = round2(getAltitude());
doc["bmp_temp"] = round2(getTemperature());
}
#endif
serializeJson(doc, message);
_socket->emit(EVENT_IMU, message);
}
private:
#if FT_ENABLED(FT_IMU)
MPU6050 _imu;
bool imu_success {false};
#endif
#if FT_ENABLED(FT_MAG)
Adafruit_HMC5883_Unified _mag;
bool mag_success {false};
#endif
#if FT_ENABLED(FT_BMP)
Adafruit_BMP085_Unified _bmp;
bool bmp_success {false};
#endif
EventSocket *_socket;
unsigned long _lastUpdate {0};
unsigned long _updateInterval {IMU_INTERVAL};
bool imu_success {false};
char message[MAX_ESP_IMU_SIZE];
};
File diff suppressed because it is too large Load Diff
-3
View File
@@ -44,13 +44,10 @@ lib_deps =
adafruit/Adafruit GFX Library@^1.11.5
adafruit/Adafruit BusIO@^1.9.3
adafruit/Adafruit PWM Servo Driver Library@^2.4.1
;adafruit/Adafruit HMC5883 Unified@^1.2.1
SPI
; thomasfredericks/Bounce2@ ^2.7.0
; adafruit/Adafruit ADS1X15@^2.4.0
; adafruit/Adafruit Unified Sensor@^1.1.11
; plageoj/UrlEncode@ ^1.0.1
; board_build.partitions = config/no_oat.csv
extra_scripts =
pre:scripts/pre_build.py
pre:scripts/build_app.py
+1 -1
View File
@@ -5,7 +5,7 @@
DRAM_ATTR PsychicHttpServer server;
DRAM_ATTR ESP32SvelteKit spot(&server, 120);
DRAM_ATTR ESP32SvelteKit spot(&server, 125);
void setup()
{