Merge pull request #8432 from device111/development

Support for VEML6075 and initial Support for VEML7700
This commit is contained in:
Theo Arends 2020-05-22 14:38:20 +02:00 committed by GitHub
commit 2b798ff194
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 2336 additions and 4 deletions

View File

@ -69,4 +69,6 @@ Index | Define | Driver | Device | Address(es) | Description
45 | USE_HDC1080 | xsns_65 | HDC1080 | 0x40 | Temperature and Humidity sensor
46 | USE_IAQ | xsns_66 | IAQ | 0x5a | Air quality sensor
47 | USE_DISPLAY_SEVENSEG| xdsp_11 | HT16K33 | 0x70 - 0x77 | Seven segment LED
48 | USE_AS3935 | xsns_67 | AS3935 | 0x03 | Franklin Lightning Sensor
48 | USE_AS3935 | xsns_67 | AS3935 | 0x03 | Franklin Lightning Sensor
49 | USE_VEML6075 | xsns_68 | VEML6075 | 0x10 | UVA/UVB/UVINDEX Sensor
50 | USE_VEML7700 | xsns_69 | VEML7700 | 0x10 | Ambient light intensity sensor

View File

@ -0,0 +1,23 @@
language: c
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
git:
depth: false
quiet: true
env:
global:
- PRETTYNAME="Adafruit BusIO Library"
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
script:
- build_main_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View File

@ -0,0 +1,258 @@
#include <Adafruit_BusIO_Register.h>
/*!
* @brief Create a register we access over an I2C Device (which defines the bus and address)
* @param i2cdevice The I2CDevice to use for underlying I2C access
* @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
* @param width The width of the register data itself, defaults to 1 byte
* @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
* @param address_width The width of the register address itself, defaults to 1 byte
*/
Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
uint8_t width, uint8_t bitorder, uint8_t address_width) {
_i2cdevice = i2cdevice;
_spidevice = NULL;
_addrwidth = address_width;
_address = reg_addr;
_bitorder = bitorder;
_width = width;
}
/*!
* @brief Create a register we access over an SPI Device (which defines the bus and CS pin)
* @param spidevice The SPIDevice to use for underlying I2C access
* @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
* @param type The method we use to read/write data to SPI (which is not as well defined as I2C)
* @param width The width of the register data itself, defaults to 1 byte
* @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
* @param address_width The width of the register address itself, defaults to 1 byte
*/
Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
Adafruit_BusIO_SPIRegType type,
uint8_t width, uint8_t bitorder, uint8_t address_width) {
_spidevice = spidevice;
_spiregtype = type;
_i2cdevice = NULL;
_addrwidth = address_width;
_address = reg_addr;
_bitorder = bitorder;
_width = width;
}
/*!
* @brief Create a register we access over an I2C or SPI Device. This is a handy function because we
* can pass in NULL for the unused interface, allowing libraries to mass-define all the registers
* @param i2cdevice The I2CDevice to use for underlying I2C access, if NULL we use SPI
* @param spidevice The SPIDevice to use for underlying I2C access, if NULL we use I2C
* @param reg_addr The address pointer value for the I2C/SMBus register, can be 8 or 16 bits
* @param type The method we use to read/write data to SPI (which is not as well defined as I2C)
* @param width The width of the register data itself, defaults to 1 byte
* @param bitorder The bit order of the register (used when width is > 1), defaults to LSBFIRST
* @param address_width The width of the register address itself, defaults to 1 byte
*/
Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice,
Adafruit_BusIO_SPIRegType type, uint16_t reg_addr,
uint8_t width, uint8_t bitorder, uint8_t address_width) {
_spidevice = spidevice;
_i2cdevice = i2cdevice;
_spiregtype = type;
_addrwidth = address_width;
_address = reg_addr;
_bitorder = bitorder;
_width = width;
}
/*!
* @brief Write a buffer of data to the register location
* @param buffer Pointer to data to write
* @param len Number of bytes to write
* @return True on successful write (only really useful for I2C as SPI is uncheckable)
*/
bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) {
uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address>>8)};
if (_i2cdevice) {
return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth);
}
if (_spidevice) {
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
addrbuffer[0] &= ~0x80;
}
return _spidevice->write( buffer, len, addrbuffer, _addrwidth);
}
return false;
}
/*!
* @brief Write up to 4 bytes of data to the register location
* @param value Data to write
* @param numbytes How many bytes from 'value' to write
* @return True on successful write (only really useful for I2C as SPI is uncheckable)
*/
bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) {
if (numbytes == 0) {
numbytes = _width;
}
if (numbytes > 4) {
return false;
}
for (int i=0; i<numbytes; i++) {
if (_bitorder == LSBFIRST) {
_buffer[i] = value & 0xFF;
} else {
_buffer[numbytes-i-1] = value & 0xFF;
}
value >>= 8;
}
return write(_buffer, numbytes);
}
/*!
* @brief Read data from the register location. This does not do any error checking!
* @return Returns 0xFFFFFFFF on failure, value otherwise
*/
uint32_t Adafruit_BusIO_Register::read(void) {
if (! read(_buffer, _width)) {
return -1;
}
uint32_t value = 0;
for (int i=0; i < _width; i++) {
value <<= 8;
if (_bitorder == LSBFIRST) {
value |= _buffer[_width-i-1];
} else {
value |= _buffer[i];
}
}
return value;
}
/*!
* @brief Read a buffer of data from the register location
* @param buffer Pointer to data to read into
* @param len Number of bytes to read
* @return True on successful write (only really useful for I2C as SPI is uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) {
uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), (uint8_t)(_address>>8)};
if (_i2cdevice) {
return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
if (_spidevice) {
if (_spiregtype == ADDRBIT8_HIGH_TOREAD) {
addrbuffer[0] |= 0x80;
}
return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len);
}
return false;
}
/*!
* @brief Read 2 bytes of data from the register location
* @param value Pointer to uint16_t variable to read into
* @return True on successful write (only really useful for I2C as SPI is uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint16_t *value) {
if (! read(_buffer, 2)) {
return false;
}
if (_bitorder == LSBFIRST) {
*value = _buffer[1];
*value <<= 8;
*value |= _buffer[0];
} else {
*value = _buffer[0];
*value <<= 8;
*value |= _buffer[1];
}
return true;
}
/*!
* @brief Read 1 byte of data from the register location
* @param value Pointer to uint8_t variable to read into
* @return True on successful write (only really useful for I2C as SPI is uncheckable)
*/
bool Adafruit_BusIO_Register::read(uint8_t *value) {
if (! read(_buffer, 1)) {
return false;
}
*value = _buffer[0];
return true;
}
/*!
* @brief Pretty printer for this register
* @param s The Stream to print to, defaults to &Serial
*/
void Adafruit_BusIO_Register::print(Stream *s) {
uint32_t val = read();
s->print("0x"); s->print(val, HEX);
}
/*!
* @brief Pretty printer for this register
* @param s The Stream to print to, defaults to &Serial
*/
void Adafruit_BusIO_Register::println(Stream *s) {
print(s);
s->println();
}
/*!
* @brief Create a slice of the register that we can address without touching other bits
* @param reg The Adafruit_BusIO_Register which defines the bus/register
* @param bits The number of bits wide we are slicing
* @param shift The number of bits that our bit-slice is shifted from LSB
*/
Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) {
_register = reg;
_bits = bits;
_shift = shift;
}
/*!
* @brief Read 4 bytes of data from the register
* @return data The 4 bytes to read
*/
uint32_t Adafruit_BusIO_RegisterBits::read(void) {
uint32_t val = _register->read();
val >>= _shift;
return val & ((1 << (_bits)) - 1);
}
/*!
* @brief Write 4 bytes of data to the register
* @param data The 4 bytes to write
*/
void Adafruit_BusIO_RegisterBits::write(uint32_t data) {
uint32_t val = _register->read();
// mask off the data before writing
uint32_t mask = (1 << (_bits)) - 1;
data &= mask;
mask <<= _shift;
val &= ~mask; // remove the current data at that spot
val |= data << _shift; // and add in the new data
_register->write(val, _register->width());
}
/*!
* @brief The width of the register data, helpful for doing calculations
* @returns The data width used when initializing the register
*/
uint8_t Adafruit_BusIO_Register::width(void) { return _width; }

View File

