Update firmware libraries

This commit is contained in:
Florian Eitel 2019-08-03 20:34:17 +02:00
parent 92908452fc
commit f4139b27c8
No known key found for this signature in database
GPG key ID: 9987EAFEF6F686BB
19 changed files with 1968 additions and 1585 deletions

View file

@ -1,94 +1,96 @@
/**************************************************************************/
/*! /*!
@file Adafruit_APDS9960.cpp * @file Adafruit_APDS9960.cpp
@author Ladyada, Dean Miller (Adafruit Industries) *
* @mainpage Adafruit APDS9960 Proximity, Light, RGB, and Gesture Sensor
@section LICENSE *
* @section author Author
Software License Agreement (BSD License) *
* Ladyada, Dean Miller (Adafruit Industries)
Copyright (c) 2017, Adafruit Industries *
All rights reserved. * @section license License
*
Redistribution and use in source and binary forms, with or without * Software License Agreement (BSD License)
modification, are permitted provided that the following conditions are met: *
1. Redistributions of source code must retain the above copyright * Copyright (c) 2017, Adafruit Industries
notice, this list of conditions and the following disclaimer. * All rights reserved.
2. Redistributions in binary form must reproduce the above copyright *
notice, this list of conditions and the following disclaimer in the * Redistribution and use in source and binary forms, with or without
documentation and/or other materials provided with the distribution. * modification, are permitted provided that the following conditions are met:
3. Neither the name of the copyright holders nor the * 1. Redistributions of source code must retain the above copyright
names of its contributors may be used to endorse or promote products * notice, this list of conditions and the following disclaimer.
derived from this software without specific prior written permission. * 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY * documentation and/or other materials provided with the distribution.
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * 3. Neither the name of the copyright holders nor the
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * names of its contributors may be used to endorse or promote products
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY * derived from this software without specific prior written permission.
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES *
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**************************************************************************/
#ifdef __AVR #ifdef __AVR
#include <avr/pgmspace.h> #include <avr/pgmspace.h>
#elif defined(ESP8266) #elif defined(ESP8266)
#include <pgmspace.h> #include <pgmspace.h>
#endif #endif
#include <stdlib.h>
#include <math.h> #include <math.h>
#include <stdlib.h>
#include "Adafruit_APDS9960.h" #include "Adafruit_APDS9960.h"
/*========================================================================*/
/* PRIVATE FUNCTIONS */
/*========================================================================*/
/**************************************************************************/
/*! /*!
@brief Implements missing powf function * @brief Implements missing powf function
* @param x
* Base number
* @param y
* Exponent
* @return x raised to the power of y
*/ */
/**************************************************************************/ float powf(const float x, const float y) {
float powf(const float x, const float y)
{
return (float)(pow((double)x, (double)y)); return (float)(pow((double)x, (double)y));
} }
/**************************************************************************/
/*! /*!
Enables the device * @brief Enables the device
Disables the device (putting it in lower power sleep mode) * Disables the device (putting it in lower power sleep mode)
* @param en
* Enable (True/False)
*/ */
/**************************************************************************/ void Adafruit_APDS9960::enable(boolean en) {
void Adafruit_APDS9960::enable(boolean en)
{
_enable.PON = en; _enable.PON = en;
this->write8(APDS9960_ENABLE, _enable.get()); this->write8(APDS9960_ENABLE, _enable.get());
} }
/*========================================================================*/
/* PUBLIC FUNCTIONS */
/*========================================================================*/
/**************************************************************************/
/*! /*!
Initializes I2C and configures the sensor (call this function before * @brief Initializes I2C and configures the sensor
doing anything else) * @param iTimeMS
* Integration time
* @param aGain
* Gain
* @param addr
* I2C address
* @param *theWire
* Wire object
* @return True if initialization was successful, otherwise false.
*/ */
/**************************************************************************/ boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain,
boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, uint8_t addr) uint8_t addr, TwoWire *theWire) {
{ _wire = theWire;
_i2c_init(); _i2c_init();
_i2caddr = addr; _i2caddr = addr;
/* Make sure we're actually connected */ /* Make sure we're actually connected */
uint8_t x = read8(APDS9960_ID); uint8_t x = read8(APDS9960_ID);
if (x != 0xAB) if (x != 0xAB) {
{
return false; return false;
} }
@ -125,28 +127,32 @@ boolean Adafruit_APDS9960::begin(uint16_t iTimeMS, apds9960AGain_t aGain, uint8_
return true; return true;
} }
/**************************************************************************/
/*! /*!
Sets the integration time for the ADC of the APDS9960, in millis * @brief Sets the integration time for the ADC of the APDS9960, in millis
* @param iTimeMS
* Integration time
*/ */
/**************************************************************************/ void Adafruit_APDS9960::setADCIntegrationTime(uint16_t iTimeMS) {
void Adafruit_APDS9960::setADCIntegrationTime(uint16_t iTimeMS)
{
float temp; float temp;
// convert ms into 2.78ms increments // convert ms into 2.78ms increments
temp = iTimeMS; temp = iTimeMS;
temp /= 2.78; temp /= 2.78;
temp = 256 - temp; temp = 256 - temp;
if (temp > 255) temp = 255; if (temp > 255)
if (temp < 0) temp = 0; temp = 255;
if (temp < 0)
temp = 0;
/* Update the timing register */ /* Update the timing register */
write8(APDS9960_ATIME, (uint8_t)temp); write8(APDS9960_ATIME, (uint8_t)temp);
} }
float Adafruit_APDS9960::getADCIntegrationTime(void) /*!
{ * @brief Returns the integration time for the ADC of the APDS9960, in millis
* @return Integration time
*/
float Adafruit_APDS9960::getADCIntegrationTime() {
float temp; float temp;
temp = read8(APDS9960_ATIME); temp = read8(APDS9960_ATIME);
@ -157,46 +163,59 @@ float Adafruit_APDS9960::getADCIntegrationTime(void)
return temp; return temp;
} }
/**************************************************************************/
/*! /*!
Adjusts the color/ALS gain on the APDS9960 (adjusts the sensitivity to light) * @brief Adjusts the color/ALS gain on the APDS9960 (adjusts the sensitivity
* to light)
* @param aGain
* Gain
*/ */
/**************************************************************************/ void Adafruit_APDS9960::setADCGain(apds9960AGain_t aGain) {
void Adafruit_APDS9960::setADCGain(apds9960AGain_t aGain)
{
_control.AGAIN = aGain; _control.AGAIN = aGain;
/* Update the timing register */ /* Update the timing register */
write8(APDS9960_CONTROL, _control.get()); write8(APDS9960_CONTROL, _control.get());
} }
apds9960AGain_t Adafruit_APDS9960::getADCGain(void) /*!
{ * @brief Returns the ADC gain
* @return ADC gain
*/
apds9960AGain_t Adafruit_APDS9960::getADCGain() {
return (apds9960AGain_t)(read8(APDS9960_CONTROL) & 0x03); return (apds9960AGain_t)(read8(APDS9960_CONTROL) & 0x03);
} }
/**************************************************************************/
/*! /*!
Adjusts the Proximity gain on the APDS9960 * @brief Adjusts the Proximity gain on the APDS9960
* @param pGain
* Gain
*/ */
/**************************************************************************/ void Adafruit_APDS9960::setProxGain(apds9960PGain_t pGain) {
void Adafruit_APDS9960::setProxGain(apds9960PGain_t pGain)
{
_control.PGAIN = pGain; _control.PGAIN = pGain;
/* Update the timing register */ /* Update the timing register */
write8(APDS9960_CONTROL, _control.get()); write8(APDS9960_CONTROL, _control.get());
} }
apds9960PGain_t Adafruit_APDS9960::getProxGain(void) /*!
{ * @brief Returns the Proximity gain on the APDS9960
* @return Proxmity gain
*/
apds9960PGain_t Adafruit_APDS9960::getProxGain() {
return (apds9960PGain_t)(read8(APDS9960_CONTROL) & 0x0C); return (apds9960PGain_t)(read8(APDS9960_CONTROL) & 0x0C);
} }
/*!
* @brief Sets number of proxmity pulses
* @param pLen
* Pulse Length
* @param pulses
* Number of pulses
*/
void Adafruit_APDS9960::setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses) { void Adafruit_APDS9960::setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses) {
if (pulses < 1) pulses = 1; if (pulses < 1)
if (pulses > 64) pulses = 64; pulses = 1;
if (pulses > 64)
pulses = 64;
pulses--; pulses--;
_ppulse.PPLEN = pLen; _ppulse.PPLEN = pLen;
@ -205,99 +224,147 @@ void Adafruit_APDS9960::setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses) {
write8(APDS9960_PPULSE, _ppulse.get()); write8(APDS9960_PPULSE, _ppulse.get());
} }
/**************************************************************************/
/*! /*!
Enable proximity readings on APDS9960 * @brief Enable proximity readings on APDS9960
* @param en
* Enable (True/False)
*/ */
/**************************************************************************/ void Adafruit_APDS9960::enableProximity(boolean en) {
void Adafruit_APDS9960::enableProximity(boolean en)
{
_enable.PEN = en; _enable.PEN = en;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
} }
/*!
* @brief Enable proximity interrupts
*/
void Adafruit_APDS9960::enableProximityInterrupt() { void Adafruit_APDS9960::enableProximityInterrupt() {
_enable.PIEN = 1; _enable.PIEN = 1;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
clearInterrupt(); clearInterrupt();
} }
/*!
* @brief Disable proximity interrupts
*/
void Adafruit_APDS9960::disableProximityInterrupt() { void Adafruit_APDS9960::disableProximityInterrupt() {
_enable.PIEN = 0; _enable.PIEN = 0;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
} }
void Adafruit_APDS9960::setProximityInterruptThreshold(uint8_t low, uint8_t high, uint8_t persistance){ /*!
* @brief Set proxmity interrupt thresholds
* @param low
* Low threshold
* @param high
* High threshold
* @param persistance
* Persistance
*/
void Adafruit_APDS9960::setProximityInterruptThreshold(uint8_t low,
uint8_t high,
uint8_t persistance) {
write8(APDS9960_PILT, low); write8(APDS9960_PILT, low);
write8(APDS9960_PIHT, high); write8(APDS9960_PIHT, high);
if (persistance > 7) persistance = 7; if (persistance > 7)
persistance = 7;
_pers.PPERS = persistance; _pers.PPERS = persistance;
write8(APDS9960_PERS, _pers.get()); write8(APDS9960_PERS, _pers.get());
} }
bool Adafruit_APDS9960::getProximityInterrupt() /*!
{ * @brief Returns proxmity interrupt status
* @return True if enabled, false otherwise.
*/
bool Adafruit_APDS9960::getProximityInterrupt() {
_status.set(this->read8(APDS9960_STATUS)); _status.set(this->read8(APDS9960_STATUS));
return _status.PINT; return _status.PINT;
}; };
/**************************************************************************/
/*! /*!
Read proximity data * @brief Read proximity data
* @return Proximity
*/ */
/**************************************************************************/ uint8_t Adafruit_APDS9960::readProximity() { return read8(APDS9960_PDATA); }
uint8_t Adafruit_APDS9960::readProximity(void)
{
return read8(APDS9960_PDATA);
}
/*!
bool Adafruit_APDS9960::gestureValid() * @brief Returns validity status of a gesture
{ * @return Status (True/False)
*/
bool Adafruit_APDS9960::gestureValid() {
_gstatus.set(this->read8(APDS9960_GSTATUS)); _gstatus.set(this->read8(APDS9960_GSTATUS));
return _gstatus.GVALID; return _gstatus.GVALID;
} }
void Adafruit_APDS9960::setGestureDimensions(uint8_t dims) /*!
{ * @brief Sets gesture dimensions
* @param dims
* Dimensions (APDS9960_DIMENSIONS_ALL, APDS9960_DIMENSIONS_UP_DOWM,
* APDS9960_DIMENSIONS_UP_DOWN, APGS9960_DIMENSIONS_LEFT_RIGHT)
*/
void Adafruit_APDS9960::setGestureDimensions(uint8_t dims) {
_gconf3.GDIMS = dims; _gconf3.GDIMS = dims;
this->write8(APDS9960_GCONF3, _gconf3.get()); this->write8(APDS9960_GCONF3, _gconf3.get());
} }
void Adafruit_APDS9960::setGestureFIFOThreshold(uint8_t thresh) /*!
{ * @brief Sets gesture FIFO Threshold
* @param thresh
* Threshold (APDS9960_GFIFO_1, APDS9960_GFIFO_4, APDS9960_GFIFO_8,
* APDS9960_GFIFO_16)
*/
void Adafruit_APDS9960::setGestureFIFOThreshold(uint8_t thresh) {
_gconf1.GFIFOTH = thresh; _gconf1.GFIFOTH = thresh;
this->write8(APDS9960_GCONF1, _gconf1.get()); this->write8(APDS9960_GCONF1, _gconf1.get());
} }
void Adafruit_APDS9960::setGestureGain(uint8_t gain) /*!
{ * @brief Sets gesture sensor gain
* @param gain
* Gain (APDS9960_GAIN_1, APDS9960_GAIN_2, APDS9960_GAIN_4,
* APDS9960_GAIN_8)
*/
void Adafruit_APDS9960::setGestureGain(uint8_t gain) {
_gconf2.GGAIN = gain; _gconf2.GGAIN = gain;
this->write8(APDS9960_GCONF2, _gconf2.get()); this->write8(APDS9960_GCONF2, _gconf2.get());
} }
void Adafruit_APDS9960::setGestureProximityThreshold(uint8_t thresh) /*!
{ * @brief Sets gesture sensor threshold
* @param thresh
* Threshold
*/
void Adafruit_APDS9960::setGestureProximityThreshold(uint8_t thresh) {
this->write8(APDS9960_GPENTH, thresh); this->write8(APDS9960_GPENTH, thresh);
} }
void Adafruit_APDS9960::setGestureOffset(uint8_t offset_up, uint8_t offset_down, uint8_t offset_left, uint8_t offset_right) /*!
{ * @brief Sets gesture sensor offset
* @param offset_up
* Up offset
* @param offset_down
* Down offset
* @param offset_left
* Left offset
* @param offset_right
* Right offset
*/
void Adafruit_APDS9960::setGestureOffset(uint8_t offset_up, uint8_t offset_down,
uint8_t offset_left,
uint8_t offset_right) {
this->write8(APDS9960_GOFFSET_U, offset_up); this->write8(APDS9960_GOFFSET_U, offset_up);
this->write8(APDS9960_GOFFSET_D, offset_down); this->write8(APDS9960_GOFFSET_D, offset_down);
this->write8(APDS9960_GOFFSET_L, offset_left); this->write8(APDS9960_GOFFSET_L, offset_left);
this->write8(APDS9960_GOFFSET_R, offset_right); this->write8(APDS9960_GOFFSET_R, offset_right);
} }
/**************************************************************************/
/*! /*!
Enable gesture readings on APDS9960 * @brief Enable gesture readings on APDS9960
* @param en
* Enable (True/False)
*/ */
/**************************************************************************/ void Adafruit_APDS9960::enableGesture(boolean en) {
void Adafruit_APDS9960::enableGesture(boolean en)
{
if (!en) { if (!en) {
_gconf4.GMODE = 0; _gconf4.GMODE = 0;
write8(APDS9960_GCONF4, _gconf4.get()); write8(APDS9960_GCONF4, _gconf4.get());
@ -307,8 +374,10 @@ void Adafruit_APDS9960::enableGesture(boolean en)
resetCounts(); resetCounts();
} }
void Adafruit_APDS9960::resetCounts() /*!
{ * @brief Resets gesture counts
*/
void Adafruit_APDS9960::resetCounts() {
gestCnt = 0; gestCnt = 0;
UCount = 0; UCount = 0;
DCount = 0; DCount = 0;
@ -316,21 +385,27 @@ void Adafruit_APDS9960::resetCounts()
RCount = 0; RCount = 0;
} }
uint8_t Adafruit_APDS9960::readGesture(void) /*!
{ * @brief Reads gesture
* @return Received gesture (APDS9960_DOWN APDS9960_UP, APDS9960_LEFT
* APDS9960_RIGHT)
*/
uint8_t Adafruit_APDS9960::readGesture() {
uint8_t toRead, bytesRead; uint8_t toRead, bytesRead;
uint8_t buf[256]; uint8_t buf[256];
unsigned long t; unsigned long t = 0;
uint8_t gestureReceived; uint8_t gestureReceived;
while (1) { while (1) {
int up_down_diff = 0; int up_down_diff = 0;
int left_right_diff = 0; int left_right_diff = 0;
gestureReceived = 0; gestureReceived = 0;
if(!gestureValid()) return 0; if (!gestureValid())
return 0;
delay(30); delay(30);
toRead = this->read8(APDS9960_GFLVL); toRead = this->read8(APDS9960_GFLVL);
// bytesRead is unused but produces sideffects needed for readGesture to work
bytesRead = this->read(APDS9960_GFIFO_U, buf, toRead); bytesRead = this->read(APDS9960_GFIFO_U, buf, toRead);
if (abs((int)buf[0] - (int)buf[1]) > 13) if (abs((int)buf[0] - (int)buf[1]) > 13)
@ -343,14 +418,13 @@ uint8_t Adafruit_APDS9960::readGesture(void)
if (up_down_diff < 0) { if (up_down_diff < 0) {
if (DCount > 0) { if (DCount > 0) {
gestureReceived = APDS9960_UP; gestureReceived = APDS9960_UP;
} } else
else UCount++; UCount++;
} } else if (up_down_diff > 0) {
else if(up_down_diff > 0){
if (UCount > 0) { if (UCount > 0) {
gestureReceived = APDS9960_DOWN; gestureReceived = APDS9960_DOWN;
} } else
else DCount++; DCount++;
} }
} }
@ -358,18 +432,18 @@ uint8_t Adafruit_APDS9960::readGesture(void)
if (left_right_diff < 0) { if (left_right_diff < 0) {
if (RCount > 0) { if (RCount > 0) {
gestureReceived = APDS9960_LEFT; gestureReceived = APDS9960_LEFT;
} } else
else LCount++; LCount++;
} } else if (left_right_diff > 0) {
else if(left_right_diff > 0){
if (LCount > 0) { if (LCount > 0) {
gestureReceived = APDS9960_RIGHT; gestureReceived = APDS9960_RIGHT;
} } else
else RCount++; RCount++;
} }
} }
if(up_down_diff != 0 || left_right_diff != 0) t = millis(); if (up_down_diff != 0 || left_right_diff != 0)
t = millis();
if (gestureReceived || millis() - t > 300) { if (gestureReceived || millis() - t > 300) {
resetCounts(); resetCounts();
@ -378,12 +452,15 @@ uint8_t Adafruit_APDS9960::readGesture(void)
} }
} }
/**************************************************************************/
/*! /*!
Set LED brightness for proximity/gesture * @brief Set LED brightness for proximity/gesture
* @param drive
* LED Drive
* @param boost
* LED Boost
*/ */
/**************************************************************************/ void Adafruit_APDS9960::setLED(apds9960LedDrive_t drive,
void Adafruit_APDS9960::setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost) { apds9960LedBoost_t boost) {
// set BOOST // set BOOST
_config2.LED_BOOST = boost; _config2.LED_BOOST = boost;
write8(APDS9960_CONFIG2, _config2.get()); write8(APDS9960_CONFIG2, _config2.get());
@ -392,46 +469,57 @@ void Adafruit_APDS9960::setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boos
write8(APDS9960_CONTROL, _control.get()); write8(APDS9960_CONTROL, _control.get());
} }
/**************************************************************************/
/*! /*!
Enable proximity readings on APDS9960 * @brief Enable proximity readings on APDS9960
* @param en
* Enable (True/False)
*/ */
/**************************************************************************/ void Adafruit_APDS9960::enableColor(boolean en) {
void Adafruit_APDS9960::enableColor(boolean en)
{
_enable.AEN = en; _enable.AEN = en;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
} }
bool Adafruit_APDS9960::colorDataReady() /*!
{ * @brief Returns status of color data
* @return True if color data ready, False otherwise
*/
bool Adafruit_APDS9960::colorDataReady() {
_status.set(this->read8(APDS9960_STATUS)); _status.set(this->read8(APDS9960_STATUS));
return _status.AVALID; return _status.AVALID;
} }
/**************************************************************************/
/*! /*!
@brief Reads the raw red, green, blue and clear channel values * @brief Reads the raw red, green, blue and clear channel values
* @param *r
* Red value
* @param *g
* Green value
* @param *b
* Blue value
* @param *c
* Clear channel value
*/ */
/**************************************************************************/ void Adafruit_APDS9960::getColorData(uint16_t *r, uint16_t *g, uint16_t *b,
void Adafruit_APDS9960::getColorData (uint16_t *r, uint16_t *g, uint16_t *b, uint16_t *c) uint16_t *c) {
{
*c = read16R(APDS9960_CDATAL); *c = read16R(APDS9960_CDATAL);
*r = read16R(APDS9960_RDATAL); *r = read16R(APDS9960_RDATAL);
*g = read16R(APDS9960_GDATAL); *g = read16R(APDS9960_GDATAL);
*b = read16R(APDS9960_BDATAL); *b = read16R(APDS9960_BDATAL);
} }
/**************************************************************************/
/*! /*!
@brief Converts the raw R/G/B values to color temperature in degrees * @brief Converts the raw R/G/B values to color temperature in degrees Kelvin
Kelvin * @param r
* Red value
* @param g
* Green value
* @param b
* Blue value
* @return Color temperature
*/ */
/**************************************************************************/ uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g,
uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, uint16_t b) uint16_t b) {
{
float X, Y, Z; /* RGB to XYZ correlation */ float X, Y, Z; /* RGB to XYZ correlation */
float xc, yc; /* Chromaticity co-ordinates */ float xc, yc; /* Chromaticity co-ordinates */
float n; /* McCamy's formula */ float n; /* McCamy's formula */
@ -453,20 +541,24 @@ uint16_t Adafruit_APDS9960::calculateColorTemperature(uint16_t r, uint16_t g, ui
n = (xc - 0.3320F) / (0.1858F - yc); n = (xc - 0.3320F) / (0.1858F - yc);
/* Calculate the final CCT */ /* Calculate the final CCT */
cct = (449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F; cct =
(449.0F * powf(n, 3)) + (3525.0F * powf(n, 2)) + (6823.3F * n) + 5520.33F;
/* Return the results in degrees Kelvin */ /* Return the results in degrees Kelvin */
return (uint16_t)cct; return (uint16_t)cct;
} }
/**************************************************************************/
/*! /*!
@brief Calculate ambient light values * @brief Calculate ambient light values
* @param r
* Red value
* @param g
* Green value
* @param b
* Blue value
* @return LUX value
*/ */
/**************************************************************************/ uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b) {
uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b)
{
float illuminance; float illuminance;
/* This only uses RGB ... how can we integrate clear or calculate lux */ /* This only uses RGB ... how can we integrate clear or calculate lux */
@ -476,21 +568,36 @@ uint16_t Adafruit_APDS9960::calculateLux(uint16_t r, uint16_t g, uint16_t b)
return (uint16_t)illuminance; return (uint16_t)illuminance;
} }
/*!
* @brief Enables color interrupt
*/
void Adafruit_APDS9960::enableColorInterrupt() { void Adafruit_APDS9960::enableColorInterrupt() {
_enable.AIEN = 1; _enable.AIEN = 1;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
} }
/*!
* @brief Disables color interrupt
*/
void Adafruit_APDS9960::disableColorInterrupt() { void Adafruit_APDS9960::disableColorInterrupt() {
_enable.AIEN = 0; _enable.AIEN = 0;
write8(APDS9960_ENABLE, _enable.get()); write8(APDS9960_ENABLE, _enable.get());
} }
void Adafruit_APDS9960::clearInterrupt(void) { /*!
* @brief Clears interrupt
*/
void Adafruit_APDS9960::clearInterrupt() {
this->write(APDS9960_AICLEAR, NULL, 0); this->write(APDS9960_AICLEAR, NULL, 0);
} }
/*!
* @brief Sets interrupt limits
* @param low
* Low limit
* @param high
* High limit
*/
void Adafruit_APDS9960::setIntLimits(uint16_t low, uint16_t high) { void Adafruit_APDS9960::setIntLimits(uint16_t low, uint16_t high) {
write8(APDS9960_AILTIL, low & 0xFF); write8(APDS9960_AILTIL, low & 0xFF);
write8(APDS9960_AILTH, low >> 8); write8(APDS9960_AILTH, low >> 8);
@ -498,51 +605,85 @@ void Adafruit_APDS9960::setIntLimits(uint16_t low, uint16_t high) {
write8(APDS9960_AIHTH, high >> 8); write8(APDS9960_AIHTH, high >> 8);
} }
void Adafruit_APDS9960::write8(byte reg, byte value) /*!
{ * @brief Writes specified value to given register
* @param reg
* Register to write to
* @param value
* Value to write
*/
void Adafruit_APDS9960::write8(byte reg, byte value) {
this->write(reg, &value, 1); this->write(reg, &value, 1);
} }
uint8_t Adafruit_APDS9960::read8(byte reg) /*!
{ * @brief Reads 8 bits from specified register
* @param reg
* Register to write to
* @return Value in register
*/
uint8_t Adafruit_APDS9960::read8(byte reg) {
uint8_t ret; uint8_t ret;
this->read(reg, &ret, 1); this->read(reg, &ret, 1);
return ret; return ret;
} }
uint32_t Adafruit_APDS9960::read32(uint8_t reg) /*!
{ * @brief Reads 32 bits from specified register
* @param reg
* Register to write to
* @return Value in register
*/
uint32_t Adafruit_APDS9960::read32(uint8_t reg) {
uint8_t ret[4]; uint8_t ret[4];
this->read(reg, ret, 4); this->read(reg, ret, 4);
return (ret[0] << 24) | (ret[1] << 16) | (ret[2] << 8) | ret[3]; return (ret[0] << 24) | (ret[1] << 16) | (ret[2] << 8) | ret[3];
} }
uint16_t Adafruit_APDS9960::read16(uint8_t reg) /*!
{ * @brief Reads 16 bites from specified register
* @param reg
* Register to write to
* @return Value in register
*/
uint16_t Adafruit_APDS9960::read16(uint8_t reg) {
uint8_t ret[2]; uint8_t ret[2];
this->read(reg, ret, 2); this->read(reg, ret, 2);
return (ret[0] << 8) | ret[1]; return (ret[0] << 8) | ret[1];
} }
uint16_t Adafruit_APDS9960::read16R(uint8_t reg) /*!
{ * @brief Reads 16 bites from specified register
* @param reg
* Register to write to
* @return Value in register
*/
uint16_t Adafruit_APDS9960::read16R(uint8_t reg) {
uint8_t ret[2]; uint8_t ret[2];
this->read(reg, ret, 2); this->read(reg, ret, 2);
return (ret[1] << 8) | ret[0]; return (ret[1] << 8) | ret[0];
} }
void Adafruit_APDS9960::_i2c_init() /*!
{ * @brief Begins I2C communication
Wire.begin(); */
} void Adafruit_APDS9960::_i2c_init() { _wire->begin(); }
uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num) /*!
{ * @brief Reads num bytes from specified register into a given buffer
uint8_t value; * @param reg
* Register
* @param *buf
* Buffer
* @param num
* Number of bytes
* @return Position after reading
*/
uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num) {
uint8_t pos = 0; uint8_t pos = 0;
bool eof = false; bool eof = false;
@ -550,28 +691,36 @@ uint8_t Adafruit_APDS9960::read(uint8_t reg, uint8_t *buf, uint8_t num)
while (pos < num && !eof) { while (pos < num && !eof) {
uint8_t read_now = min(32, num - pos); uint8_t read_now = min(32, num - pos);
Wire.beginTransmission((uint8_t)_i2caddr); _wire->beginTransmission((uint8_t)_i2caddr);
Wire.write((uint8_t)reg + pos); _wire->write((uint8_t)reg + pos);
Wire.endTransmission(); _wire->endTransmission();
Wire.requestFrom((uint8_t)_i2caddr, read_now); _wire->requestFrom((uint8_t)_i2caddr, read_now);
for (int i = 0; i < read_now; i++) { for (int i = 0; i < read_now; i++) {
if(!Wire.available()){ if (!_wire->available()) {
eof = true; eof = true;
break; break;
} }
buf[pos] = Wire.read(); buf[pos] = _wire->read();
pos++; pos++;
} }
} }
return pos; return pos;
} }
void Adafruit_APDS9960::write(uint8_t reg, uint8_t *buf, uint8_t num) /*!
{ * @brief Writes num bytes from specified buffer into a given register
Wire.beginTransmission((uint8_t)_i2caddr); * @param reg
Wire.write((uint8_t)reg); * Register
Wire.write((uint8_t *)buf, num); * @param *buf
Wire.endTransmission(); * Buffer
* @param num
* Number of bytes
*/
void Adafruit_APDS9960::write(uint8_t reg, uint8_t *buf, uint8_t num) {
_wire->beginTransmission((uint8_t)_i2caddr);
_wire->write((uint8_t)reg);
_wire->write((uint8_t *)buf, num);
_wire->endTransmission();
} }