@ -0,0 +1,69 @@
#include <Adafruit_I2CDevice.h>
#include <Adafruit_SPIDevice.h>
#include <Arduino.h>
#ifndef Adafruit_BusIO_Register_h
#define Adafruit_BusIO_Register_h
typedef enum _Adafruit_BusIO_SPIRegType {
ADDRBIT8_HIGH_TOREAD = 0,
} Adafruit_BusIO_SPIRegType;
/*!
* @brief The class which defines a device register (a location to read/write data from)
*/
class Adafruit_BusIO_Register {
public:
Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr,
uint8_t width=1, uint8_t bitorder=LSBFIRST,
uint8_t address_width=1);
Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr,
Adafruit_BusIO_SPIRegType type,
uint8_t width=1, uint8_t bitorder=LSBFIRST,
uint8_t address_width=1);
Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice,
Adafruit_SPIDevice *spidevice,
Adafruit_BusIO_SPIRegType type,
uint16_t reg_addr,
uint8_t width=1, uint8_t bitorder=LSBFIRST,
uint8_t address_width=1);
bool read(uint8_t *buffer, uint8_t len);
bool read(uint8_t *value);
bool read(uint16_t *value);
uint32_t read(void);
bool write(uint8_t *buffer, uint8_t len);
bool write(uint32_t value, uint8_t numbytes=0);
uint8_t width(void);
void print(Stream *s=&Serial);
void println(Stream *s=&Serial);
private:
Adafruit_I2CDevice *_i2cdevice;
Adafruit_SPIDevice *_spidevice;
Adafruit_BusIO_SPIRegType _spiregtype;
uint16_t _address;
uint8_t _width, _addrwidth, _bitorder;
uint8_t _buffer[4]; // we wont support anything larger than uint32 for non-buffered read
};
/*!
* @brief The class which defines a slice of bits from within a device register (a location to read/write data from)
*/
class Adafruit_BusIO_RegisterBits {
public:
Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift);
void write(uint32_t value);
uint32_t read(void);
private:
Adafruit_BusIO_Register *_register;
uint8_t _bits, _shift;
};
#endif //BusIO_Register_h

View File

@ -0,0 +1,213 @@
#include <Adafruit_I2CDevice.h>
#include <Arduino.h>
//#define DEBUG_SERIAL Serial
/*!
* @brief Create an I2C device at a given address
* @param addr The 7-bit I2C address for the device
* @param theWire The I2C bus to use, defaults to &Wire
*/
Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) {
_addr = addr;
_wire = theWire;
_begun = false;
#ifdef ARDUINO_ARCH_SAMD
_maxBufferSize = 250; // as defined in Wire.h's RingBuffer
#else
_maxBufferSize = 32;
#endif
}
/*!
* @brief Initializes and does basic address detection
* @param addr_detect Whether we should attempt to detect the I2C address with a scan.
* 99% of sensors/devices don't mind but once in a while, they spaz on a scan!
* @return True if I2C initialized and a device with the addr found
*/
bool Adafruit_I2CDevice::begin(bool addr_detect) {
_wire->begin();
_begun = true;
if (addr_detect) {
return detected();
}
return true;
}
/*!
* @brief Scans I2C for the address - note will give a false-positive
* if there's no pullups on I2C
* @return True if I2C initialized and a device with the addr found
*/
bool Adafruit_I2CDevice::detected(void) {
// Init I2C if not done yet
if (!_begun && !begin()) {
return false;
}
// A basic scanner, see if it ACK's
_wire->beginTransmission(_addr);
if (_wire->endTransmission () == 0) {
return true;
}
return false;
}
/*!
* @brief Write a buffer or two to the I2C device. Cannot be more than maxBufferSize() bytes.
* @param buffer Pointer to buffer of data to write
* @param len Number of bytes from buffer to write
* @param prefix_buffer Pointer to optional array of data to write before buffer.
* Cannot be more than maxBufferSize() bytes.
* @param prefix_len Number of bytes from prefix buffer to write
* @param stop Whether to send an I2C STOP signal on write
* @return True if write was successful, otherwise false.
*/
bool Adafruit_I2CDevice::write(uint8_t *buffer, size_t len, bool stop, uint8_t *prefix_buffer, size_t prefix_len) {
if ((len+prefix_len) > maxBufferSize()) {
// currently not guaranteed to work if more than 32 bytes!
// we will need to find out if some platforms have larger
// I2C buffer sizes :/
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer"));
#endif
return false;
}
_wire->beginTransmission(_addr);
// Write the prefix data (usually an address)
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
if (_wire->write(prefix_buffer, prefix_len) != prefix_len) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
#endif
return false;
}
}
// Write the data itself
if (_wire->write(buffer, len) != len) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("\tI2CDevice failed to write"));
#endif
return false;
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tI2CDevice Wrote: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
for (uint16_t i=0; i<prefix_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
}
}
for (uint16_t i=0; i<len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print("Stop: "); DEBUG_SERIAL.println(stop);
#endif
if (_wire->endTransmission(stop) == 0) {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println("Sent!");
#endif
return true;
} else {
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println("Failed to send!");
#endif
return false;
}
}
/*!
* @brief Read from I2C into a buffer from the I2C device.
* Cannot be more than maxBufferSize() bytes.
* @param buffer Pointer to buffer of data to read into
* @param len Number of bytes from buffer to read.
* @param stop Whether to send an I2C STOP signal on read
* @return True if read was successful, otherwise false.
*/
bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) {
if (len > maxBufferSize()) {
// currently not guaranteed to work if more than 32 bytes!
// we will need to find out if some platforms have larger
// I2C buffer sizes :/
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.println(F("\tI2CDevice could not read such a large buffer"));
#endif
return false;
}
size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop);
if (recv != len) {
// Not enough data available to fulfill our obligation!
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: "));
DEBUG_SERIAL.println(recv);
#endif
return false;
}
for (uint16_t i=0; i<len; i++) {
buffer[i] = _wire->read();
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tI2CDevice Read: "));
for (uint16_t i=0; i<len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
return true;
}
/*!
* @brief Write some data, then read some data from I2C into another buffer.
* Cannot be more than maxBufferSize() bytes. The buffers can point to
* same/overlapping locations.
* @param write_buffer Pointer to buffer of data to write from
* @param write_len Number of bytes from buffer to write.
* @param read_buffer Pointer to buffer of data to read into.
* @param read_len Number of bytes from buffer to read.
* @param stop Whether to send an I2C STOP signal between the write and read
* @return True if write & read was successful, otherwise false.
*/
bool Adafruit_I2CDevice::write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, bool stop) {
if (! write(write_buffer, write_len, stop)) {
return false;
}
return read(read_buffer, read_len);
}
/*!
* @brief Returns the 7-bit address of this device
* @return The 7-bit address of this device
*/
uint8_t Adafruit_I2CDevice::address(void) {
return _addr;
}

View File

@ -0,0 +1,29 @@
#include <Wire.h>
#ifndef Adafruit_I2CDevice_h
#define Adafruit_I2CDevice_h
///< The class which defines how we will talk to this device over I2C
class Adafruit_I2CDevice {
public:
Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire=&Wire);
uint8_t address(void);
bool begin(bool addr_detect=true);
bool detected(void);
bool read(uint8_t *buffer, size_t len, bool stop=true);
bool write(uint8_t *buffer, size_t len, bool stop=true, uint8_t *prefix_buffer=NULL, size_t prefix_len=0);
bool write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, bool stop=false);
/*! @brief How many bytes we can read in a transaction
* @return The size of the Wire receive/transmit buffer */
uint16_t maxBufferSize() { return _maxBufferSize; }
private:
uint8_t _addr;
TwoWire *_wire;
bool _begun;
uint16_t _maxBufferSize;
};
#endif // Adafruit_I2CDevice_h

View File

@ -0,0 +1,8 @@
#include "Adafruit_BusIO_Register.h"
#ifndef _ADAFRUIT_I2C_REGISTER_H_
#define _ADAFRUIT_I2C_REGISTER_H_
typedef Adafruit_BusIO_Register Adafruit_I2CRegister;
typedef Adafruit_BusIO_RegisterBits Adafruit_I2CRegisterBits;
#endif

View File

@ -0,0 +1,301 @@
#include <Adafruit_SPIDevice.h>
#include <Arduino.h>
//#define DEBUG_SERIAL Serial
/*!
* @brief Create an SPI device with the given CS pin and settins
* @param cspin The arduino pin number to use for chip select
* @param freq The SPI clock frequency to use, defaults to 1MHz
* @param dataOrder The SPI data order to use for bits within each byte, defaults to SPI_BITORDER_MSBFIRST
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
* @param theSPI The SPI bus to use, defaults to &theSPI
*/
Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, BitOrder dataOrder, uint8_t dataMode, SPIClass *theSPI) {
_cs = cspin;
_sck = _mosi = _miso = -1;
_spi = theSPI;
_begun = false;
_spiSetting = new SPISettings(freq, dataOrder, dataMode);
_freq = freq;
_dataOrder = dataOrder;
_dataMode = dataMode;
}
/*!
* @brief Create an SPI device with the given CS pin and settins
* @param cspin The arduino pin number to use for chip select
* @param sckpin The arduino pin number to use for SCK
* @param misopin The arduino pin number to use for MISO, set to -1 if not used
* @param mosipin The arduino pin number to use for MOSI, set to -1 if not used
* @param freq The SPI clock frequency to use, defaults to 1MHz
* @param dataOrder The SPI data order to use for bits within each byte, defaults to SPI_BITORDER_MSBFIRST
* @param dataMode The SPI mode to use, defaults to SPI_MODE0
*/
Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, int8_t misopin, int8_t mosipin,
uint32_t freq, BitOrder dataOrder, uint8_t dataMode) {
_cs = cspin;
_sck = sckpin;
_miso = misopin;
_mosi = mosipin;
_freq = freq;
_dataOrder = dataOrder;
_dataMode = dataMode;
_begun = false;
_spiSetting = new SPISettings(freq, dataOrder, dataMode);
_spi = NULL;
}
/*!
* @brief Initializes SPI bus and sets CS pin high
* @return Always returns true because there's no way to test success of SPI init
*/
bool Adafruit_SPIDevice::begin(void) {
pinMode(_cs, OUTPUT);
digitalWrite(_cs, HIGH);
if (_spi) { // hardware SPI
_spi->begin();
} else {
pinMode(_sck, OUTPUT);
if (_dataMode==SPI_MODE0) {
digitalWrite(_sck, HIGH);
} else {
digitalWrite(_sck, LOW);
}
if (_mosi != -1) {
pinMode(_mosi, OUTPUT);
digitalWrite(_mosi, HIGH);
}
if (_miso != -1) {
pinMode(_miso, INPUT);
}
}
_begun = true;
return true;
}
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @param buffer The buffer to send and receive at the same time
* @param len The number of bytes to transfer
*/
void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
if (_spi) {
// hardware SPI is easy
_spi->transfer(buffer, len);
return;
}
// for softSPI we'll do it by hand
for (size_t i=0; i<len; i++) {
// software SPI
uint8_t reply = 0;
uint8_t send = buffer[i];
if (_dataOrder == SPI_BITORDER_LSBFIRST) {
// LSB is rare, if it happens we'll just flip the bits around for them
uint8_t temp = 0;
for (uint8_t b=0; b<8; b++) {
temp |= ((send >> b) & 0x1) << (7-b);
}
send = temp;
}
for (int b=7; b>=0; b--) {
reply <<= 1;
if (_dataMode == SPI_MODE0) {
digitalWrite(_sck, LOW);
digitalWrite(_mosi, send & (1<<b));
digitalWrite(_sck, HIGH);
if ((_miso != -1) && digitalRead(_miso)) {
reply |= 1;
}
}
if (_dataMode == SPI_MODE1) {
digitalWrite(_sck, HIGH);
digitalWrite(_mosi, send & (1<<b));
digitalWrite(_sck, LOW);
if ((_miso != -1) && digitalRead(_miso)) {
reply |= 1;
}
}
}
if (_dataOrder == SPI_BITORDER_LSBFIRST) {
// LSB is rare, if it happens we'll just flip the bits around for them
uint8_t temp = 0;
for (uint8_t b=0; b<8; b++) {
temp |= ((reply >> b) & 0x1) << (7-b);
}
reply = temp;
}
buffer[i] = reply;
}
return;
}
/*!
* @brief Transfer (send/receive) one byte over hard/soft SPI
* @param send The byte to send
* @return The byte received while transmitting
*/
uint8_t Adafruit_SPIDevice::transfer(uint8_t send) {
uint8_t data = send;
transfer(&data, 1);
return data;
}
/*!
* @brief Write a buffer or two to the SPI device.
* @param buffer Pointer to buffer of data to write
* @param len Number of bytes from buffer to write
* @param prefix_buffer Pointer to optional array of data to write before buffer.
* @param prefix_len Number of bytes from prefix buffer to write
* @return Always returns true because there's no way to test success of SPI writes
*/
bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer, size_t prefix_len) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
digitalWrite(_cs, LOW);
// do the writing
for (size_t i=0; i<prefix_len; i++) {
transfer(prefix_buffer[i]);
}
for (size_t i=0; i<len; i++) {
transfer(buffer[i]);
}
digitalWrite(_cs, HIGH);
if (_spi) {
_spi->endTransaction();
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
if ((prefix_len != 0) && (prefix_buffer != NULL)) {
for (uint16_t i=0; i<prefix_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(prefix_buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
}
}
for (uint16_t i=0; i<len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
return true;
}
/*!
* @brief Read from SPI into a buffer from the SPI device.
* @param buffer Pointer to buffer of data to read into
* @param len Number of bytes from buffer to read.
* @param sendvalue The 8-bits of data to write when doing the data read, defaults to 0xFF
* @return Always returns true because there's no way to test success of SPI writes
*/
bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
memset(buffer, sendvalue, len); // clear out existing buffer
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
digitalWrite(_cs, LOW);
transfer(buffer, len);
digitalWrite(_cs, HIGH);
if (_spi) {
_spi->endTransaction();
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
for (uint16_t i=0; i<len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
return true;
}
/*!
* @brief Write some data, then read some data from SPI into another buffer. The buffers can point to same/overlapping locations. This does not transmit-receive at the same time!
* @param write_buffer Pointer to buffer of data to write from
* @param write_len Number of bytes from buffer to write.
* @param read_buffer Pointer to buffer of data to read into.
* @param read_len Number of bytes from buffer to read.
* @param sendvalue The 8-bits of data to write when doing the data read, defaults to 0xFF
* @return Always returns true because there's no way to test success of SPI writes
*/
bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, uint8_t sendvalue) {
if (_spi) {
_spi->beginTransaction(*_spiSetting);
}
digitalWrite(_cs, LOW);
// do the writing
for (size_t i=0; i<write_len; i++) {
transfer(write_buffer[i]);
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
for (uint16_t i=0; i<write_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(write_buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (write_len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
// do the reading
for (size_t i=0; i<read_len; i++) {
read_buffer[i] = transfer(sendvalue);
}
#ifdef DEBUG_SERIAL
DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
for (uint16_t i=0; i<read_len; i++) {
DEBUG_SERIAL.print(F("0x"));
DEBUG_SERIAL.print(read_buffer[i], HEX);
DEBUG_SERIAL.print(F(", "));
if (read_len % 32 == 31) {
DEBUG_SERIAL.println();
}
}
DEBUG_SERIAL.println();
#endif
digitalWrite(_cs, HIGH);
if (_spi) {
_spi->endTransaction();
}
return true;
}

View File

@ -0,0 +1,62 @@
#include <SPI.h>
#ifndef Adafruit_SPIDevice_h
#define Adafruit_SPIDevice_h
// some modern SPI definitions don't have BitOrder enum
#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || defined(ESP8266) || defined(TEENSYDUINO)
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = MSBFIRST,
SPI_BITORDER_LSBFIRST = LSBFIRST,
} BitOrder;
#endif
// some modern SPI definitions don't have BitOrder enum and have different SPI mode defines
#if defined(ESP32)
typedef enum _BitOrder {
SPI_BITORDER_MSBFIRST = SPI_MSBFIRST,
SPI_BITORDER_LSBFIRST = SPI_LSBFIRST,
} BitOrder;
#endif
// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST
#if defined(ARDUINO_ARCH_SAMD) || defined(__SAM3X8E__) || defined(NRF52_SERIES) || defined(ARDUINO_ARCH_ARDUINO_CORE_STM32) || defined(ARDUINO_ARCH_MEGAAVR) || defined(_STM32_DEF_)
#define SPI_BITORDER_MSBFIRST MSBFIRST
#define SPI_BITORDER_LSBFIRST LSBFIRST
#endif
///< The class which defines how we will talk to this device over SPI
class Adafruit_SPIDevice {
public:
Adafruit_SPIDevice(int8_t cspin,
uint32_t freq=1000000,
BitOrder dataOrder=SPI_BITORDER_MSBFIRST,
uint8_t dataMode=SPI_MODE0,
SPIClass *theSPI=&SPI);
Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi,
uint32_t freq=1000000,
BitOrder dataOrder=SPI_BITORDER_MSBFIRST,
uint8_t dataMode=SPI_MODE0);
bool begin(void);
bool read(uint8_t *buffer, size_t len, uint8_t sendvalue=0xFF);
bool write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer=NULL, size_t prefix_len=0);
bool write_then_read(uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, uint8_t sendvalue=0xFF);
uint8_t transfer(uint8_t send);
void transfer(uint8_t *buffer, size_t len);
private:
SPIClass *_spi;
SPISettings *_spiSetting;
uint32_t _freq;
BitOrder _dataOrder;
uint8_t _dataMode;
int8_t _cs, _sck, _mosi, _miso;
bool _begun;
};
#endif // Adafruit_SPIDevice_h

View File

@ -0,0 +1,21 @@
The MIT License (MIT)
Copyright (c) 2017 Adafruit Industries
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,7 @@
# Adafruit Bus IO Library [![Build Status](https://travis-ci.com/adafruit/Adafruit_BusIO.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_BusIO)
This is a helper libary to abstract away I2C & SPI transactions and registers
Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit!
MIT license, all text above must be included in any redistribution

View File

@ -0,0 +1,21 @@
#include <Adafruit_I2CDevice.h>
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(0x10);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("I2C address detection test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
}
void loop() {
}

View File

@ -0,0 +1,41 @@
#include <Adafruit_I2CDevice.h>
#define I2C_ADDRESS 0x60
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("I2C device read and write test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
uint8_t buffer[32];
// Try to read 32 bytes
i2c_dev.read(buffer, 32);
Serial.print("Read: ");
for (uint8_t i=0; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
// read a register by writing first, then reading
buffer[0] = 0x0C; // we'll reuse the same buffer
i2c_dev.write_then_read(buffer, 1, buffer, 2, false);
Serial.print("Write then Read: ");
for (uint8_t i=0; i<2; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
}
void loop() {
}

View File

@ -0,0 +1,38 @@
#include <Adafruit_I2CDevice.h>
#include <Adafruit_BusIO_Register.h>
#define I2C_ADDRESS 0x60
Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("I2C device register test");
if (!i2c_dev.begin()) {
Serial.print("Did not find device at 0x");
Serial.println(i2c_dev.address(), HEX);
while (1);
}
Serial.print("Device found on address 0x");
Serial.println(i2c_dev.address(), HEX);
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST);
uint16_t id;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST);
uint16_t thresh;
thresh_reg.read(&thresh);
Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX);
thresh_reg.write(~thresh);
Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX);
}
void loop() {
}