View file

@ -1,58 +1,43 @@
/**************************************************************************/
/*! /*!
@file Adafruit_APDS9960.h * @file Adafruit_APDS9960.h
@author Ladyada, Dean Miller (Adafruit Industries) *
* Software License Agreement (BSD License)
@section LICENSE *
* Copyright (c) 2017, Adafruit Industries
Software License Agreement (BSD License) * All rights reserved.
*
Copyright (c) 2017, Adafruit Industries * Redistribution and use in source and binary forms, with or without
All rights reserved. * modification, are permitted provided that the following conditions are met:
* 1. Redistributions of source code must retain the above copyright
Redistribution and use in source and binary forms, with or without * notice, this list of conditions and the following disclaimer.
modification, are permitted provided that the following conditions are met: * 2. Redistributions in binary form must reproduce the above copyright
1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer in the
notice, this list of conditions and the following disclaimer. * documentation and/or other materials provided with the distribution.
2. Redistributions in binary form must reproduce the above copyright * 3. Neither the name of the copyright holders nor the
notice, this list of conditions and the following disclaimer in the * names of its contributors may be used to endorse or promote products
documentation and/or other materials provided with the distribution. * derived from this software without specific prior written permission.
3. Neither the name of the copyright holders nor the *
names of its contributors may be used to endorse or promote products * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
derived from this software without specific prior written permission. * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
/**************************************************************************/
#ifndef _APDS9960_H_ #ifndef _APDS9960_H_
#define _APDS9960_H_ #define _APDS9960_H_
#include <Arduino.h> #include <Arduino.h>
#include <Wire.h> #include <Wire.h>
#define I2CDEBUG #define APDS9960_ADDRESS (0x39) /**< I2C Address */
/*========================================================================= /** I2C Registers */
I2C ADDRESS/BITS enum {
-----------------------------------------------------------------------*/
#define APDS9960_ADDRESS (0x39)
/*=========================================================================*/
/*=========================================================================
REGISTERS
-----------------------------------------------------------------------*/
enum
{
APDS9960_RAM = 0x00, APDS9960_RAM = 0x00,
APDS9960_ENABLE = 0x80, APDS9960_ENABLE = 0x80,
APDS9960_ATIME = 0x81, APDS9960_ATIME = 0x81,
@ -105,117 +90,109 @@
APDS9960_GFIFO_R = 0xFF, APDS9960_GFIFO_R = 0xFF,
}; };
/** ADC gain settings */
/*=========================================================================*/ typedef enum {
typedef enum
{
APDS9960_AGAIN_1X = 0x00, /**< No gain */ APDS9960_AGAIN_1X = 0x00, /**< No gain */
APDS9960_AGAIN_4X = 0x01, /**< 2x gain */ APDS9960_AGAIN_4X = 0x01, /**< 2x gain */
APDS9960_AGAIN_16X = 0x02, /**< 16x gain */ APDS9960_AGAIN_16X = 0x02, /**< 16x gain */
APDS9960_AGAIN_64X = 0x03 /**< 64x gain */ APDS9960_AGAIN_64X = 0x03 /**< 64x gain */
} } apds9960AGain_t;
apds9960AGain_t;
/** Proxmity gain settings */
typedef enum typedef enum {
{
APDS9960_PGAIN_1X = 0x00, /**< 1x gain */ APDS9960_PGAIN_1X = 0x00, /**< 1x gain */
APDS9960_PGAIN_2X = 0x04, /**< 2x gain */ APDS9960_PGAIN_2X = 0x04, /**< 2x gain */
APDS9960_PGAIN_4X = 0x08, /**< 4x gain */ APDS9960_PGAIN_4X = 0x08, /**< 4x gain */
APDS9960_PGAIN_8X = 0x0C /**< 8x gain */ APDS9960_PGAIN_8X = 0x0C /**< 8x gain */
} } apds9960PGain_t;
apds9960PGain_t;
/** Pulse length settings */
typedef enum typedef enum {
{
APDS9960_PPULSELEN_4US = 0x00, /**< 4uS */ APDS9960_PPULSELEN_4US = 0x00, /**< 4uS */
APDS9960_PPULSELEN_8US = 0x40, /**< 8uS */ APDS9960_PPULSELEN_8US = 0x40, /**< 8uS */
APDS9960_PPULSELEN_16US = 0x80, /**< 16uS */ APDS9960_PPULSELEN_16US = 0x80, /**< 16uS */
APDS9960_PPULSELEN_32US = 0xC0 /**< 32uS */ APDS9960_PPULSELEN_32US = 0xC0 /**< 32uS */
} } apds9960PPulseLen_t;
apds9960PPulseLen_t;
/** LED drive settings */
typedef enum typedef enum {
{
APDS9960_LEDDRIVE_100MA = 0x00, /**< 100mA */ APDS9960_LEDDRIVE_100MA = 0x00, /**< 100mA */
APDS9960_LEDDRIVE_50MA = 0x40, /**< 50mA */ APDS9960_LEDDRIVE_50MA = 0x40, /**< 50mA */
APDS9960_LEDDRIVE_25MA = 0x80, /**< 25mA */ APDS9960_LEDDRIVE_25MA = 0x80, /**< 25mA */
APDS9960_LEDDRIVE_12MA = 0xC0 /**< 12.5mA */ APDS9960_LEDDRIVE_12MA = 0xC0 /**< 12.5mA */
} } apds9960LedDrive_t;
apds9960LedDrive_t;
/** LED boost settings */
typedef enum typedef enum {
{
APDS9960_LEDBOOST_100PCNT = 0x00, /**< 100% */ APDS9960_LEDBOOST_100PCNT = 0x00, /**< 100% */
APDS9960_LEDBOOST_150PCNT = 0x10, /**< 150% */ APDS9960_LEDBOOST_150PCNT = 0x10, /**< 150% */
APDS9960_LEDBOOST_200PCNT = 0x20, /**< 200% */ APDS9960_LEDBOOST_200PCNT = 0x20, /**< 200% */
APDS9960_LEDBOOST_300PCNT = 0x30 /**< 300% */ APDS9960_LEDBOOST_300PCNT = 0x30 /**< 300% */
} } apds9960LedBoost_t;
apds9960LedBoost_t;
enum /** Dimensions */
{ enum {
APDS9960_DIMENSIONS_ALL = 0x00, APDS9960_DIMENSIONS_ALL = 0x00, // All dimensions
APDS9960_DIMENSIONS_UP_DOWM = 0x01, APDS9960_DIMENSIONS_UP_DOWN = 0x01, // Up/Down dimensions
APGS9960_DIMENSIONS_LEFT_RIGHT = 0x02, APGS9960_DIMENSIONS_LEFT_RIGHT = 0x02, // Left/Right dimensions
}; };
enum /** FIFO Interrupts */
{ enum {
APDS9960_GFIFO_1 = 0x00, APDS9960_GFIFO_1 = 0x00, // Generate interrupt after 1 dataset in FIFO
APDS9960_GFIFO_4 = 0x01, APDS9960_GFIFO_4 = 0x01, // Generate interrupt after 2 datasets in FIFO
APDS9960_GFIFO_8 = 0x02, APDS9960_GFIFO_8 = 0x02, // Generate interrupt after 3 datasets in FIFO
APDS9960_GFIFO_16 = 0x03, APDS9960_GFIFO_16 = 0x03, // Generate interrupt after 4 datasets in FIFO
}; };
enum /** Gesture Gain */
{ enum {
APDS9960_GGAIN_1 = 0x00, APDS9960_GGAIN_1 = 0x00, // Gain 1x
APDS9960_GGAIN_2 = 0x01, APDS9960_GGAIN_2 = 0x01, // Gain 2x
APDS9960_GGAIN_4 = 0x02, APDS9960_GGAIN_4 = 0x02, // Gain 4x
APDS9960_GGAIN_8 = 0x03, APDS9960_GGAIN_8 = 0x03, // Gain 8x
}; };
enum /** Pulse Lenghts */
{ enum {
APDS9960_GPULSE_4US = 0x00, APDS9960_GPULSE_4US = 0x00, // Pulse 4us
APDS9960_GPULSE_8US = 0x01, APDS9960_GPULSE_8US = 0x01, // Pulse 8us
APDS9960_GPULSE_16US = 0x02, APDS9960_GPULSE_16US = 0x02, // Pulse 16us
APDS9960_GPULSE_32US = 0x03, APDS9960_GPULSE_32US = 0x03, // Pulse 32us
}; };
#define APDS9960_TIME_MULT 2.78 //millisec #define APDS9960_UP 0x01 /**< Gesture Up */
#define APDS9960_DOWN 0x02 /**< Gesture Down */
#define APDS9960_UP 0x01 #define APDS9960_LEFT 0x03 /**< Gesture Left */
#define APDS9960_DOWN 0x02 #define APDS9960_RIGHT 0x04 /**< Gesture Right */
#define APDS9960_LEFT 0x03
#define APDS9960_RIGHT 0x04
/*!
* @brief Class that stores state and functions for interacting with
* APDS9960 Sensor
*/
class Adafruit_APDS9960 { class Adafruit_APDS9960 {
public: public:
Adafruit_APDS9960(void) {}; Adafruit_APDS9960(){};
~Adafruit_APDS9960(void) {}; ~Adafruit_APDS9960(){};
boolean begin(uint16_t iTimeMS = 10, apds9960AGain_t = APDS9960_AGAIN_4X, uint8_t addr = APDS9960_ADDRESS); boolean begin(uint16_t iTimeMS = 10, apds9960AGain_t = APDS9960_AGAIN_4X,
uint8_t addr = APDS9960_ADDRESS, TwoWire *theWire = &Wire);
void setADCIntegrationTime(uint16_t iTimeMS); void setADCIntegrationTime(uint16_t iTimeMS);
float getADCIntegrationTime(void); float getADCIntegrationTime();
void setADCGain(apds9960AGain_t gain); void setADCGain(apds9960AGain_t gain);
apds9960AGain_t getADCGain(void); apds9960AGain_t getADCGain();
void setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost); void setLED(apds9960LedDrive_t drive, apds9960LedBoost_t boost);
// proximity // proximity
void enableProximity(boolean en = true); void enableProximity(boolean en = true);
void setProxGain(apds9960PGain_t gain); void setProxGain(apds9960PGain_t gain);
apds9960PGain_t getProxGain(void); apds9960PGain_t getProxGain();
void setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses); void setProxPulse(apds9960PPulseLen_t pLen, uint8_t pulses);
void enableProximityInterrupt(); void enableProximityInterrupt();
void disableProximityInterrupt(); void disableProximityInterrupt();
uint8_t readProximity(void); uint8_t readProximity();
void setProximityInterruptThreshold(uint8_t low, uint8_t high, uint8_t persistance = 4); void setProximityInterruptThreshold(uint8_t low, uint8_t high,
uint8_t persistance = 4);
bool getProximityInterrupt(); bool getProximityInterrupt();
// gesture // gesture
@ -225,8 +202,9 @@ class Adafruit_APDS9960 {
void setGestureFIFOThreshold(uint8_t thresh); void setGestureFIFOThreshold(uint8_t thresh);
void setGestureGain(uint8_t gain); void setGestureGain(uint8_t gain);
void setGestureProximityThreshold(uint8_t thresh); void setGestureProximityThreshold(uint8_t thresh);
void setGestureOffset(uint8_t offset_up, uint8_t offset_down, uint8_t offset_left, uint8_t offset_right); void setGestureOffset(uint8_t offset_up, uint8_t offset_down,
uint8_t readGesture(void); uint8_t offset_left, uint8_t offset_right);
uint8_t readGesture();
void resetCounts(); void resetCounts();
// light & color // light & color
@ -237,15 +215,15 @@ class Adafruit_APDS9960 {
uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b); uint16_t calculateLux(uint16_t r, uint16_t g, uint16_t b);
void enableColorInterrupt(); void enableColorInterrupt();
void disableColorInterrupt(); void disableColorInterrupt();
void clearInterrupt(void); void clearInterrupt();
void setIntLimits(uint16_t l, uint16_t h); void setIntLimits(uint16_t l, uint16_t h);
// turn on/off elements // turn on/off elements
void enable(boolean en = true); void enable(boolean en = true);
private: private:
uint8_t _i2caddr; uint8_t _i2caddr;
TwoWire *_wire;
uint32_t read32(uint8_t reg); uint32_t read32(uint8_t reg);
uint16_t read16(uint8_t reg); uint16_t read16(uint8_t reg);
@ -290,46 +268,44 @@ class Adafruit_APDS9960 {
uint8_t GEN : 1; uint8_t GEN : 1;
uint8_t get() { uint8_t get() {
return (GEN << 6) | (PIEN << 5) | (AIEN << 4) | (WEN << 3) | (PEN << 2) | (AEN << 1) | PON; return (GEN << 6) | (PIEN << 5) | (AIEN << 4) | (WEN << 3) | (PEN << 2) |
(AEN << 1) | PON;
}; };
}; };
struct enable _enable; struct enable _enable;
struct pers { struct pers {
//ALS Interrupt Persistence. Controls rate of Clear channel interrupt to the host processor // ALS Interrupt Persistence. Controls rate of Clear channel interrupt to
// the host processor
uint8_t APERS : 4; uint8_t APERS : 4;
//proximity interrupt persistence, controls rate of prox interrupt to host processor // proximity interrupt persistence, controls rate of prox interrupt to host
// processor
uint8_t PPERS : 4; uint8_t PPERS : 4;
uint8_t get(){ uint8_t get() { return (PPERS << 4) | APERS; };
return (PPERS << 4) | APERS;
};
}; };
pers _pers; pers _pers;
struct config1 { struct config1 {
uint8_t WLONG : 1; uint8_t WLONG : 1;
uint8_t get(){ uint8_t get() { return WLONG << 1; };
return WLONG << 1;
};
}; };
config1 _config1; config1 _config1;
struct ppulse { struct ppulse {
/*Proximity Pulse Count. Specifies the number of proximity pulses to be generated on LDR. /*Proximity Pulse Count. Specifies the number of proximity pulses to be
Number of pulses is set by PPULSE value plus 1. generated on LDR. Number of pulses is set by PPULSE value plus 1.
*/ */
uint8_t PPULSE : 6; uint8_t PPULSE : 6;
//Proximity Pulse Length. Sets the LED-ON pulse width during a proximity LDR pulse. // Proximity Pulse Length. Sets the LED-ON pulse width during a proximity
// LDR pulse.
uint8_t PPLEN : 2; uint8_t PPLEN : 2;
uint8_t get(){ uint8_t get() { return (PPLEN << 6) | PPULSE; }
return (PPLEN << 6) | PPULSE;
}
}; };
ppulse _ppulse; ppulse _ppulse;
@ -343,15 +319,13 @@ class Adafruit_APDS9960 {
// led drive strength // led drive strength
uint8_t LDRIVE : 2; uint8_t LDRIVE : 2;
uint8_t get(){ uint8_t get() { return (LDRIVE << 6) | (PGAIN << 2) | AGAIN; }
return (LDRIVE << 6) | (PGAIN << 2) | AGAIN;
}
}; };
control _control; control _control;
struct config2 { struct config2 {
/* Additional LDR current during proximity and gesture LED pulses. Current value, set by LDRIVE, /* Additional LDR current during proximity and gesture LED pulses. Current
is increased by the percentage of LED_BOOST. value, set by LDRIVE, is increased by the percentage of LED_BOOST.
*/ */
uint8_t LED_BOOST : 2; uint8_t LED_BOOST : 2;
@ -368,38 +342,41 @@ class Adafruit_APDS9960 {
config2 _config2; config2 _config2;
struct status { struct status {
/* ALS Valid. Indicates that an ALS cycle has completed since AEN was asserted or since a read /* ALS Valid. Indicates that an ALS cycle has completed since AEN was
from any of the ALS/Color data registers. asserted or since a read from any of the ALS/Color data registers.
*/ */
uint8_t AVALID : 1; uint8_t AVALID : 1;
/* Proximity Valid. Indicates that a proximity cycle has completed since PEN was asserted or since /* Proximity Valid. Indicates that a proximity cycle has completed since PEN
PDATA was last read. A read of PDATA automatically clears PVALID. was asserted or since PDATA was last read. A read of PDATA automatically
clears PVALID.
*/ */
uint8_t PVALID : 1; uint8_t PVALID : 1;
/* Gesture Interrupt. GINT is asserted when GFVLV becomes greater than GFIFOTH or if GVALID /* Gesture Interrupt. GINT is asserted when GFVLV becomes greater than
has become asserted when GMODE transitioned to zero. The bit is reset when FIFO is GFIFOTH or if GVALID has become asserted when GMODE transitioned to zero.
completely emptied (read). The bit is reset when FIFO is completely emptied (read).
*/ */
uint8_t GINT : 1; uint8_t GINT : 1;
// ALS Interrupt. This bit triggers an interrupt if AIEN in ENABLE is set. // ALS Interrupt. This bit triggers an interrupt if AIEN in ENABLE is set.
uint8_t AINT : 1; uint8_t AINT : 1;
//Proximity Interrupt. This bit triggers an interrupt if PIEN in ENABLE is set. // Proximity Interrupt. This bit triggers an interrupt if PIEN in ENABLE is
// set.
uint8_t PINT : 1; uint8_t PINT : 1;
/* Indicates that an analog saturation event occurred during a previous proximity or gesture /* Indicates that an analog saturation event occurred during a previous
cycle. Once set, this bit remains set until cleared by clear proximity interrupt special function proximity or gesture cycle. Once set, this bit remains set until cleared by
command (0xE5 PICLEAR) or by disabling Prox (PEN=0). This bit triggers an interrupt if PSIEN clear proximity interrupt special function command (0xE5 PICLEAR) or by
is set. disabling Prox (PEN=0). This bit triggers an interrupt if PSIEN is set.
*/ */
uint8_t PGSAT : 1; uint8_t PGSAT : 1;
/* Clear Photodiode Saturation. When asserted, the analog sensor was at the upper end of its /* Clear Photodiode Saturation. When asserted, the analog sensor was at the
dynamic range. The bit can be de-asserted by sending a Clear channel interrupt command upper end of its dynamic range. The bit can be de-asserted by sending a
(0xE6 CICLEAR) or by disabling the ADC (AEN=0). This bit triggers an interrupt if CPSIEN is set. Clear channel interrupt command (0xE6 CICLEAR) or by disabling the ADC
(AEN=0). This bit triggers an interrupt if CPSIEN is set.
*/ */
uint8_t CPSAT : 1; uint8_t CPSAT : 1;
@ -422,111 +399,108 @@ class Adafruit_APDS9960 {
uint8_t PMASK_D : 1; uint8_t PMASK_D : 1;
uint8_t PMASK_U : 1; uint8_t PMASK_U : 1;
/* Sleep After Interrupt. When enabled, the device will automatically enter low power mode /* Sleep After Interrupt. When enabled, the device will automatically enter
when the INT pin is asserted and the state machine has progressed to the SAI decision block. low power mode when the INT pin is asserted and the state machine has
Normal operation is resumed when INT pin is cleared over I2C. progressed to the SAI decision block. Normal operation is resumed when INT
pin is cleared over I2C.
*/ */
uint8_t SAI : 1; uint8_t SAI : 1;
/* Proximity Gain Compensation Enable. This bit provides gain compensation when proximity /* Proximity Gain Compensation Enable. This bit provides gain compensation
photodiode signal is reduced as a result of sensor masking. If only one diode of the diode pair when proximity photodiode signal is reduced as a result of sensor masking.
is contributing, then only half of the signal is available at the ADC; this results in a maximum If only one diode of the diode pair is contributing, then only half of the
ADC value of 127. Enabling PCMP enables an additional gain of 2X, resulting in a maximum signal is available at the ADC; this results in a maximum ADC value of 127.
ADC value of 255. Enabling PCMP enables an additional gain of 2X, resulting in a maximum ADC
value of 255.
*/ */
uint8_t PCMP : 1; uint8_t PCMP : 1;
uint8_t get() { uint8_t get() {
return (PCMP << 5) | (SAI << 4) | (PMASK_U << 3) | (PMASK_D << 2) | (PMASK_L << 1) | PMASK_R; return (PCMP << 5) | (SAI << 4) | (PMASK_U << 3) | (PMASK_D << 2) |
(PMASK_L << 1) | PMASK_R;
} }
}; };
config3 _config3; config3 _config3;
struct gconf1 { struct gconf1 {
/* Gesture Exit Persistence. When a number of consecutive “gesture end” occurrences become /* Gesture Exit Persistence. When a number of consecutive “gesture end”
equal or greater to the GEPERS value, the Gesture state machine is exited. occurrences become equal or greater to the GEPERS value, the Gesture state
machine is exited.
*/ */
uint8_t GEXPERS : 2; uint8_t GEXPERS : 2;
/* Gesture Exit Mask. Controls which of the gesture detector photodiodes (UDLR) will be included /* Gesture Exit Mask. Controls which of the gesture detector photodiodes
to determine a gesture end and subsequent exit of the gesture state machine. Unmasked (UDLR) will be included to determine a “gesture end” and subsequent exit
UDLR data will be compared with the value in GTHR_OUT. Field value bits correspond to UDLR of the gesture state machine. Unmasked UDLR data will be compared with the
detectors. value in GTHR_OUT. Field value bits correspond to UDLR detectors.
*/ */
uint8_t GEXMSK : 4; uint8_t GEXMSK : 4;
/* Gesture FIFO Threshold. This value is compared with the FIFO Level (i.e. the number of UDLR /* Gesture FIFO Threshold. This value is compared with the FIFO Level (i.e.
datasets) to generate an interrupt (if enabled). the number of UDLR datasets) to generate an interrupt (if enabled).
*/ */
uint8_t GFIFOTH : 2; uint8_t GFIFOTH : 2;
uint8_t get(){ uint8_t get() { return (GFIFOTH << 6) | (GEXMSK << 2) | GEXPERS; }
return (GFIFOTH << 6) | (GEXMSK << 2) | GEXPERS;
}
}; };
gconf1 _gconf1; gconf1 _gconf1;
struct gconf2 { struct gconf2 {
/* Gesture Wait Time. The GWTIME controls the amount of time in a low power mode between /* Gesture Wait Time. The GWTIME controls the amount of time in a low power
gesture detection cycles. mode between gesture detection cycles.
*/ */
uint8_t GWTIME : 3; uint8_t GWTIME : 3;
// Gesture LED Drive Strength. Sets LED Drive Strength in gesture mode. // Gesture LED Drive Strength. Sets LED Drive Strength in gesture mode.
uint8_t GLDRIVE : 2; uint8_t GLDRIVE : 2;
//Gesture Gain Control. Sets the gain of the proximity receiver in gesture mode. // Gesture Gain Control. Sets the gain of the proximity receiver in gesture
// mode.
uint8_t GGAIN : 2; uint8_t GGAIN : 2;
uint8_t get(){ uint8_t get() { return (GGAIN << 5) | (GLDRIVE << 3) | GWTIME; }
return (GGAIN << 5) | (GLDRIVE << 3) | GWTIME;
}
}; };
gconf2 _gconf2; gconf2 _gconf2;
struct gpulse { struct gpulse {
/* Number of Gesture Pulses. Specifies the number of pulses to be generated on LDR. /* Number of Gesture Pulses. Specifies the number of pulses to be generated
Number of pulses is set by GPULSE value plus 1. on LDR. Number of pulses is set by GPULSE value plus 1.
*/ */
uint8_t GPULSE : 6; uint8_t GPULSE : 6;
//Gesture Pulse Length. Sets the LED_ON pulse width during a Gesture LDR Pulse. // Gesture Pulse Length. Sets the LED_ON pulse width during a Gesture LDR
// Pulse.
uint8_t GPLEN : 2; uint8_t GPLEN : 2;
uint8_t get(){ uint8_t get() { return (GPLEN << 6) | GPULSE; }
return (GPLEN << 6) | GPULSE;
}
}; };
gpulse _gpulse; gpulse _gpulse;
struct gconf3 { struct gconf3 {
/* Gesture Dimension Select. Selects which gesture photodiode pairs are enabled to gather /* Gesture Dimension Select. Selects which gesture photodiode pairs are
results during gesture. enabled to gather results during gesture.
*/ */
uint8_t GDIMS : 2; uint8_t GDIMS : 2;
uint8_t get(){ uint8_t get() { return GDIMS; }
return GDIMS;
}
}; };
gconf3 _gconf3; gconf3 _gconf3;
struct gconf4 { struct gconf4 {
/* Gesture Mode. Reading this bit reports if the gesture state machine is actively running, 1 /* Gesture Mode. Reading this bit reports if the gesture state machine is
= Gesture, 0= ALS, Proximity, Color. Writing a 1 to this bit causes immediate entry in to the actively running, 1 = Gesture, 0= ALS, Proximity, Color. Writing a 1 to this
gesture state machine (as if GPENTH had been exceeded). Writing a 0 to this bit causes exit of bit causes immediate entry in to the gesture state machine (as if GPENTH had
gesture when current analog conversion has finished (as if GEXTH had been exceeded). been exceeded). Writing a 0 to this bit causes exit of gesture when current
analog conversion has finished (as if GEXTH had been exceeded).
*/ */
uint8_t GMODE : 1; uint8_t GMODE : 1;
/* Gesture interrupt enable. Gesture Interrupt Enable. When asserted, all gesture related /* Gesture interrupt enable. Gesture Interrupt Enable. When asserted, all
interrupts are unmasked. gesture related interrupts are unmasked.
*/ */
uint8_t GIEN : 2; uint8_t GIEN : 2;
uint8_t get(){ uint8_t get() { return (GIEN << 1) | GMODE; }
return (GIEN << 1) | GMODE;
}
void set(uint8_t data) { void set(uint8_t data) {
GIEN = (data >> 1) & 0x01; GIEN = (data >> 1) & 0x01;
GMODE = data & 0x01; GMODE = data & 0x01;
@ -535,14 +509,14 @@ class Adafruit_APDS9960 {
gconf4 _gconf4; gconf4 _gconf4;
struct gstatus { struct gstatus {
/* Gesture FIFO Data. GVALID bit is sent when GFLVL becomes greater than GFIFOTH (i.e. FIFO has /* Gesture FIFO Data. GVALID bit is sent when GFLVL becomes greater than
enough data to set GINT). GFIFOD is reset when GMODE = 0 and the GFLVL=0 (i.e. All FIFO data GFIFOTH (i.e. FIFO has enough data to set GINT). GFIFOD is reset when GMODE
has been read). = 0 and the GFLVL=0 (i.e. All FIFO data has been read).
*/ */
uint8_t GVALID : 1; uint8_t GVALID : 1;
/* Gesture FIFO Overflow. A setting of 1 indicates that the FIFO has filled to capacity and that new /* Gesture FIFO Overflow. A setting of 1 indicates that the FIFO has filled
gesture detector data has been lost. to capacity and that new gesture detector data has been lost.
*/ */
uint8_t GFOV : 1; uint8_t GFOV : 1;
@ -552,7 +526,6 @@ class Adafruit_APDS9960 {
} }
}; };
gstatus _gstatus; gstatus _gstatus;
}; };
#endif #endif

View file

@ -0,0 +1,18 @@
# Adafruit APDS9960 Library [![Build Status](https://travis-ci.com/adafruit/Adafruit_APDS9960.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_APDS9960)
<a href="https://www.adafruit.com/product/3595"><img src="assets/board.jpg?raw=true" width="500px"></a>
This is the Adafruit APDS9960 Proximity, Light, RGB, and Gesture sensor Library
Tested and works great with the Adafruit APDS9960 Board
* http://www.adafruit.com/products/3595
This chip uses I2C to communicate, 2 pins are required to interface
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
Written by Dean Miller, Limor Fried for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution
To install, use the Arduino Library Manager and search for "Adafruit APDS9960 Library" and install the library.

Binary file not shown.

After

Width:  |  Height:  |  Size: 285 KiB

View file

@ -0,0 +1,127 @@
# Adafruit Community Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and leaders pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, gender identity and expression, level or type of
experience, education, socio-economic status, nationality, personal appearance,
race, religion, or sexual identity and orientation.
## Our Standards
We are committed to providing a friendly, safe and welcoming environment for
all.
Examples of behavior that contributes to creating a positive environment
include:
* Be kind and courteous to others
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Collaborating with other community members
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and sexual attention or advances
* The use of inappropriate images, including in a community member's avatar
* The use of inappropriate language, including in a community member's nickname
* Any spamming, flaming, baiting or other attention-stealing behavior
* Excessive or unwelcome helping; answering outside the scope of the question
asked
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate
The goal of the standards and moderation guidelines outlined here is to build
and maintain a respectful community. We ask that you dont just aim to be
"technically unimpeachable", but rather try to be your best self.
We value many things beyond technical expertise, including collaboration and
supporting others within our community. Providing a positive experience for
other community members can have a much more significant impact than simply
providing the correct answer.
## Our Responsibilities
Project leaders are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project leaders have the right and responsibility to remove, edit, or
reject messages, comments, commits, code, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any community member for other behaviors that they deem
inappropriate, threatening, offensive, or harmful.
## Moderation
Instances of behaviors that violate the Adafruit Community Code of Conduct
may be reported by any member of the community. Community members are
encouraged to report these situations, including situations they witness
involving other community members.
You may report in the following ways:
In any situation, you may send an email to <support@adafruit.com>.
On the Adafruit Discord, you may send an open message from any channel
to all Community Helpers by tagging @community helpers. You may also send an
open message from any channel, or a direct message to @kattni#1507,
@tannewt#4653, @Dan Halbert#1614, @cater#2442, @sommersoft#0222, or
@Andon#8175.
Email and direct message reports will be kept confidential.
In situations on Discord where the issue is particularly egregious, possibly
illegal, requires immediate action, or violates the Discord terms of service,
you should also report the message directly to Discord.
These are the steps for upholding our communitys standards of conduct.
1. Any member of the community may report any situation that violates the
Adafruit Community Code of Conduct. All reports will be reviewed and
investigated.
2. If the behavior is an egregious violation, the community member who
committed the violation may be banned immediately, without warning.
3. Otherwise, moderators will first respond to such behavior with a warning.
4. Moderators follow a soft "three strikes" policy - the community member may
be given another chance, if they are receptive to the warning and change their
behavior.
5. If the community member is unreceptive or unreasonable when warned by a
moderator, or the warning goes unheeded, they may be banned for a first or
second offense. Repeated offenses will result in the community member being
banned.
## Scope
This Code of Conduct and the enforcement policies listed above apply to all
Adafruit Community venues. This includes but is not limited to any community
spaces (both public and private), the entire Adafruit Discord server, and
Adafruit GitHub repositories. Examples of Adafruit Community spaces include
but are not limited to meet-ups, audio chats on the Adafruit Discord, or
interaction at a conference.
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. As a community
member, you are representing our community, and are expected to behave
accordingly.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 1.4, available at
<https://www.contributor-covenant.org/version/1/4/code-of-conduct.html>,
and the [Rust Code of Conduct](https://www.rust-lang.org/en-US/conduct.html).
For other projects adopting the Adafruit Community Code of
Conduct, please contact the maintainers of those projects for enforcement.
If you wish to use this code of conduct for your own project, consider
explicitly mentioning your moderation policy or making a copy with your
own moderation policy so as to avoid confusion.

View file

@ -1,5 +1,5 @@
name=Adafruit APDS9960 Library name=Adafruit APDS9960 Library
version=1.0.5 version=1.1.1
author=Adafruit author=Adafruit
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for the Adafruit APDS9960 gesture/proximity/color/light sensor. sentence=This is a library for the Adafruit APDS9960 gesture/proximity/color/light sensor.

View file

@ -0,0 +1,26 @@
Software License Agreement (BSD License)
Copyright (c) 2012, Adafruit Industries
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holders nor the
names of its contributors may be used to endorse or promote products
derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,75 +1,121 @@
/***************************************************************************
This is a library for the BME280 humidity, temperature & pressure sensor
Designed specifically to work with the Adafruit BME280 Breakout
----> http://www.adafruit.com/products/2650
These sensors use I2C or SPI to communicate, 2 or 4 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 Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#include "Arduino.h"
#include <Wire.h>
#include <SPI.h>
#include "Adafruit_BME280.h"
/***************************************************************************
PRIVATE FUNCTIONS
***************************************************************************/
Adafruit_BME280::Adafruit_BME280()
: _cs(-1), _mosi(-1), _miso(-1), _sck(-1)
{ }
Adafruit_BME280::Adafruit_BME280(int8_t cspin)
: _cs(cspin), _mosi(-1), _miso(-1), _sck(-1)
{ }
Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin)
: _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin)
{ }
/**************************************************************************/
/*! /*!
@brief Initialise sensor with given parameters / settings * @file Adafruit_BME280.cpp
*
* @mainpage Adafruit BME280 humidity, temperature & pressure sensor
*
* @section intro_sec Introduction
*
* Driver for the BME280 humidity, temperature & pressure sensor
*
* These sensors use I2C or SPI to communicate, 2 or 4 pins are required
* to interface.
*
* Designed specifically to work with the Adafruit BME280 Breakout
* ----> http://www.adafruit.com/products/2652
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* @section author Author
*
* Written by Kevin "KTOWN" Townsend for Adafruit Industries.
*
* @section license License
*
* BSD license, all text here must be included in any redistribution.
* See the LICENSE file for details.
*
*/ */
/**************************************************************************/
bool Adafruit_BME280::begin(TwoWire *theWire) #include "Adafruit_BME280.h"
{ #include "Arduino.h"
#include <SPI.h>
#include <Wire.h>
/*!
* @brief class constructor
*/
Adafruit_BME280::Adafruit_BME280() : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) {}
/*!
* @brief class constructor if using hardware SPI
* @param cspin the chip select pin to use
* @param *theSPI
* optional SPI object
*/
Adafruit_BME280::Adafruit_BME280(int8_t cspin, SPIClass *theSPI) {
_cs = cspin;
_mosi = _miso = _sck = -1;
_spi = theSPI;
}
/*!
* @brief class constructor if using software SPI
* @param cspin the chip select pin to use
* @param mosipin the MOSI pin to use
* @param misopin the MISO pin to use
* @param sckpin the SCK pin to use
*/
Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin,
int8_t sckpin)
: _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) {}
/*!
* @brief Initialise sensor with given parameters / settings
* @param theWire the I2C object to use
* @returns true on success, false otherwise
*/
bool Adafruit_BME280::begin(TwoWire *theWire) {
_wire = theWire; _wire = theWire;
_i2caddr = BME280_ADDRESS; _i2caddr = BME280_ADDRESS;
return init(); return init();
} }
bool Adafruit_BME280::begin(uint8_t addr) /*!
{ * @brief Initialise sensor with given parameters / settings
* @param addr the I2C address the device can be found on
* @returns true on success, false otherwise
*/
bool Adafruit_BME280::begin(uint8_t addr) {
_i2caddr = addr; _i2caddr = addr;
_wire = &Wire; _wire = &Wire;
return init(); return init();
} }
bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) /*!
{ * @brief Initialise sensor with given parameters / settings
* @param addr the I2C address the device can be found on
* @param theWire the I2C object to use
* @returns true on success, false otherwise
*/
bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) {
_i2caddr = addr; _i2caddr = addr;
_wire = theWire; _wire = theWire;
return init(); return init();
} }
bool Adafruit_BME280::begin(void) /*!
{ * @brief Initialise sensor with given parameters / settings
* @returns true on success, false otherwise
*/
bool Adafruit_BME280::begin(void) {
bool status = false;
_i2caddr = BME280_ADDRESS; _i2caddr = BME280_ADDRESS;
_wire = &Wire; _wire = &Wire;
return init(); status = init();
if (!status) {
_i2caddr = BME280_ADDRESS_ALTERNATE;
status = init();
}
return status;
} }
bool Adafruit_BME280::init() /*!
{ * @brief Initialise sensor with given parameters / settings
* @returns true on success, false otherwise
*/
bool Adafruit_BME280::init() {
// init I2C or SPI sensor interface // init I2C or SPI sensor interface
if (_cs == -1) { if (_cs == -1) {
// I2C // I2C
@ -79,7 +125,7 @@ bool Adafruit_BME280::init()
pinMode(_cs, OUTPUT); pinMode(_cs, OUTPUT);
if (_sck == -1) { if (_sck == -1) {
// hardware SPI // hardware SPI
SPI.begin(); _spi->begin();
} else { } else {
// software SPI // software SPI
pinMode(_sck, OUTPUT); pinMode(_sck, OUTPUT);
@ -89,7 +135,8 @@ bool Adafruit_BME280::init()
} }
// check if sensor, i.e. the chip ID is correct // check if sensor, i.e. the chip ID is correct
if (read8(BME280_REGISTER_CHIPID) != 0x60) _sensorID = read8(BME280_REGISTER_CHIPID);
if (_sensorID != 0x60)
return false; return false;
// reset the device using soft-reset // reset the device using soft-reset
@ -112,16 +159,18 @@ bool Adafruit_BME280::init()
return true; return true;
} }
/**************************************************************************/
/*! /*!
@brief setup sensor with given parameters / settings * @brief setup sensor with given parameters / settings
*
This is simply a overload to the normal begin()-function, so SPI users * This is simply a overload to the normal begin()-function, so SPI users
don't get confused about the library requiring an address. * don't get confused about the library requiring an address.
* @param mode the power mode to use for the sensor
* @param tempSampling the temp samping rate to use
* @param pressSampling the pressure sampling rate to use
* @param humSampling the humidity sampling rate to use
* @param filter the filter mode to use
* @param duration the standby duration to use
*/ */
/**************************************************************************/
void Adafruit_BME280::setSampling(sensor_mode mode, void Adafruit_BME280::setSampling(sensor_mode mode,
sensor_sampling tempSampling, sensor_sampling tempSampling,
sensor_sampling pressSampling, sensor_sampling pressSampling,
@ -132,29 +181,28 @@ void Adafruit_BME280::setSampling(sensor_mode mode,
_measReg.osrs_t = tempSampling; _measReg.osrs_t = tempSampling;
_measReg.osrs_p = pressSampling; _measReg.osrs_p = pressSampling;
_humReg.osrs_h = humSampling; _humReg.osrs_h = humSampling;
_configReg.filter = filter; _configReg.filter = filter;
_configReg.t_sb = duration; _configReg.t_sb = duration;
// you must make sure to also set REGISTER_CONTROL after setting the // you must make sure to also set REGISTER_CONTROL after setting the
// CONTROLHUMID register, otherwise the values won't be applied (see DS 5.4.3) // CONTROLHUMID register, otherwise the values won't be applied (see
// DS 5.4.3)
write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); write8(BME280_REGISTER_CONTROLHUMID, _humReg.get());
write8(BME280_REGISTER_CONFIG, _configReg.get()); write8(BME280_REGISTER_CONFIG, _configReg.get());
write8(BME280_REGISTER_CONTROL, _measReg.get()); write8(BME280_REGISTER_CONTROL, _measReg.get());
} }
/**************************************************************************/
/*! /*!
@brief Encapsulate hardware and software SPI transfer into one function * @brief Encapsulate hardware and software SPI transfer into one
* function
* @param x the data byte to transfer
* @returns the data byte read from the device
*/ */
/**************************************************************************/
uint8_t Adafruit_BME280::spixfer(uint8_t x) { uint8_t Adafruit_BME280::spixfer(uint8_t x) {
// hardware SPI // hardware SPI
if (_sck == -1) if (_sck == -1)
return SPI.transfer(x); return _spi->transfer(x);
// software SPI // software SPI
uint8_t reply = 0; uint8_t reply = 0;
@ -169,12 +217,11 @@ uint8_t Adafruit_BME280::spixfer(uint8_t x) {
return reply; return reply;
} }
/**************************************************************************/
/*! /*!
@brief Writes an 8 bit value over I2C or SPI * @brief Writes an 8 bit value over I2C or SPI
* @param reg the register address to write to
* @param value the value to write to the register
*/ */
/**************************************************************************/
void Adafruit_BME280::write8(byte reg, byte value) { void Adafruit_BME280::write8(byte reg, byte value) {
if (_cs == -1) { if (_cs == -1) {
_wire->beginTransmission((uint8_t)_i2caddr); _wire->beginTransmission((uint8_t)_i2caddr);
@ -183,22 +230,21 @@ void Adafruit_BME280::write8(byte reg, byte value) {
_wire->endTransmission(); _wire->endTransmission();
} else { } else {
if (_sck == -1) if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW); digitalWrite(_cs, LOW);
spixfer(reg & ~0x80); // write, bit 7 low spixfer(reg & ~0x80); // write, bit 7 low
spixfer(value); spixfer(value);
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
if (_sck == -1) if (_sck == -1)
SPI.endTransaction(); // release the SPI bus _spi->endTransaction(); // release the SPI bus
} }
} }
/**************************************************************************/
/*! /*!
@brief Reads an 8 bit value over I2C or SPI * @brief Reads an 8 bit value over I2C or SPI
* @param reg the register address to read from
* @returns the data byte read from the device
*/ */
/**************************************************************************/
uint8_t Adafruit_BME280::read8(byte reg) { uint8_t Adafruit_BME280::read8(byte reg) {
uint8_t value; uint8_t value;
@ -210,25 +256,23 @@ uint8_t Adafruit_BME280::read8(byte reg) {
value = _wire->read(); value = _wire->read();
} else { } else {
if (_sck == -1) if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW); digitalWrite(_cs, LOW);
spixfer(reg | 0x80); // read, bit 7 high spixfer(reg | 0x80); // read, bit 7 high
value = spixfer(0); value = spixfer(0);
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
if (_sck == -1) if (_sck == -1)
SPI.endTransaction(); // release the SPI bus _spi->endTransaction(); // release the SPI bus
} }
return value; return value;
} }
/**************************************************************************/
/*! /*!
@brief Reads a 16 bit value over I2C or SPI * @brief Reads a 16 bit value over I2C or SPI
* @param reg the register address to read from
* @returns the 16 bit data value read from the device
*/ */
/**************************************************************************/ uint16_t Adafruit_BME280::read16(byte reg) {
uint16_t Adafruit_BME280::read16(byte reg)
{
uint16_t value; uint16_t value;
if (_cs == -1) { if (_cs == -1) {
@ -239,59 +283,50 @@ uint16_t Adafruit_BME280::read16(byte reg)
value = (_wire->read() << 8) | _wire->read(); value = (_wire->read() << 8) | _wire->read();
} else { } else {
if (_sck == -1) if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW); digitalWrite(_cs, LOW);
spixfer(reg | 0x80); // read, bit 7 high spixfer(reg | 0x80); // read, bit 7 high
value = (spixfer(0) << 8) | spixfer(0); value = (spixfer(0) << 8) | spixfer(0);
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
if (_sck == -1) if (_sck == -1)
SPI.endTransaction(); // release the SPI bus _spi->endTransaction(); // release the SPI bus
} }
return value; return value;
} }
/**************************************************************************/
/*! /*!
* @brief Reads a signed 16 bit little endian value over I2C or SPI
* @param reg the register address to read from
* @returns the 16 bit data value read from the device
*/ */
/**************************************************************************/
uint16_t Adafruit_BME280::read16_LE(byte reg) { uint16_t Adafruit_BME280::read16_LE(byte reg) {
uint16_t temp = read16(reg); uint16_t temp = read16(reg);
return (temp >> 8) | (temp << 8); return (temp >> 8) | (temp << 8);
} }
/**************************************************************************/
/*! /*!
@brief Reads a signed 16 bit value over I2C or SPI * @brief Reads a signed 16 bit value over I2C or SPI
* @param reg the register address to read from
* @returns the 16 bit data value read from the device
*/ */
/**************************************************************************/ int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); }
int16_t Adafruit_BME280::readS16(byte reg)
{
return (int16_t)read16(reg);
}
/**************************************************************************/
/*! /*!
* @brief Reads a signed little endian 16 bit value over I2C or SPI
* @param reg the register address to read from
* @returns the 16 bit data value read from the device
*/ */
/**************************************************************************/ int16_t Adafruit_BME280::readS16_LE(byte reg) {
int16_t Adafruit_BME280::readS16_LE(byte reg)
{
return (int16_t)read16_LE(reg); return (int16_t)read16_LE(reg);
} }
/**************************************************************************/
/*! /*!
@brief Reads a 24 bit value over I2C * @brief Reads a 24 bit value over I2C
* @param reg the register address to read from
* @returns the 24 bit data value read from the device
*/ */
/**************************************************************************/ uint32_t Adafruit_BME280::read24(byte reg) {
uint32_t Adafruit_BME280::read24(byte reg)
{
uint32_t value; uint32_t value;
if (_cs == -1) { if (_cs == -1) {
@ -307,7 +342,7 @@ uint32_t Adafruit_BME280::read24(byte reg)
value |= _wire->read(); value |= _wire->read();
} else { } else {
if (_sck == -1) if (_sck == -1)
SPI.beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0));
digitalWrite(_cs, LOW); digitalWrite(_cs, LOW);
spixfer(reg | 0x80); // read, bit 7 high spixfer(reg | 0x80); // read, bit 7 high
@ -319,20 +354,16 @@ uint32_t Adafruit_BME280::read24(byte reg)
digitalWrite(_cs, HIGH); digitalWrite(_cs, HIGH);
if (_sck == -1) if (_sck == -1)
SPI.endTransaction(); // release the SPI bus _spi->endTransaction(); // release the SPI bus
} }
return value; return value;
} }
/**************************************************************************/
/*! /*!
@brief Take a new measurement (only possible in forced mode) * @brief Take a new measurement (only possible in forced mode)
*/ */
/**************************************************************************/ void Adafruit_BME280::takeForcedMeasurement() {
void Adafruit_BME280::takeForcedMeasurement()
{
// If we are in forced mode, the BME sensor goes back to sleep after each // If we are in forced mode, the BME sensor goes back to sleep after each
// measurement and we need to set it to forced mode once at this point, so // measurement and we need to set it to forced mode once at this point, so
// it will take the next measurement and then return to sleep again. // it will take the next measurement and then return to sleep again.
@ -347,14 +378,10 @@ void Adafruit_BME280::takeForcedMeasurement()
} }
} }
/**************************************************************************/
/*! /*!
@brief Reads the factory-set coefficients * @brief Reads the factory-set coefficients
*/ */
/**************************************************************************/ void Adafruit_BME280::readCoefficients(void) {
void Adafruit_BME280::readCoefficients(void)
{
_bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1);
_bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2);
_bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3);
@ -372,31 +399,28 @@ void Adafruit_BME280::readCoefficients(void)
_bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1);
_bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2);
_bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3);
_bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) | (read8(BME280_REGISTER_DIG_H4+1) & 0xF); _bme280_calib.dig_H4 = (read8(BME280_REGISTER_DIG_H4) << 4) |
_bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5+1) << 4) | (read8(BME280_REGISTER_DIG_H5) >> 4); (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
_bme280_calib.dig_H5 = (read8(BME280_REGISTER_DIG_H5 + 1) << 4) |
(read8(BME280_REGISTER_DIG_H5) >> 4);
_bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6);
} }
/**************************************************************************/
/*! /*!
@brief return true if chip is busy reading cal data * @brief return true if chip is busy reading cal data
* @returns true if reading calibration, false otherwise
*/ */
/**************************************************************************/ bool Adafruit_BME280::isReadingCalibration(void) {
bool Adafruit_BME280::isReadingCalibration(void)
{
uint8_t const rStatus = read8(BME280_REGISTER_STATUS); uint8_t const rStatus = read8(BME280_REGISTER_STATUS);
return (rStatus & (1 << 0)) != 0; return (rStatus & (1 << 0)) != 0;
} }
/**************************************************************************/
/*! /*!
@brief Returns the temperature from the sensor * @brief Returns the temperature from the sensor
* @returns the temperature read from the device
*/ */
/**************************************************************************/ float Adafruit_BME280::readTemperature(void) {
float Adafruit_BME280::readTemperature(void)
{
int32_t var1, var2; int32_t var1, var2;
int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
@ -405,11 +429,14 @@ float Adafruit_BME280::readTemperature(void)
adc_T >>= 4; adc_T >>= 4;
var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib.dig_T1 << 1))) * var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib.dig_T1 << 1))) *
((int32_t)_bme280_calib.dig_T2)) >> 11; ((int32_t)_bme280_calib.dig_T2)) >>
11;
var2 = (((((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1)) * var2 = (((((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1)) *
((adc_T>>4) - ((int32_t)_bme280_calib.dig_T1))) >> 12) * ((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1))) >>
((int32_t)_bme280_calib.dig_T3)) >> 14; 12) *
((int32_t)_bme280_calib.dig_T3)) >>
14;
t_fine = var1 + var2; t_fine = var1 + var2;
@ -417,12 +444,10 @@ float Adafruit_BME280::readTemperature(void)
return T / 100; return T / 100;
} }
/**************************************************************************/
/*! /*!
@brief Returns the temperature from the sensor * @brief Returns the pressure from the sensor
* @returns the pressure value (in Pascal) read from the device
*/ */
/**************************************************************************/
float Adafruit_BME280::readPressure(void) { float Adafruit_BME280::readPressure(void) {
int64_t var1, var2, p; int64_t var1, var2, p;
@ -439,7 +464,8 @@ float Adafruit_BME280::readPressure(void) {
var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35); var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35);
var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) + var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) +
((var1 * (int64_t)_bme280_calib.dig_P2) << 12); ((var1 * (int64_t)_bme280_calib.dig_P2) << 12);
var1 = (((((int64_t)1)<<47)+var1))*((int64_t)_bme280_calib.dig_P1)>>33; var1 =
(((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 33;
if (var1 == 0) { if (var1 == 0) {
return 0; // avoid exception caused by division by zero return 0; // avoid exception caused by division by zero
@ -453,12 +479,10 @@ float Adafruit_BME280::readPressure(void) {
return (float)p / 256; return (float)p / 256;
} }
/**************************************************************************/
/*! /*!
@brief Returns the humidity from the sensor * @brief Returns the humidity from the sensor
* @returns the humidity value read from the device
*/ */
/**************************************************************************/
float Adafruit_BME280::readHumidity(void) { float Adafruit_BME280::readHumidity(void) {
readTemperature(); // must be done first to get t_fine readTemperature(); // must be done first to get t_fine
@ -471,13 +495,21 @@ float Adafruit_BME280::readHumidity(void) {
v_x1_u32r = (t_fine - ((int32_t)76800)); v_x1_u32r = (t_fine - ((int32_t)76800));
v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) -
(((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) * (((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) +
((int32_t)16384)) >>
15) *
(((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * (((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) *
(((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) + (((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) +
((int32_t)2097152)) * ((int32_t)_bme280_calib.dig_H2) + 8192) >> 14)); ((int32_t)32768))) >>
10) +
((int32_t)2097152)) *
((int32_t)_bme280_calib.dig_H2) +
8192) >>
14));
v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
((int32_t)_bme280_calib.dig_H1)) >> 4)); ((int32_t)_bme280_calib.dig_H1)) >>
4));
v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
@ -485,18 +517,13 @@ float Adafruit_BME280::readHumidity(void) {
return h / 1024.0; return h / 1024.0;
} }
/**************************************************************************/
/*! /*!
Calculates the altitude (in meters) from the specified atmospheric * Calculates the altitude (in meters) from the specified atmospheric
pressure (in hPa), and sea-level pressure (in hPa). * pressure (in hPa), and sea-level pressure (in hPa).
* @param seaLevel Sea-level pressure in hPa
@param seaLevel Sea-level pressure in hPa * @returns the altitude value read from the device
@param atmospheric Atmospheric pressure in hPa
*/ */
/**************************************************************************/ float Adafruit_BME280::readAltitude(float seaLevel) {
float Adafruit_BME280::readAltitude(float seaLevel)
{
// Equation taken from BMP180 datasheet (page 16): // Equation taken from BMP180 datasheet (page 16):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
@ -508,17 +535,14 @@ float Adafruit_BME280::readAltitude(float seaLevel)
return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903));
} }
/**************************************************************************/
/*! /*!
Calculates the pressure at sea level (in hPa) from the specified altitude * Calculates the pressure at sea level (in hPa) from the specified
(in meters), and atmospheric pressure (in hPa). * altitude (in meters), and atmospheric pressure (in hPa).
@param altitude Altitude in meters * @param altitude Altitude in meters
@param atmospheric Atmospheric pressure in hPa * @param atmospheric Atmospheric pressure in hPa
* @returns the pressure at sea level (in hPa) from the specified altitude
*/ */
/**************************************************************************/ float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) {
float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric)
{
// Equation taken from BMP180 datasheet (page 17): // Equation taken from BMP180 datasheet (page 17):
// http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf
@ -528,3 +552,9 @@ float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric)
return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255); return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255);
} }
/*!
* Returns Sensor ID found by init() for diagnostics
* @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280
*/
uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; }