View File

@ -0,0 +1,38 @@
#include <Adafruit_BusIO_Register.h>
// Define which interface to use by setting the unused interface to NULL!
#define SPIDEVICE_CS 10
Adafruit_SPIDevice *spi_dev = NULL; // new Adafruit_SPIDevice(SPIDEVICE_CS);
#define I2C_ADDRESS 0x5D
Adafruit_I2CDevice *i2c_dev = new Adafruit_I2CDevice(I2C_ADDRESS);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("I2C or SPI device register test");
if (spi_dev && !spi_dev->begin()) {
Serial.println("Could not initialize SPI device");
}
if (i2c_dev) {
if (i2c_dev->begin()) {
Serial.print("Device found on I2C address 0x");
Serial.println(i2c_dev->address(), HEX);
} else {
Serial.print("Did not find I2C device at 0x");
Serial.println(i2c_dev->address(), HEX);
}
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F);
uint8_t id;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
}
void loop() {
}

View File

@ -0,0 +1,29 @@
#include <Adafruit_SPIDevice.h>
#define SPIDEVICE_CS 10
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
//Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("SPI device mode test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
}
}
void loop() {
Serial.println("\n\nTransfer test");
for (uint16_t x=0; x<=0xFF; x++) {
uint8_t i = x;
Serial.print("0x"); Serial.print(i, HEX);
spi_dev.read(&i, 1, i);
Serial.print("/"); Serial.print(i, HEX);
Serial.print(", ");
delay(25);
}
}

View File

@ -0,0 +1,39 @@
#include <Adafruit_SPIDevice.h>
#define SPIDEVICE_CS 10
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("SPI device read and write test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
}
uint8_t buffer[32];
// Try to read 32 bytes
spi_dev.read(buffer, 32);
Serial.print("Read: ");
for (uint8_t i=0; i<32; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
// read a register by writing first, then reading
buffer[0] = 0x8F; // we'll reuse the same buffer
spi_dev.write_then_read(buffer, 1, buffer, 2, false);
Serial.print("Write then Read: ");
for (uint8_t i=0; i<2; i++) {
Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", ");
}
Serial.println();
}
void loop() {
}

View File

@ -0,0 +1,34 @@
#include <Adafruit_BusIO_Register.h>
#include <Adafruit_SPIDevice.h>
#define SPIDEVICE_CS 10
Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS);
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("SPI device register test");
if (!spi_dev.begin()) {
Serial.println("Could not initialize SPI device");
while (1);
}
Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD);
uint8_t id;
id_reg.read(&id);
Serial.print("ID register = 0x"); Serial.println(id, HEX);
Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST);
uint16_t thresh;
thresh_reg.read(&thresh);
Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX);
thresh_reg.write(~thresh);
Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX);
}
void loop() {
}

View File

@ -0,0 +1,9 @@
name=Adafruit BusIO
version=1.0.10
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=This is a library for abstracting away UART, I2C and SPI interfacing
paragraph=This is a library for abstracting away UART, I2C and SPI interfacing
category=Signal Input/Output
url=https://github.com/adafruit/Adafruit_BusIO
architectures=*

View File

@ -0,0 +1,46 @@
Thank you for opening an issue on an Adafruit Arduino library repository. To
improve the speed of resolution please review the following guidelines and
common troubleshooting steps below before creating the issue:
- **Do not use GitHub issues for troubleshooting projects and issues.** Instead use
the forums at http://forums.adafruit.com to ask questions and troubleshoot why
something isn't working as expected. In many cases the problem is a common issue
that you will more quickly receive help from the forum community. GitHub issues
are meant for known defects in the code. If you don't know if there is a defect
in the code then start with troubleshooting on the forum first.
- **If following a tutorial or guide be sure you didn't miss a step.** Carefully
check all of the steps and commands to run have been followed. Consult the
forum if you're unsure or have questions about steps in a guide/tutorial.
- **For Arduino projects check these very common issues to ensure they don't apply**:
- For uploading sketches or communicating with the board make sure you're using
a **USB data cable** and **not** a **USB charge-only cable**. It is sometimes
very hard to tell the difference between a data and charge cable! Try using the
cable with other devices or swapping to another cable to confirm it is not
the problem.
- **Be sure you are supplying adequate power to the board.** Check the specs of
your board and plug in an external power supply. In many cases just
plugging a board into your computer is not enough to power it and other
peripherals.
- **Double check all soldering joints and connections.** Flakey connections
cause many mysterious problems. See the [guide to excellent soldering](https://learn.adafruit.com/adafruit-guide-excellent-soldering/tools) for examples of good solder joints.
- **Ensure you are using an official Arduino or Adafruit board.** We can't
guarantee a clone board will have the same functionality and work as expected
with this code and don't support them.
If you're sure this issue is a defect in the code and checked the steps above
please fill in the following fields to provide enough troubleshooting information.
You may delete the guideline and text above to just leave the following details:
- Arduino board: **INSERT ARDUINO BOARD NAME/TYPE HERE**
- Arduino IDE version (found in Arduino -> About Arduino menu): **INSERT ARDUINO
VERSION HERE**
- List the steps to reproduce the problem below (if possible attach a sketch or
copy the sketch code in too): **LIST REPRO STEPS BELOW**

View File

@ -0,0 +1,26 @@
Thank you for creating a pull request to contribute to Adafruit's GitHub code!
Before you open the request please review the following guidelines and tips to
help it be more easily integrated:
- **Describe the scope of your change--i.e. what the change does and what parts
of the code were modified.** This will help us understand any risks of integrating
the code.
- **Describe any known limitations with your change.** For example if the change
doesn't apply to a supported platform of the library please mention it.
- **Please run any tests or examples that can exercise your modified code.** We
strive to not break users of the code and running tests/examples helps with this
process.
Thank you again for contributing! We will try to test and integrate the change
as soon as we can, but be aware we have many GitHub repositories to manage and
can't immediately respond to every request. There is no need to bump or check in
on a pull request (it will clutter the discussion of the request).
Also don't be worried if the request is closed or not integrated--sometimes the
priorities of Adafruit's GitHub code (education, ease of use) might not match the
priorities of the pull request. Don't fret, the open source community thrives on
forks and GitHub makes it easy to keep your changes in a forked repo.
After reviewing the guidelines above you can delete this text from the pull request.

8
lib/Adafruit_VEML7700/.gitignore vendored Normal file
View File

@ -0,0 +1,8 @@
# osx
.DS_Store
# doxygen
Doxyfile*
doxygen_sqlite3.db
html
*.tmp

View File

@ -0,0 +1,26 @@
language: c
sudo: false
cache:
directories:
- ~/arduino_ide
- ~/.arduino15/packages/
git:
depth: false
quiet: true
env:
global:
- PRETTYNAME="Adafruit VEML7700 Arduino Library"
before_install:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh)
install:
- arduino --install-library "Adafruit BusIO"
script:
- build_main_platforms
# Generate and deploy documentation
after_success:
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/library_check.sh)
- source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/doxy_gen_and_deploy.sh)

View File

@ -0,0 +1,322 @@
/*!
* @file Adafruit_VEML7700.cpp
*
* @mainpage Adafruit VEML7700 I2C Lux Sensor
*
* @section intro_sec Introduction
*
* I2C Driver for the VEML7700 I2C Lux sensor
*
* This is a library for the Adafruit VEML7700 breakout:
* http://www.adafruit.com/
*
* 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
*
* Limor Fried (Adafruit Industries)
*
* @section license License
*
* BSD (see license.txt)
*
* @section HISTORY
*
* v1.0 - First release
*/
#include "Arduino.h"
#include <Wire.h>
#include "Adafruit_VEML7700.h"
/*!
* @brief Instantiates a new VEML7700 class
*/
Adafruit_VEML7700::Adafruit_VEML7700(void) {}
/*!
* @brief Setups the hardware for talking to the VEML7700
* @param theWire An optional pointer to an I2C interface
* @return True if initialization was successful, otherwise false.
*/
boolean Adafruit_VEML7700::begin(TwoWire *theWire) {
i2c_dev = new Adafruit_I2CDevice(VEML7700_I2CADDR_DEFAULT, theWire);
if (!i2c_dev->begin()) {
return false;
}
ALS_Config = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_CONFIG, 2, LSBFIRST);
ALS_HighThreshold = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_THREHOLD_HIGH, 2, LSBFIRST);
ALS_LowThreshold = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_THREHOLD_LOW, 2, LSBFIRST);
Power_Saving = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_POWER_SAVE, 2, LSBFIRST);
ALS_Data = new Adafruit_I2CRegister(i2c_dev, VEML7700_ALS_DATA, 2, LSBFIRST);
White_Data = new Adafruit_I2CRegister(i2c_dev, VEML7700_WHITE_DATA, 2, LSBFIRST);
Interrupt_Status = new Adafruit_I2CRegister(i2c_dev, VEML7700_INTERRUPTSTATUS, 2, LSBFIRST);
ALS_Shutdown = new Adafruit_I2CRegisterBits(ALS_Config, 1, 0); // # bits, bit_shift
ALS_Interrupt_Enable = new Adafruit_I2CRegisterBits(ALS_Config, 1, 1);
ALS_Persistence = new Adafruit_I2CRegisterBits(ALS_Config, 2, 4);
ALS_Integration_Time = new Adafruit_I2CRegisterBits(ALS_Config, 4, 6);
ALS_Gain = new Adafruit_I2CRegisterBits(ALS_Config, 2, 11);
PowerSave_Enable = new Adafruit_I2CRegisterBits(Power_Saving, 1, 0);
PowerSave_Mode = new Adafruit_I2CRegisterBits(Power_Saving, 2, 1);
enable(false);
interruptEnable(false);
setPersistence(VEML7700_PERS_1);
setGain(VEML7700_GAIN_1);
setIntegrationTime(VEML7700_IT_100MS);
powerSaveEnable(false);
enable(true);
return true;
}
float Adafruit_VEML7700::normalize_resolution(float value) {
// adjust for gain (1x is normalized)
switch (getGain()) {
case VEML7700_GAIN_2:
value /= 2.0; break;
case VEML7700_GAIN_1_4:
value *= 4; break;
case VEML7700_GAIN_1_8:
value *= 8; break;
}
// adjust for integrationtime (100ms is normalized)
switch (getIntegrationTime()) {
case VEML7700_IT_25MS:
value *= 4; break;
case VEML7700_IT_50MS:
value *= 2; break;
case VEML7700_IT_200MS:
value /= 2.0; break;
case VEML7700_IT_400MS:
value /= 4.0; break;
case VEML7700_IT_800MS:
value /= 8.0; break;
}
return value;
}
/*!
* @brief Read the calibrated lux value. See app note lux table on page 5
* @returns Floating point Lux data (ALS multiplied by 0.0576)
*/
float Adafruit_VEML7700::readLux() {
return ( normalize_resolution(ALS_Data->read()) * 0.0576); // see app note lux table on page 5
}
/*!
* @brief Read the lux value with correction for non-linearity at high-lux settings
* @returns Floating point Lux data (ALS multiplied by 0.0576 and corrected for high-lux settings)
*/
float Adafruit_VEML7700::readLuxNormalized() {
float lux = readLux();
// user-provided correction for non-linearities at high lux/white values:
// https://forums.adafruit.com/viewtopic.php?f=19&t=152997&p=758582#p759346
if ((getGain() == VEML7700_GAIN_1_8) && (getIntegrationTime() == VEML7700_IT_25MS)){
lux = 6.0135e-13*pow(lux,4) - 9.3924e-9*pow(lux,3) + 8.1488e-5*pow(lux,2) + 1.0023*lux;
}
return lux;
}
/*!
* @brief Read the raw ALS data
* @returns 16-bit data value from the ALS register
*/
uint16_t Adafruit_VEML7700::readALS() {
return ALS_Data->read();
}
/*!
* @brief Read the white light data
* @returns Floating point 'white light' data multiplied by 0.0576
*/
float Adafruit_VEML7700::readWhite() {
// white_corrected= 2E-15*pow(VEML_white,4) + 4E-12*pow(VEML_white,3) + 9E-06*pow(VEML_white,)2 + 1.0179*VEML_white - 11.052;
return normalize_resolution(White_Data->read()) * 0.0576; // Unclear if this is the right multiplier
}
/*!
* @brief Read the 'white light' value with correction for non-linearity at high-lux settings
* @returns Floating point 'white light' data multiplied by 0.0576 and corrected for high-lux settings
*/
float Adafruit_VEML7700::readWhiteNormalized() {
float white = readWhite();
// user-provided correction for non-linearities at high lux values:
// https://forums.adafruit.com/viewtopic.php?f=19&t=152997&p=758582#p759346
if ((getGain() == VEML7700_GAIN_1_8) && (getIntegrationTime() == VEML7700_IT_25MS)){
white = 2E-15*pow(white,4) + 4E-12*pow(white,3) + 9E-06*pow(white,2) + 1.0179*white - 11.052;
}
return white;
}
/*!
* @brief Enable or disable the sensor
* @param enable The flag to enable/disable
*/
void Adafruit_VEML7700::enable(bool enable) {
ALS_Shutdown->write(!enable);
}
/*!
* @brief Ask if the interrupt is enabled
* @returns True if enabled, false otherwise
*/
bool Adafruit_VEML7700::enabled(void) {
return !ALS_Shutdown->read();
}
/*!
* @brief Enable or disable the interrupt
* @param enable The flag to enable/disable
*/
void Adafruit_VEML7700::interruptEnable(bool enable) {
ALS_Interrupt_Enable->write(enable);
}
/*!
* @brief Ask if the interrupt is enabled
* @returns True if enabled, false otherwise
*/
bool Adafruit_VEML7700::interruptEnabled(void) {
return ALS_Interrupt_Enable->read();
}
/*!
* @brief Set the ALS IRQ persistance setting
* @param pers Persistance constant, can be VEML7700_PERS_1, VEML7700_PERS_2,
* VEML7700_PERS_4 or VEML7700_PERS_8
*/
void Adafruit_VEML7700::setPersistence(uint8_t pers) {
ALS_Persistence->write(pers);
}
/*!
* @brief Get the ALS IRQ persistance setting
* @returns Persistance constant, can be VEML7700_PERS_1, VEML7700_PERS_2,
* VEML7700_PERS_4 or VEML7700_PERS_8
*/
uint8_t Adafruit_VEML7700::getPersistence(void) {
return ALS_Persistence->read();
}
/*!
* @brief Set ALS integration time
* @param it Can be VEML7700_IT_100MS, VEML7700_IT_200MS, VEML7700_IT_400MS,
* VEML7700_IT_800MS, VEML7700_IT_50MS or VEML7700_IT_25MS
*/
void Adafruit_VEML7700::setIntegrationTime(uint8_t it) {
ALS_Integration_Time->write(it);
}
/*!
* @brief Get ALS integration time
* @returns IT index, can be VEML7700_IT_100MS, VEML7700_IT_200MS, VEML7700_IT_400MS,
* VEML7700_IT_800MS, VEML7700_IT_50MS or VEML7700_IT_25MS
*/
uint8_t Adafruit_VEML7700::getIntegrationTime(void) {
return ALS_Integration_Time->read();
}
/*!
* @brief Set ALS gain
* @param gain Can be VEML7700_GAIN_1, VEML7700_GAIN_2, VEML7700_GAIN_1_8 or VEML7700_GAIN_1_4
*/
void Adafruit_VEML7700::setGain(uint8_t gain) {
ALS_Gain->write(gain);
}
/*!
* @brief Get ALS gain
* @returns Gain index, can be VEML7700_GAIN_1, VEML7700_GAIN_2, VEML7700_GAIN_1_8 or VEML7700_GAIN_1_4
*/
uint8_t Adafruit_VEML7700::getGain(void) {
return ALS_Gain->read();
}
/*!
* @brief Enable power save mode
* @param enable True if power save should be enabled
*/
void Adafruit_VEML7700::powerSaveEnable(bool enable) {
PowerSave_Enable->write(enable);
}
/*!
* @brief Check if power save mode is enabled
* @returns True if power save is enabled
*/
bool Adafruit_VEML7700::powerSaveEnabled(void) {
return PowerSave_Enable->read();
}
/*!
* @brief Assign the power save register data
* @param mode The 16-bit data to write to VEML7700_ALS_POWER_SAVE
*/
void Adafruit_VEML7700::setPowerSaveMode(uint8_t mode) {
PowerSave_Mode->write(mode);
}
/*!
* @brief Retrieve the power save register data
* @return 16-bit data from VEML7700_ALS_POWER_SAVE
*/
uint8_t Adafruit_VEML7700::getPowerSaveMode(void) {
return PowerSave_Mode->read();
}
/*!
* @brief Assign the low threshold register data
* @param value The 16-bit data to write to VEML7700_ALS_THREHOLD_LOW
*/
void Adafruit_VEML7700::setLowThreshold(uint16_t value) {
ALS_LowThreshold->write(value);
}
/*!
* @brief Retrieve the low threshold register data
* @return 16-bit data from VEML7700_ALS_THREHOLD_LOW
*/
uint16_t Adafruit_VEML7700::getLowThreshold(void) {
return ALS_LowThreshold->read();
}
/*!
* @brief Assign the high threshold register data
* @param value The 16-bit data to write to VEML7700_ALS_THREHOLD_HIGH
*/
void Adafruit_VEML7700::setHighThreshold(uint16_t value) {
ALS_HighThreshold->write(value);
}
/*!
* @brief Retrieve the high threshold register data
* @return 16-bit data from VEML7700_ALS_THREHOLD_HIGH
*/
uint16_t Adafruit_VEML7700::getHighThreshold(void) {
return ALS_HighThreshold->read();
}
/*!
* @brief Retrieve the interrupt status register data
* @return 16-bit data from VEML7700_INTERRUPTSTATUS
*/
uint16_t Adafruit_VEML7700::interruptStatus(void) {
return Interrupt_Status->read();
}