View file

@ -1,42 +1,45 @@
/*************************************************************************** /*!
This is a library for the BME280 humidity, temperature & pressure sensor * @file Adafruit_BME280.h
*
* Designed specifically to work with the Adafruit BME280 Breakout
* ----> http://www.adafruit.com/products/2650
*
* These sensors use I2C or SPI to communicate, 2 or 4 pins are required
* to interface.
*
* Adafruit invests time and resources providing this open source code,
* please support Adafruit and open-source hardware by purchasing
* products from Adafruit!
*
* Written by Kevin "KTOWN" Townsend for Adafruit Industries.
*
* BSD license, all text here must be included in any redistribution.
* See the LICENSE file for details.
*
*/
Designed specifically to work with the Adafruit BME280 Breakout
----> http://www.adafruit.com/products/2650
These sensors use I2C or SPI to communicate, 2 or 4 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 Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution
***************************************************************************/
#ifndef __BME280_H__ #ifndef __BME280_H__
#define __BME280_H__ #define __BME280_H__
#if (ARDUINO >= 100)
#include "Arduino.h" #include "Arduino.h"
#else
#include "WProgram.h"
#endif
#include <Adafruit_Sensor.h> #include <Adafruit_Sensor.h>
#include <SPI.h>
#include <Wire.h> #include <Wire.h>
/*========================================================================= /*!
I2C ADDRESS/BITS * @brief default I2C address
-----------------------------------------------------------------------*/ */
#define BME280_ADDRESS (0x77) #define BME280_ADDRESS (0x77) // Primary I2C Address
/*=========================================================================*/ /*!
* @brief alternate I2C address
*/
#define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address
/*========================================================================= /*!
REGISTERS * @brief Register addresses
-----------------------------------------------------------------------*/ */
enum enum {
{
BME280_REGISTER_DIG_T1 = 0x88, BME280_REGISTER_DIG_T1 = 0x88,
BME280_REGISTER_DIG_T2 = 0x8A, BME280_REGISTER_DIG_T2 = 0x8A,
BME280_REGISTER_DIG_T3 = 0x8C, BME280_REGISTER_DIG_T3 = 0x8C,
@ -73,33 +76,32 @@
BME280_REGISTER_HUMIDDATA = 0xFD BME280_REGISTER_HUMIDDATA = 0xFD
}; };
/*=========================================================================*/ /**************************************************************************/
/*!
@brief calibration data
*/
/**************************************************************************/
typedef struct {
uint16_t dig_T1; ///< temperature compensation value
int16_t dig_T2; ///< temperature compensation value
int16_t dig_T3; ///< temperature compensation value
/*========================================================================= uint16_t dig_P1; ///< pressure compensation value
CALIBRATION DATA int16_t dig_P2; ///< pressure compensation value
-----------------------------------------------------------------------*/ int16_t dig_P3; ///< pressure compensation value
typedef struct int16_t dig_P4; ///< pressure compensation value
{ int16_t dig_P5; ///< pressure compensation value
uint16_t dig_T1; int16_t dig_P6; ///< pressure compensation value
int16_t dig_T2; int16_t dig_P7; ///< pressure compensation value
int16_t dig_T3; int16_t dig_P8; ///< pressure compensation value
int16_t dig_P9; ///< pressure compensation value
uint16_t dig_P1; uint8_t dig_H1; ///< humidity compensation value
int16_t dig_P2; int16_t dig_H2; ///< humidity compensation value
int16_t dig_P3; uint8_t dig_H3; ///< humidity compensation value
int16_t dig_P4; int16_t dig_H4; ///< humidity compensation value
int16_t dig_P5; int16_t dig_H5; ///< humidity compensation value
int16_t dig_P6; int8_t dig_H6; ///< humidity compensation value
int16_t dig_P7;
int16_t dig_P8;
int16_t dig_P9;
uint8_t dig_H1;
int16_t dig_H2;
uint8_t dig_H3;
int16_t dig_H4;
int16_t dig_H5;
int8_t dig_H6;
} bme280_calib_data; } bme280_calib_data;
/*=========================================================================*/ /*=========================================================================*/
@ -124,8 +126,18 @@ class Adafruit_BME280_Unified : public Adafruit_Sensor
*/ */
/**************************************************************************/
/*!
@brief Class that stores state and functions for interacting with BME280 IC
*/
/**************************************************************************/
class Adafruit_BME280 { class Adafruit_BME280 {
public: public:
/**************************************************************************/
/*!
@brief sampling rates
*/
/**************************************************************************/
enum sensor_sampling { enum sensor_sampling {
SAMPLING_NONE = 0b000, SAMPLING_NONE = 0b000,
SAMPLING_X1 = 0b001, SAMPLING_X1 = 0b001,
@ -135,12 +147,22 @@ class Adafruit_BME280 {
SAMPLING_X16 = 0b101 SAMPLING_X16 = 0b101
}; };
/**************************************************************************/
/*!
@brief power modes
*/
/**************************************************************************/
enum sensor_mode { enum sensor_mode {
MODE_SLEEP = 0b00, MODE_SLEEP = 0b00,
MODE_FORCED = 0b01, MODE_FORCED = 0b01,
MODE_NORMAL = 0b11 MODE_NORMAL = 0b11
}; };
/**************************************************************************/
/*!
@brief filter values
*/
/**************************************************************************/
enum sensor_filter { enum sensor_filter {
FILTER_OFF = 0b000, FILTER_OFF = 0b000,
FILTER_X2 = 0b001, FILTER_X2 = 0b001,
@ -149,7 +171,11 @@ class Adafruit_BME280 {
FILTER_X16 = 0b100 FILTER_X16 = 0b100
}; };
// standby durations in ms /**************************************************************************/
/*!
@brief standby duration in ms
*/
/**************************************************************************/
enum standby_duration { enum standby_duration {
STANDBY_MS_0_5 = 0b000, STANDBY_MS_0_5 = 0b000,
STANDBY_MS_10 = 0b110, STANDBY_MS_10 = 0b110,
@ -162,11 +188,12 @@ class Adafruit_BME280 {
}; };
// constructors // constructors
Adafruit_BME280(void); Adafruit_BME280();
Adafruit_BME280(int8_t cspin); Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI);
Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin,
int8_t sckpin);
bool begin(void); bool begin();
bool begin(TwoWire *theWire); bool begin(TwoWire *theWire);
bool begin(uint8_t addr); bool begin(uint8_t addr);
bool begin(uint8_t addr, TwoWire *theWire); bool begin(uint8_t addr, TwoWire *theWire);
@ -177,8 +204,7 @@ class Adafruit_BME280 {
sensor_sampling pressSampling = SAMPLING_X16, sensor_sampling pressSampling = SAMPLING_X16,
sensor_sampling humSampling = SAMPLING_X16, sensor_sampling humSampling = SAMPLING_X16,
sensor_filter filter = FILTER_OFF, sensor_filter filter = FILTER_OFF,
standby_duration duration = STANDBY_MS_0_5 standby_duration duration = STANDBY_MS_0_5);
);
void takeForcedMeasurement(); void takeForcedMeasurement();
float readTemperature(void); float readTemperature(void);
@ -187,10 +213,11 @@ class Adafruit_BME280 {
float readAltitude(float seaLevel); float readAltitude(float seaLevel);
float seaLevelForAltitude(float altitude, float pressure); float seaLevelForAltitude(float altitude, float pressure);
uint32_t sensorID(void);
protected:
private: TwoWire *_wire; //!< pointer to a TwoWire object
TwoWire *_wire; SPIClass *_spi; //!< pointer to SPI object
void readCoefficients(void); void readCoefficients(void);
bool isReadingCalibration(void); bool isReadingCalibration(void);
uint8_t spixfer(uint8_t x); uint8_t spixfer(uint8_t x);
@ -203,15 +230,24 @@ class Adafruit_BME280 {
uint16_t read16_LE(byte reg); // little endian uint16_t read16_LE(byte reg); // little endian
int16_t readS16_LE(byte reg); // little endian int16_t readS16_LE(byte reg); // little endian
uint8_t _i2caddr; uint8_t _i2caddr; //!< I2C addr for the TwoWire interface
int32_t _sensorID; int32_t _sensorID; //!< ID of the BME Sensor
int32_t t_fine; int32_t t_fine; //!< temperature with high resolution, stored as an attribute
//!< as this is used for temperature compensation reading
//!< humidity and pressure
int8_t _cs, _mosi, _miso, _sck; int8_t _cs; //!< for the SPI interface
int8_t _mosi; //!< for the SPI interface
int8_t _miso; //!< for the SPI interface
int8_t _sck; //!< for the SPI interface
bme280_calib_data _bme280_calib; bme280_calib_data _bme280_calib; //!< here calibration data is stored
// The config register /**************************************************************************/
/*!
@brief config register
*/
/**************************************************************************/
struct config { struct config {
// inactive duration (standby time) in normal mode // inactive duration (standby time) in normal mode
// 000 = 0.5 ms // 000 = 0.5 ms
@ -222,7 +258,7 @@ class Adafruit_BME280 {
// 101 = 1000 ms // 101 = 1000 ms
// 110 = 10 ms // 110 = 10 ms
// 111 = 20 ms // 111 = 20 ms
unsigned int t_sb : 3; unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode
// filter settings // filter settings
// 000 = filter off // 000 = filter off
@ -230,20 +266,22 @@ class Adafruit_BME280 {
// 010 = 4x filter // 010 = 4x filter
// 011 = 8x filter // 011 = 8x filter
// 100 and above = 16x filter // 100 and above = 16x filter
unsigned int filter : 3; unsigned int filter : 3; ///< filter settings
// unused - don't set // unused - don't set
unsigned int none : 1; unsigned int none : 1; ///< unused - don't set
unsigned int spi3w_en : 1; unsigned int spi3w_en : 1; ///< unused - don't set
unsigned int get() { /// @return combined config register
return (t_sb << 5) | (filter << 3) | spi3w_en; unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; }
}
}; };
config _configReg; config _configReg; //!< config register object
/**************************************************************************/
// The ctrl_meas register /*!
@brief ctrl_meas register
*/
/**************************************************************************/
struct ctrl_meas { struct ctrl_meas {
// temperature oversampling // temperature oversampling
// 000 = skipped // 000 = skipped
@ -252,7 +290,7 @@ class Adafruit_BME280 {
// 011 = x4 // 011 = x4
// 100 = x8 // 100 = x8
// 101 and above = x16 // 101 and above = x16
unsigned int osrs_t : 3; unsigned int osrs_t : 3; ///< temperature oversampling
// pressure oversampling // pressure oversampling
// 000 = skipped // 000 = skipped
@ -261,24 +299,26 @@ class Adafruit_BME280 {
// 011 = x4 // 011 = x4
// 100 = x8 // 100 = x8
// 101 and above = x16 // 101 and above = x16
unsigned int osrs_p : 3; unsigned int osrs_p : 3; ///< pressure oversampling
// device mode // device mode
// 00 = sleep // 00 = sleep
// 01 or 10 = forced // 01 or 10 = forced
// 11 = normal // 11 = normal
unsigned int mode : 2; unsigned int mode : 2; ///< device mode
unsigned int get() { /// @return combined ctrl register
return (osrs_t << 5) | (osrs_p << 3) | mode; unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; }
}
}; };
ctrl_meas _measReg; ctrl_meas _measReg; //!< measurement register object
/**************************************************************************/
// The ctrl_hum register /*!
@brief ctrl_hum register
*/
/**************************************************************************/
struct ctrl_hum { struct ctrl_hum {
// unused - don't set /// unused - don't set
unsigned int none : 5; unsigned int none : 5;
// pressure oversampling // pressure oversampling
@ -288,13 +328,12 @@ class Adafruit_BME280 {
// 011 = x4 // 011 = x4
// 100 = x8 // 100 = x8
// 101 and above = x16 // 101 and above = x16
unsigned int osrs_h : 3; unsigned int osrs_h : 3; ///< pressure oversampling
unsigned int get() { /// @return combined ctrl hum register
return (osrs_h); unsigned int get() { return (osrs_h); }
}
}; };
ctrl_hum _humReg; ctrl_hum _humReg; //!< hum register object
}; };
#endif #endif

View file

@ -0,0 +1,27 @@
Copyright (c) 2015, Limor Fried & Kevin Townsend for Adafruit Industries
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of Adafruit Industries nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

View file

@ -1,3 +1,7 @@
# Adafruit BME280 Library [![Build Status](https://travis-ci.com/adafruit/Adafruit_BME280_Library.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_BME280_Library)
<a href="http://www.adafruit.com/products/2652"><img src="./assets/board.jpg" width="500"/></a>
This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor
Designed specifically to work with the Adafruit BME280 Breakout Designed specifically to work with the Adafruit BME280 Breakout
@ -25,35 +29,3 @@ You may need to create the libraries subfolder if its your first library. Restar
We also have a great tutorial on Arduino library installation at: We also have a great tutorial on Arduino library installation at:
http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use http://learn.adafruit.com/adafruit-all-about-arduino-libraries-install-use
<!-- START COMPATIBILITY TABLE -->
## Compatibility
MCU | Tested Works | Doesn't Work | Not Tested | Notes
------------------ | :----------: | :----------: | :---------: | -----
Atmega328 @ 16MHz | X | | |
Atmega328 @ 12MHz | X | | |
Atmega32u4 @ 16MHz | X | | | Use SDA/SCL on pins D2 &amp; D3
Atmega32u4 @ 8MHz | X | | | Use SDA/SCL on pins D2 &amp; D3
ESP8266 | X | | | I2C: just works, SPI: SDA/SCL default to pins 4 &amp; 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL)
ESP32 | X | | | I2C: just works, SPI: SDA/SCL default to pins 4 &amp; 5 but any two pins can be assigned as SDA/SCL using Wire.begin(SDA,SCL)
Atmega2560 @ 16MHz | X | | | Use SDA/SCL on pins 20 &amp; 21
ATSAM3X8E | X | | | Use SDA/SCL on pins 20 &amp; 21
ATSAM21D | X | | |
ATtiny85 @ 16MHz | | X | |
ATtiny85 @ 8MHz | | X | |
Intel Curie @ 32MHz | | | X |
STM32F2 | | | X |
* ATmega328 @ 16MHz : Arduino UNO, Adafruit Pro Trinket 5V, Adafruit Metro 328, Adafruit Metro Mini
* ATmega328 @ 12MHz : Adafruit Pro Trinket 3V
* ATmega32u4 @ 16MHz : Arduino Leonardo, Arduino Micro, Arduino Yun, Teensy 2.0
* ATmega32u4 @ 8MHz : Adafruit Flora, Bluefruit Micro
* ESP8266 : Adafruit Huzzah
* ATmega2560 @ 16MHz : Arduino Mega
* ATSAM3X8E : Arduino Due
* ATSAM21D : Arduino Zero, M0 Pro
* ATtiny85 @ 16MHz : Adafruit Trinket 5V
* ATtiny85 @ 8MHz : Adafruit Gemma, Arduino Gemma, Adafruit Trinket 3V
<!-- END COMPATIBILITY TABLE -->

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

View file

@ -13,6 +13,7 @@
Written by Limor Fried & Kevin Townsend for Adafruit Industries. Written by Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution BSD license, all text above must be included in any redistribution
See the LICENSE file for details.
***************************************************************************/ ***************************************************************************/
#include <Wire.h> #include <Wire.h>
@ -37,7 +38,7 @@ void setup() {
Serial.begin(9600); Serial.begin(9600);
Serial.println(F("BME280 test")); Serial.println(F("BME280 test"));
if (! bme.begin(&Wire1)) { if (! bme.begin(&Wire)) {
Serial.println("Could not find a valid BME280 sensor, check wiring!"); Serial.println("Could not find a valid BME280 sensor, check wiring!");
while (1); while (1);
} }
@ -101,6 +102,7 @@ void setup() {
// = 40ms (25Hz) // = 40ms (25Hz)
// with standby time that should really be 24.16913... Hz // with standby time that should really be 24.16913... Hz
delayTime = 41; delayTime = 41;
*/
/* /*
// gaming // gaming

View file

@ -13,6 +13,7 @@
Written by Limor Fried & Kevin Townsend for Adafruit Industries. Written by Limor Fried & Kevin Townsend for Adafruit Industries.
BSD license, all text above must be included in any redistribution BSD license, all text above must be included in any redistribution
See the LICENSE file for details.
***************************************************************************/ ***************************************************************************/
#include <Wire.h> #include <Wire.h>
@ -35,15 +36,21 @@ unsigned long delayTime;
void setup() { void setup() {
Serial.begin(9600); Serial.begin(9600);
while(!Serial); // time to get serial running
Serial.println(F("BME280 test")); Serial.println(F("BME280 test"));
bool status; unsigned status;
// default settings // default settings
// (you can also pass in a Wire library object like &Wire2) // (you can also pass in a Wire library object like &Wire2)
status = bme.begin(); status = bme.begin();
if (!status) { if (!status) {
Serial.println("Could not find a valid BME280 sensor, check wiring!"); Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!");
Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16);
Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n");
Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n");
Serial.print(" ID of 0x60 represents a BME 280.\n");
Serial.print(" ID of 0x61 represents a BME 680.\n");
while (1); while (1);
} }

View file

@ -1,5 +1,5 @@
name=Adafruit BME280 Library name=Adafruit BME280 Library
version=1.0.7 version=1.0.9
author=Adafruit author=Adafruit
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for BME280 sensors. sentence=Arduino library for BME280 sensors.

View file

@ -20,7 +20,9 @@
#ifndef _ADAFRUIT_SENSOR_H #ifndef _ADAFRUIT_SENSOR_H
#define _ADAFRUIT_SENSOR_H #define _ADAFRUIT_SENSOR_H
#if ARDUINO >= 100 #ifndef ARDUINO
#include <stdint.h>
#elif ARDUINO >= 100
#include "Arduino.h" #include "Arduino.h"
#include "Print.h" #include "Print.h"
#else #else
@ -72,9 +74,9 @@ typedef struct {
}; };
/* Orientation sensors */ /* Orientation sensors */
struct { struct {
float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */ float roll; /**< Rotation around the longitudinal axis (the plane body, 'X axis'). Roll is positive and increasing when moving downward. -90°<=roll<=90° */
float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */ float pitch; /**< Rotation around the lateral axis (the wing span, 'Y axis'). Pitch is positive and increasing when moving upwards. -180°<=pitch<=180°) */
float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */ float heading; /**< Angle between the longitudinal axis (the plane body) and magnetic north, measured clockwise when viewing from the top of the device. 0-359° */
}; };
}; };
int8_t status; int8_t status;
@ -143,7 +145,7 @@ class Adafruit_Sensor {
virtual ~Adafruit_Sensor() {} virtual ~Adafruit_Sensor() {}
// These must be defined by the subclass // These must be defined by the subclass
/// NOT USED virtual void enableAutoRange(bool enabled) {}; virtual void enableAutoRange(bool enabled) { (void)enabled; /* suppress unused warning */ };
virtual bool getEvent(sensors_event_t*) = 0; virtual bool getEvent(sensors_event_t*) = 0;
virtual void getSensor(sensor_t*) = 0; virtual void getSensor(sensor_t*) = 0;

View file

@ -35,7 +35,18 @@ The following drivers are based on the Adafruit Unified Sensor Driver:
- [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library) - [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library)
**Humidity & Temperature** **Humidity & Temperature**
- [Adafruit\_DHT\_Unified](https://github.com/adafruit/Adafruit_DHT_Unified) - [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? ## ## How Does it Work? ##

View file

@ -1,5 +1,5 @@
name=Adafruit Unified Sensor name=Adafruit Unified Sensor
version=1.0.2 version=1.0.3
author=Adafruit <info@adafruit.com> author=Adafruit <info@adafruit.com>
maintainer=Adafruit <info@adafruit.com> maintainer=Adafruit <info@adafruit.com>
sentence=Required for all Adafruit Unified Sensor based libraries. sentence=Required for all Adafruit Unified Sensor based libraries.
@ -7,3 +7,4 @@ paragraph=A unified sensor abstraction layer used by many Adafruit sensor librar
category=Sensors category=Sensors
url=https://github.com/adafruit/Adafruit_Sensor url=https://github.com/adafruit/Adafruit_Sensor
architectures=* architectures=*
includes=Adafruit_Sensor.h

3
firmware/sensors.ino Executable file → Normal file
View file

@ -31,7 +31,7 @@ float fetchLight() {
return lux * LIGHT_FACTOR; return lux * LIGHT_FACTOR;
} }
void _anemometerInterrupt() { ICACHE_RAM_ATTR void _anemometerInterrupt() {
anemometerRotations++; anemometerRotations++;
#ifdef DEBUG #ifdef DEBUG
Serial.print("*"); Serial.print("*");
@ -75,4 +75,3 @@ float isBatCharging() {
} }
#endif #endif