View File

@ -0,0 +1,113 @@
/*!
* @file Adafruit_VEML7700.h
*
* I2C Driver for VEML7700 Lux sensor
*
* This is a library for the Adafruit VEML7700 breakout:
* http://www.adafruit.com/
*
* Adafruit invests time and resources providing this open source code,
*please support Adafruit and open-source hardware by purchasing products from
* Adafruit!
*
*
* BSD license (see license.txt)
*/
#ifndef _ADAFRUIT_VEML7700_H
#define _ADAFRUIT_VEML7700_H
#include "Arduino.h"
#include <Wire.h>
#include <Adafruit_I2CDevice.h>
#include <Adafruit_I2CRegister.h>
#define VEML7700_I2CADDR_DEFAULT 0x10 ///< I2C address
#define VEML7700_ALS_CONFIG 0x00 ///< Light configuration register
#define VEML7700_ALS_THREHOLD_HIGH 0x01 ///< Light high threshold for irq
#define VEML7700_ALS_THREHOLD_LOW 0x02 ///< Light low threshold for irq
#define VEML7700_ALS_POWER_SAVE 0x03 ///< Power save regiester
#define VEML7700_ALS_DATA 0x04 ///< The light data output
#define VEML7700_WHITE_DATA 0x05 ///< The white light data output
#define VEML7700_INTERRUPTSTATUS 0x06 ///< What IRQ (if any)
#define VEML7700_INTERRUPT_HIGH 0x4000 ///< Interrupt status for high threshold
#define VEML7700_INTERRUPT_LOW 0x8000 ///< Interrupt status for low threshold
#define VEML7700_GAIN_1 0x00 ///< ALS gain 1x
#define VEML7700_GAIN_2 0x01 ///< ALS gain 2x
#define VEML7700_GAIN_1_8 0x02 ///< ALS gain 1/8x
#define VEML7700_GAIN_1_4 0x03 ///< ALS gain 1/4x
#define VEML7700_IT_100MS 0x00 ///< ALS intetgration time 100ms
#define VEML7700_IT_200MS 0x01 ///< ALS intetgration time 200ms
#define VEML7700_IT_400MS 0x02 ///< ALS intetgration time 400ms
#define VEML7700_IT_800MS 0x03 ///< ALS intetgration time 800ms
#define VEML7700_IT_50MS 0x08 ///< ALS intetgration time 50ms
#define VEML7700_IT_25MS 0x0C ///< ALS intetgration time 25ms
#define VEML7700_PERS_1 0x00 ///< ALS irq persisance 1 sample
#define VEML7700_PERS_2 0x01 ///< ALS irq persisance 2 samples
#define VEML7700_PERS_4 0x02 ///< ALS irq persisance 4 samples
#define VEML7700_PERS_8 0x03 ///< ALS irq persisance 8 samples
#define VEML7700_POWERSAVE_MODE1 0x00 ///< Power saving mode 1
#define VEML7700_POWERSAVE_MODE2 0x01 ///< Power saving mode 2
#define VEML7700_POWERSAVE_MODE3 0x02 ///< Power saving mode 3
#define VEML7700_POWERSAVE_MODE4 0x03 ///< Power saving mode 4
/*!
* @brief Class that stores state and functions for interacting with
* VEML7700 Temp Sensor
*/
class Adafruit_VEML7700 {
public:
Adafruit_VEML7700();
boolean begin(TwoWire *theWire = &Wire);
void enable(bool enable);
bool enabled(void);
void interruptEnable(bool enable);
bool interruptEnabled(void);
void setPersistence(uint8_t pers);
uint8_t getPersistence(void);
void setIntegrationTime(uint8_t it);
uint8_t getIntegrationTime(void);
void setGain(uint8_t gain);
uint8_t getGain(void);
void powerSaveEnable(bool enable);
bool powerSaveEnabled(void);
void setPowerSaveMode(uint8_t mode);
uint8_t getPowerSaveMode(void);
void setLowThreshold(uint16_t value);
uint16_t getLowThreshold(void);
void setHighThreshold(uint16_t value);
uint16_t getHighThreshold(void);
uint16_t interruptStatus(void);
float readLux();
float readLuxNormalized();
uint16_t readALS();
float readWhite();
float readWhiteNormalized();
private:
Adafruit_I2CRegister *ALS_Config, *ALS_Data, *White_Data,
*ALS_HighThreshold, *ALS_LowThreshold, *Power_Saving, *Interrupt_Status;
Adafruit_I2CRegisterBits *ALS_Shutdown, *ALS_Interrupt_Enable,
*ALS_Persistence, *ALS_Integration_Time, *ALS_Gain,
*PowerSave_Enable, *PowerSave_Mode;
float normalize_resolution(float value);
Adafruit_I2CDevice *i2c_dev;
};
#endif

View File

@ -0,0 +1,16 @@
Adafruit_VEML7700 [![Build Status](https://travis-ci.com/adafruit/Adafruit_VEML7700.svg?branch=master)](https://travis-ci.com/adafruit/Adafruit_VEML7700)
================
This is the Adafruit VEML7700 Lux sensor library
Tested and works great with the [Adafruit VEML7700 Breakout Board](http://www.adafruit.com/)
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 Kevin Townsend/Limor Fried for Adafruit Industries.
BSD license, check license.txt for more information
All text above must be included in any redistribution

View File

@ -0,0 +1,58 @@
#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml = Adafruit_VEML7700();
void setup() {
while (!Serial) { delay(10); }
Serial.begin(115200);
Serial.println("Adafruit VEML7700 Test");
if (!veml.begin()) {
Serial.println("Sensor not found");
while (1);
}
Serial.println("Sensor found");
veml.setGain(VEML7700_GAIN_1);
veml.setIntegrationTime(VEML7700_IT_800MS);
Serial.print(F("Gain: "));
switch (veml.getGain()) {
case VEML7700_GAIN_1: Serial.println("1"); break;
case VEML7700_GAIN_2: Serial.println("2"); break;
case VEML7700_GAIN_1_4: Serial.println("1/4"); break;
case VEML7700_GAIN_1_8: Serial.println("1/8"); break;
}
Serial.print(F("Integration Time (ms): "));
switch (veml.getIntegrationTime()) {
case VEML7700_IT_25MS: Serial.println("25"); break;
case VEML7700_IT_50MS: Serial.println("50"); break;
case VEML7700_IT_100MS: Serial.println("100"); break;
case VEML7700_IT_200MS: Serial.println("200"); break;
case VEML7700_IT_400MS: Serial.println("400"); break;
case VEML7700_IT_800MS: Serial.println("800"); break;
}
//veml.powerSaveEnable(true);
//veml.setPowerSaveMode(VEML7700_POWERSAVE_MODE4);
veml.setLowThreshold(10000);
veml.setHighThreshold(20000);
veml.interruptEnable(true);
}
void loop() {
Serial.print("Lux: "); Serial.println(veml.readLux());
Serial.print("White: "); Serial.println(veml.readWhite());
Serial.print("Raw ALS: "); Serial.println(veml.readALS());
uint16_t irq = veml.interruptStatus();
if (irq & VEML7700_INTERRUPT_LOW) {
Serial.println("** Low threshold");
}
if (irq & VEML7700_INTERRUPT_HIGH) {
Serial.println("** High threshold");
}
delay(500);
}

View File

@ -0,0 +1,9 @@
name=Adafruit VEML7700 Library
version=1.0.0
author=Adafruit
maintainer=Adafruit <info@adafruit.com>
sentence=Arduino library for the VEML7700 sensors in the Adafruit shop
paragraph=Arduino library for the VEML7700 sensors in the Adafruit shop
category=Sensors
url=https://github.com/adafruit/Adafruit_VEML7700
architectures=*

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

@ -586,6 +586,16 @@
// Commands xsns_02_analog.ino
#define D_CMND_ADCPARAM "AdcParam"
// xsns_70_veml6075.ino
#define D_JSON_UVA_INTENSITY "UvaIntensity"
#define D_JSON_UVB_INTENSITY "UvbItensity"
#define D_CMND_VEML6075_POWER "power"
#define D_CMND_VEML6075_DYNAMIC "dynamic"
#define D_CMND_VEML6075_INTTIME "inttime"
// xsns_71_veml7700.ino
#define D_JSON_WHITE_CONTENT "WhiteContent"
/********************************************************************************************/
// Log message prefix

View File

@ -516,6 +516,8 @@
// #define USE_HDC1080 // [I2cDriver45] Enable HDC1080 temperature/humidity sensor (I2C address 0x40) (+1k5 code)
// #define USE_IAQ // [I2cDriver46] Enable iAQ-core air quality sensor (I2C address 0x5a) (+0k6 code)
// #define USE_AS3935 // [I2cDriver48] Enable AS3935 Franklin Lightning Sensor (I2C address 0x03) (+5k4 code)
// #define USE_VEML6075 // [I2cDriver49] Enable VEML6075 UVA/UVB/UVINDEX Sensor (I2C address 0x10) (+2k1 code)
// #define USE_VEML7700 // [I2cDriver50] Enable VEML7700 Ambient Light sensor (I2C addresses 0x10) (+4k5 code)
// #define USE_DISPLAY // Add I2C Display Support (+2k code)
#define USE_DISPLAY_MODES1TO5 // Enable display mode 1 to 5 in addition to mode 0

View File

@ -563,10 +563,13 @@ void GetFeatures(void)
#ifdef USE_THERMOSTAT
feature6 |= 0x00000400; // xdrv_39_heating.ino
#endif
#ifdef USE_VEML6075
feature6 |= 0x00000800; // xsns_70_veml6075.ino
#endif
#ifdef USE_VEML7700
feature6 |= 0x00001000; // xsns_71_veml7700.ino
#endif
// feature6 |= 0x00000800;
// feature6 |= 0x00001000;
// feature6 |= 0x00002000;
// feature6 |= 0x00004000;
// feature6 |= 0x00008000;

View File

@ -83,6 +83,8 @@
#define USE_BME680 // Add additional support for BME680 sensor using Bosch BME680 library (+4k code)
#define USE_BH1750 // Add I2C code for BH1750 sensor (+0k5 code)
#define USE_VEML6070 // Add I2C code for VEML6070 sensor (+0k5 code)
// #define USE_VEML6075 // Add I2C code for VEML6075 UVA/UVB/UVINDEX Sensor (+2k1 code)
// #define USE_VEML7700 // Add I2C code for VEML7700 Ambient Light sensor (+4k5 code)
#define USE_ADS1115 // Add I2C code for ADS1115 16 bit A/D converter based on Adafruit ADS1x15 library (no library needed) (+0k7 code)
#define USE_INA219 // Add I2C code for INA219 Low voltage and current sensor (+1k code)
//#define USE_INA226 // Enable INA226 (I2C address 0x40, 0x41 0x44 or 0x45) Low voltage and current sensor (+2k3 code)

View File

@ -0,0 +1,306 @@
/*
xsns_70_veml6075.ino - VEML6075 Franklin Lightning Sensor support for Tasmota
Copyright (C) 2020 Martin Wagner
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_VEML6075
/*********************************************************************************************\
* VEML6075 UVA/UVB/UVINDEX Sensor
*
* I2C Address: 0x10
\*********************************************************************************************/
#define XSNS_70 70
#define XI2C_49 49 // See I2CDEVICES.md
#define VEML6075_ADDR 0x10 // I2C address
#define VEML6075_CHIP_ID 0x26 // Manufacture ID
// I2C register
#define VEML6075_REG_CONF 0x00 // Configuration register
#define VEML6075_REG_UVA 0x07 // UVA band raw measurement
#define VEML6075_REG_DARK 0x08 // Dark current (?) measurement
#define VEML6075_REG_UVB 0x09 // UVB band raw measurement
#define VEML6075_REG_UVCOMP1 0x0A // UV1 compensation value
#define VEML6075_REG_UVCOMP2 0x0B // UV2 compensation value
#define VEML6075_REG_ID 0x0C // ID Register
// global constants for Calc
#define VEML6075_DEFAULT_UVA_A_COEFF 2.22 // Default for no coverglass
#define VEML6075_DEFAULT_UVA_B_COEFF 1.33 // Default for no coverglass
#define VEML6075_DEFAULT_UVB_C_COEFF 2.95 // Default for no coverglass
#define VEML6075_DEFAULT_UVB_D_COEFF 1.74 // Default for no coverglass
#define UVA_RESPONSIVITY_100MS_UNCOVERED 0.001461 // Default for no coverglass
#define UVB_RESPONSIVITY_100MS_UNCOVERED 0.002591 // Default for no coverglass
const float UVA_RESPONSIVITY[] PROGMEM =
{
UVA_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, // 50ms
UVA_RESPONSIVITY_100MS_UNCOVERED, // 100ms
UVA_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, // 200ms
UVA_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, // 400ms
UVA_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 // 800ms
};
const float UVB_RESPONSIVITY[] PROGMEM =
{
UVB_RESPONSIVITY_100MS_UNCOVERED / 0.5016286645, // 50ms
UVB_RESPONSIVITY_100MS_UNCOVERED, // 100ms
UVB_RESPONSIVITY_100MS_UNCOVERED / 2.039087948, // 200ms
UVB_RESPONSIVITY_100MS_UNCOVERED / 3.781758958, // 400ms
UVB_RESPONSIVITY_100MS_UNCOVERED / 7.371335505 // 800ms
};
// http and json defines
#define D_NAME_VEML6075 "VEML6075"
#define D_UVA_INTENSITY "UVA intensity"
#define D_UVB_INTENSITY "UVB intensity"
const char HTTP_SNS_UVA[] PROGMEM = "{s}%s " D_UVA_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}";
const char HTTP_SNS_UVB[] PROGMEM = "{s}%s " D_UVB_INTENSITY "{m}%d " D_UNIT_WATT_METER_QUADRAT "{e}";
const char HTTP_SNS_UVINDEX[] PROGMEM = "{s}%s " D_UV_INDEX "{m}%s {e}";
const char JSON_SNS_VEML6075[] PROGMEM = ",\"%s\":{\"" D_JSON_UVA_INTENSITY "\":%d,\"" D_JSON_UVB_INTENSITY "\":%d,\"" D_JSON_UV_INDEX "\":%s}";
const char S_JSON_VEML6075_COMMAND_NVALUE[] PROGMEM = "{\"" D_NAME_VEML6075 "\":{\"%s\":%d}}";
const char kVEML6075_Commands[] PROGMEM = D_CMND_VEML6075_POWER "|" D_CMND_VEML6075_DYNAMIC "|" D_CMND_VEML6075_INTTIME;
enum VEML6075_Commands { // commands for Console
CMND_VEML6075_PWR,
CMND_VEML6075_SET_HD,
CMND_VEML6075_SET_UVIT,
};
// global variables
struct VEML6075STRUCT
{
char types[9] = D_NAME_VEML6075;
uint8_t address = VEML6075_ADDR;
uint8_t inttime = 0;
uint16_t uva = 0;
uint16_t uvb = 0;
uint16_t uva_raw = 0;
uint16_t uvb_raw = 0;
uint16_t comp1 = 0;
uint16_t comp2 = 0;
uint16_t conf = 0;
float uvi = 0.0f;
} veml6075_sensor;
uint8_t veml6075_active = 0;
// typedef of config register
typedef union {
struct {
uint8_t pwr:1; // Shut Down
uint8_t forded_auto:1; // Auto or forced
uint8_t forced_trigger:1; // Trigger forced mode
uint8_t hd:1; // High dynamic
uint8_t inttime:3; // Integration Time
uint8_t spare7:1; // spare
};
uint16_t config;
} veml6075configRegister;
veml6075configRegister veml6075Config;
/********************************************************************************************/
uint16_t VEML6075read16 (uint8_t reg) {
uint16_t swap = I2cRead16(VEML6075_ADDR, reg);
uint16_t ret = ((swap & 0xFF) << 8) | (swap >> 8);
return ret;
}
void VEML6075write16 (uint8_t reg, uint16_t val) {
uint16_t swap = ((val & 0xFF) << 8) | (val >> 8);
I2cWrite16(VEML6075_ADDR, reg, swap);
}
float VEML6075calcUVA (void) {
float uva_calc = veml6075_sensor.uva_raw - (VEML6075_DEFAULT_UVA_A_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVA_B_COEFF * veml6075_sensor.comp2);
return uva_calc;
}
float VEML6075calcUVB (void) {
float uvb_calc = veml6075_sensor.uvb_raw - (VEML6075_DEFAULT_UVB_C_COEFF * veml6075_sensor.comp1) - (VEML6075_DEFAULT_UVB_D_COEFF * veml6075_sensor.comp2);
return uvb_calc;
}
float VEML6075calcUVI (void) {
float uvi_calc = ((veml6075_sensor.uva * UVA_RESPONSIVITY[veml6075_sensor.inttime]) + (veml6075_sensor.uvb * UVB_RESPONSIVITY[veml6075_sensor.inttime])) / 2;
return uvi_calc;
}
void VEML6075SetHD(uint8_t val){
veml6075Config.hd = val;
VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config);
}
uint8_t VEML6075ReadHD(void){
veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF);
return veml6075Config.hd;
}
void VEML6075SetUvIt(uint8_t val){
veml6075Config.inttime = val;
VEML6075Pwr(1);
VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config);
VEML6075Pwr(0);
}
uint8_t VEML6075GetUvIt(void){
veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF);
return veml6075Config.inttime;
}
void VEML6075Pwr(uint8_t val){
veml6075Config.pwr = val;
VEML6075write16 (VEML6075_REG_CONF, veml6075Config.config);
}
uint8_t VEML6075GetPwr(void){
veml6075Config.config = VEML6075read16 (VEML6075_REG_CONF);
return veml6075Config.pwr;
}
void VEML6075ReadData(void)
{
veml6075_sensor.uva_raw = VEML6075read16 (VEML6075_REG_UVA);
veml6075_sensor.uvb_raw = VEML6075read16 (VEML6075_REG_UVB);
veml6075_sensor.comp1 = VEML6075read16 (VEML6075_REG_UVCOMP1);
veml6075_sensor.comp2 = VEML6075read16 (VEML6075_REG_UVCOMP2);
veml6075_sensor.inttime = VEML6075GetUvIt();
veml6075_sensor.uva = VEML6075calcUVA();
veml6075_sensor.uvb = VEML6075calcUVB();
veml6075_sensor.uvi = VEML6075calcUVI();
}
bool VEML6075init(void)
{
uint8_t id = VEML6075read16 (VEML6075_REG_ID);
if(id == VEML6075_CHIP_ID) // Sensor id
return true;
return false;
}
void VEML6075Detect(void) {
if (I2cActive(veml6075_sensor.address)) return;
if (VEML6075init()) {
I2cSetActiveFound(veml6075_sensor.address, veml6075_sensor.types);
VEML6075write16 (VEML6075_REG_CONF, 0x10); // set default
veml6075_active = 1;
}
}
void VEML6075EverySecond(void) {
VEML6075ReadData();
}
bool VEML6075Cmd(void) {
char command[CMDSZ];
uint8_t name_len = strlen(D_NAME_VEML6075);
if (!strncasecmp_P(XdrvMailbox.topic, PSTR(D_NAME_VEML6075), name_len)) {
uint32_t command_code = GetCommandCode(command, sizeof(command), XdrvMailbox.topic + name_len, kVEML6075_Commands);
switch (command_code) {
case CMND_VEML6075_PWR:
if (XdrvMailbox.data_len) {
if (2 >= XdrvMailbox.payload) {
VEML6075Pwr(XdrvMailbox.payload);
}
}
Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetPwr());
break;
case CMND_VEML6075_SET_HD:
if (XdrvMailbox.data_len) {
if (2 >= XdrvMailbox.payload) {
VEML6075SetHD(XdrvMailbox.payload);
}
}
Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075ReadHD());
break;
case CMND_VEML6075_SET_UVIT:
if (XdrvMailbox.data_len) {
if (4 >= XdrvMailbox.payload) {
VEML6075SetUvIt(XdrvMailbox.payload);
}
}
Response_P(S_JSON_VEML6075_COMMAND_NVALUE, command, VEML6075GetUvIt());
break;
default:
return false;
}
return true;
} else {
return false;
}
}
void VEML6075Show(bool json)
{
char s_uvindex[FLOATSZ];
dtostrfd(veml6075_sensor.uvi,1, s_uvindex);
if (json) {
ResponseAppend_P(JSON_SNS_VEML6075, D_NAME_VEML6075, veml6075_sensor.uva, veml6075_sensor.uvb, s_uvindex);
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_UVA, D_NAME_VEML6075, veml6075_sensor.uva);
WSContentSend_PD(HTTP_SNS_UVB, D_NAME_VEML6075, veml6075_sensor.uvb);
WSContentSend_PD(HTTP_SNS_UVINDEX, D_NAME_VEML6075 ,s_uvindex);
#endif // USE_WEBSERVER
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns70(uint8_t function)
{
if (!I2cEnabled(XI2C_49)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
VEML6075Detect();
}
else if (veml6075_active) {
switch (function) {
case FUNC_EVERY_SECOND:
VEML6075EverySecond();
break;
case FUNC_COMMAND:
result = VEML6075Cmd();
break;
case FUNC_JSON_APPEND:
VEML6075Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
VEML6075Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_VEML6075
#endif // USE_I2C

View File

@ -0,0 +1,117 @@
/*
xsns_71_VEML7700.ino - VEML7700 Franklin Lightning Sensor support for Tasmota
Copyright (C) 2020 Martin Wagner
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifdef USE_I2C
#ifdef USE_VEML7700
/*********************************************************************************************\
* VEML7700 ALS Sensor
* Using the Adafruit VEML7700 Libary
* I2C Address: 0x10
\*********************************************************************************************/
#define XSNS_71 71
#define XI2C_50 50 // See I2CDEVICES.md
#include "Adafruit_VEML7700.h"
Adafruit_VEML7700 veml7700 = Adafruit_VEML7700(); //create object copy
#define D_NAME_VEML7700 "VEML7700"
#define D_WHITE_CONTENT "White content"
const char HTTP_SNS_LUX[] PROGMEM = "{s}%s " D_ILLUMINANCE "{m}%d " D_UNIT_LUX " {e}";
const char HTTP_SNS_WHITE[] PROGMEM = "{s}%s " D_WHITE_CONTENT "{m}%d {e}";
const char JSON_SNS_VEML7700[] PROGMEM = ",\"%s\":{\"" D_JSON_ILLUMINANCE "\":%d,\"" D_JSON_WHITE_CONTENT "\":%d}";
struct VEML7700STRUCT
{
char types[9] = D_NAME_VEML7700;
uint8_t address = VEML7700_I2CADDR_DEFAULT;
uint16_t lux = 0;
uint16_t white = 0;
} veml7700_sensor;
uint8_t veml7700_active = 0;
/********************************************************************************************/
void VEML7700Detect(void) {
if (I2cActive(veml7700_sensor.address)) return;
if (veml7700.begin()) {
I2cSetActiveFound(veml7700_sensor.address, veml7700_sensor.types);
veml7700_active = 1;
}
}
void VEML7700EverySecond(void) {
veml7700_sensor.lux = (uint16_t) veml7700.readLux();
veml7700_sensor.white = (uint16_t) veml7700.readWhite();
}
void VEML7700Show(bool json)
{
if (json) {
ResponseAppend_P(JSON_SNS_VEML7700, D_NAME_VEML7700, veml7700_sensor.lux, veml7700_sensor.white);
#ifdef USE_DOMOTICZ
if (0 == tele_period) DomoticzSensor(DZ_ILLUMINANCE, veml7700_sensor.lux);
#endif // USE_DOMOTICZ
#ifdef USE_WEBSERVER
} else {
WSContentSend_PD(HTTP_SNS_LUX, D_NAME_VEML7700, veml7700_sensor.lux);
WSContentSend_PD(HTTP_SNS_WHITE, D_NAME_VEML7700, veml7700_sensor.white);
#endif // USE_WEBSERVER
}
}
/*********************************************************************************************\
* Interface
\*********************************************************************************************/
bool Xsns71(uint8_t function)
{
if (!I2cEnabled(XI2C_50)) { return false; }
bool result = false;
if (FUNC_INIT == function) {
VEML7700Detect();
}
else if (veml7700_active) {
switch (function) {
case FUNC_EVERY_SECOND:
VEML7700EverySecond();
break;
case FUNC_COMMAND:
//result = VEML7700Cmd();
break;
case FUNC_JSON_APPEND:
VEML7700Show(1);
break;
#ifdef USE_WEBSERVER
case FUNC_WEB_SENSOR:
VEML7700Show(0);
break;
#endif // USE_WEBSERVER
}
}
return result;
}
#endif // USE_VEML7700
#endif // USE_I2C