+++ /dev/null
-#include "arduino.h"
-
-Adafruit_I2CDevice::Adafruit_I2CDevice (uint8_t addr) {
-}
-
-
-bool Adafruit_I2CDevice::begin (bool addr_detect) {
- return false;
-}
-
-void Adafruit_I2CDevice::end (void) {
-
-}
-
-bool Adafruit_I2CDevice::read (uint8_t *buffer, size_t len, bool stop) {
- return false;
-}
-
-bool Adafruit_I2CDevice::write (const uint8_t *buffer, size_t len) {
- return false;
-}
-
-// bool write(const uint8_t *buffer, size_t len, bool stop = true,
-// const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
-
-bool Adafruit_I2CDevice::write_then_read (const uint8_t *write_buffer, size_t write_len, uint8_t *read_buffer, size_t read_len, bool stop) {
- return false;
-}
+++ /dev/null
-#ifndef __ARDUINO_H__
-#define __ARDUINO_H__
-
-#include <stdint.h>
-#include <string.h>
-
-#define byte uint8_t
-
-
-
-class Adafruit_SPIDevice {};
-
-class SPIClass {};
-
-class TwoWire {};
-
-extern SPIClass SPI;
-extern TwoWire Wire;
-extern uint32_t millis ();
-
-class Adafruit_I2CDevice {
- public:
- Adafruit_I2CDevice(uint8_t addr);
- bool begin(bool addr_detect = true);
- void end(void);
- bool read(uint8_t *buffer, size_t len, bool stop = true);
- bool write(const uint8_t *buffer, size_t len);
- // bool write(const uint8_t *buffer, size_t len, bool stop = true,
- // const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
-
- bool write_then_read(const uint8_t *write_buffer, size_t write_len,
- uint8_t *read_buffer, size_t read_len,
- bool stop = false);
-
-
- private:
- uint8_t _addr;
- TwoWire *_wire;
- bool _begun;
- size_t _maxBufferSize;
- bool _read(uint8_t *buffer, size_t len, bool stop);
-};
-
-
-
-#endif
\ No newline at end of file
-/*!
- * @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.
- *
- */
-
-// #include "Adafruit_BME280.h"
-// #include "Arduino.h"
-
#include "bme280.h"
-#include "arduino.h"
#include <util/delay.h>
+#include <stdio.h>
Adafruit_BME280 theBME280;
Adafruit_BME280_Temp bm280TempSensor;
Adafruit_BME280_Pressure bm280PressureSensor;
Adafruit_BME280_Humidity bm280HumiditySensor;
-
-
-/*!
- * @brief class constructor
- */
Adafruit_BME280::Adafruit_BME280() {
- t_fine_adjust = 0;
- temp_sensor = &bm280TempSensor;
- pressure_sensor = &bm280PressureSensor;
- humidity_sensor = &bm280HumiditySensor;
+ static I2cDevice i2cDevice;
+ t_fine_adjust = 0;
+ temp_sensor = &bm280TempSensor;
+ pressure_sensor = &bm280PressureSensor;
+ humidity_sensor = &bm280HumiditySensor;
+ i2c_dev = &i2cDevice;
}
-// /*!
-// * @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) {
-// spi_dev = new Adafruit_SPIDevice(cspin, 1000000, SPI_BITORDER_MSBFIRST,
-// SPI_MODE0, theSPI);
-// }
-
-/*!
- * @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, defaults to &Wire
- * @returns true on success, false otherwise
- */
bool Adafruit_BME280::begin (uint8_t addr) {
- if (!i2c_dev->begin()) {
- return false;
- }
- return init();
+ if (!i2c_dev->begin(addr)) {
+ return false;
+ }
+ return init();
}
-/*!
- * @brief Initialise sensor with given parameters / settings
- * @returns true on success, false otherwise
- */
bool Adafruit_BME280::init() {
- // check if sensor, i.e. the chip ID is correct
- _sensorID = read8(BME280_REGISTER_CHIPID);
- if (_sensorID != 0x60)
- return false;
-
- // reset the device using soft-reset
- // this makes sure the IIR is off, etc.
- write8(BME280_REGISTER_SOFTRESET, 0xB6);
-
- // wait for chip to wake up.
- _delay_ms(10);
-
- // if chip is still reading calibration, delay
- while (isReadingCalibration())
- _delay_ms(10);
-
- readCoefficients(); // read trimming parameters, see DS 4.2.2
-
- setSampling(); // use defaults
-
- _delay_ms(100);
-
- return true;
+ _sensorID = read8(BME280_REGISTER_CHIPID);
+ if (_sensorID != 0x60) {
+ return false;
+ }
+ write8(BME280_REGISTER_SOFTRESET, 0xB6);
+ _delay_ms(10); // wait for chip to wake up.
+
+ // if chip is still reading calibration, delay
+ while (isReadingCalibration()) {
+ _delay_ms(10);
+ }
+
+ readCoefficients(); // read trimming parameters, see DS 4.2.2
+ setSampling(); // use defaults
+ _delay_ms(100);
+
+ return true;
}
/*!
* @param duration the standby duration to use
*/
void Adafruit_BME280::setSampling(sensor_mode mode,
- sensor_sampling tempSampling,
- sensor_sampling pressSampling,
- sensor_sampling humSampling,
- sensor_filter filter,
- standby_duration duration) {
+ sensor_sampling tempSampling,
+ sensor_sampling pressSampling,
+ sensor_sampling humSampling,
+ sensor_filter filter,
+ standby_duration duration) {
_measReg.mode = mode;
_measReg.osrs_t = tempSampling;
_measReg.osrs_p = pressSampling;
byte buffer[2];
buffer[1] = value;
if (i2c_dev) {
- buffer[0] = reg;
- i2c_dev->write(buffer, 2);
+ buffer[0] = reg;
+ i2c_dev->write(buffer, 2);
}
}
uint8_t Adafruit_BME280::read8(byte reg) {
uint8_t buffer[1];
if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 1);
+ buffer[0] = uint8_t(reg);
+ i2c_dev->write_then_read(buffer, 1, buffer, 1);
}
return buffer[0];
}
uint8_t buffer[2];
if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 2);
+ buffer[0] = uint8_t(reg);
+ i2c_dev->write_then_read(buffer, 1, buffer, 2);
}
return uint16_t(buffer[0]) << 8 | uint16_t(buffer[1]);
}
uint8_t buffer[3];
if (i2c_dev) {
- buffer[0] = uint8_t(reg);
- i2c_dev->write_then_read(buffer, 1, buffer, 3);
+ buffer[0] = uint8_t(reg);
+ i2c_dev->write_then_read(buffer, 1, buffer, 3);
}
return uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 |
- uint32_t(buffer[2]);
+ uint32_t(buffer[2]);
}
/*!
* @brief Take a new measurement (only possible in forced mode)
- @returns true in case of success else false
+ @returns true in case of success else false
*/
bool Adafruit_BME280::takeForcedMeasurement(void) {
bool return_value = false;
// it will take the next measurement and then return to sleep again.
// In normal mode simply does new measurements periodically.
if (_measReg.mode == MODE_FORCED) {
- return_value = true;
- // set to forced mode, i.e. "take next measurement"
- write8(BME280_REGISTER_CONTROL, _measReg.get());
- // Store current time to measure the timeout
- uint32_t timeout_start = millis();
- // wait until measurement has been completed, otherwise we would read the
- // the values from the last measurement or the timeout occurred after 2 sec.
- while (read8(BME280_REGISTER_STATUS) & 0x08) {
- // In case of a timeout, stop the while loop
- if ((millis() - timeout_start) > 2000) {
- return_value = false;
- break;
- }
- _delay_ms(1);
- }
+ return_value = true;
+ // set to forced mode, i.e. "take next measurement"
+ write8(BME280_REGISTER_CONTROL, _measReg.get());
+ // Store current time to measure the timeout
+ uint32_t timeout_start = millis();
+ // wait until measurement has been completed, otherwise we would read the
+ // the values from the last measurement or the timeout occurred after 2 sec.
+ while (read8(BME280_REGISTER_STATUS) & 0x08) {
+ // In case of a timeout, stop the while loop
+ if ((millis() - timeout_start) > 2000) {
+ return_value = false;
+ break;
+ }
+ _delay_ms(1);
+ }
}
return return_value;
}
_bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2);
_bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3);
_bme280_calib.dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) |
- (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
+ (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF);
_bme280_calib.dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) |
- (read8(BME280_REGISTER_DIG_H5) >> 4);
+ (read8(BME280_REGISTER_DIG_H5) >> 4);
_bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6);
}
int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
if (adc_T == 0x800000) // value in case temp measurement was disabled
- return NAN;
+ return NAN;
adc_T >>= 4;
var1 = (int32_t)((adc_T / 8) - ((int32_t)_bme280_calib.dig_T1 * 2));
int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);
if (adc_P == 0x800000) // value in case pressure measurement was disabled
- return NAN;
+ return NAN;
adc_P >>= 4;
var1 = ((int64_t)t_fine) - 128000;
var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) * 131072);
var2 = var2 + (((int64_t)_bme280_calib.dig_P4) * 34359738368);
var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) / 256) +
- ((var1 * ((int64_t)_bme280_calib.dig_P2) * 4096));
+ ((var1 * ((int64_t)_bme280_calib.dig_P2) * 4096));
var3 = ((int64_t)1) * 140737488355328;
var1 = (var3 + var1) * ((int64_t)_bme280_calib.dig_P1) / 8589934592;
if (var1 == 0) {
- return 0; // avoid exception caused by division by zero
+ return 0; // avoid exception caused by division by zero
}
var4 = 1048576 - adc_P;
var4 = (((var4 * 2147483648UL) - var2) * 3125) / var1;
var1 = (((int64_t)_bme280_calib.dig_P9) * (var4 / 8192) * (var4 / 8192)) /
- 33554432;
+ 33554432;
var2 = (((int64_t)_bme280_calib.dig_P8) * var4) / 524288;
var4 = ((var4 + var1 + var2) / 256) + (((int64_t)_bme280_calib.dig_P7) * 16);
int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
if (adc_H == 0x8000) // value in case humidity measurement was disabled
- return NAN;
+ return NAN;
var1 = t_fine - ((int32_t)76800);
var2 = (int32_t)(adc_H * 16384);
/**************************************************************************/
/*!
- @brief Gets the sensor_t data for the BME280's temperature sensor
+ @brief Gets the sensor_t data for the BME280's temperature sensor
*/
/**************************************************************************/
void Adafruit_BME280_Temp::getSensor(sensor_t *sensor) {
/**************************************************************************/
/*!
- @brief Gets the temperature as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
+ @brief Gets the temperature as a standard sensor event
+ @param event Sensor event object that will be populated
+ @returns True
*/
/**************************************************************************/
bool Adafruit_BME280_Temp::getEvent(sensors_event_t *event) {
/**************************************************************************/
/*!
- @brief Gets the sensor_t data for the BME280's pressure sensor
+ @brief Gets the sensor_t data for the BME280's pressure sensor
*/
/**************************************************************************/
void Adafruit_BME280_Pressure::getSensor(sensor_t *sensor) {
/**************************************************************************/
/*!
- @brief Gets the pressure as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
+ @brief Gets the pressure as a standard sensor event
+ @param event Sensor event object that will be populated
+ @returns True
*/
/**************************************************************************/
bool Adafruit_BME280_Pressure::getEvent(sensors_event_t *event) {
/**************************************************************************/
/*!
- @brief Gets the sensor_t data for the BME280's humidity sensor
+ @brief Gets the sensor_t data for the BME280's humidity sensor
*/
/**************************************************************************/
void Adafruit_BME280_Humidity::getSensor(sensor_t *sensor) {
/**************************************************************************/
/*!
- @brief Gets the humidity as a standard sensor event
- @param event Sensor event object that will be populated
- @returns True
+ @brief Gets the humidity as a standard sensor event
+ @param event Sensor event object that will be populated
+ @returns True
*/
/**************************************************************************/
bool Adafruit_BME280_Humidity::getEvent(sensors_event_t *event) {
// #include <Adafruit_Sensor.h>
+#include "../i2cdevice.hpp"
+#include "../main.hpp"
+#define byte uint8_t
+
+
+
#include <stdint.h>
#include <string.h>
-#include "arduino.h"
#include "sensor.h"
/*!
void setTemperatureCompensation(float);
protected:
- Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
- Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface
+ I2cDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface
+ // Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface
Adafruit_BME280_Temp *temp_sensor;
Adafruit_BME280_Pressure *pressure_sensor;
--- /dev/null
+/*
+ ScioSense_ENS160.h - Library for the ENS160 sensor with I2C interface from ScioSense
+ 2023 Mar 23 v6 Christoph Friese Bugfix measurement routine, prepare next release
+ 2021 Nov 25 v5 Martin Herold Custom mode timing fixed
+ 2021 Feb 04 v4 Giuseppe de Pinto Custom mode fixed
+ 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
+ 2020 Feb 15 v2 Giuseppe Pasetti Corrected firmware flash option
+ 2019 May 05 v1 Christoph Friese Created
+ based on application note "ENS160 Software Integration.pdf" rev 0.01
+*/
+
+#include "ens160.h"
+#include "math.h"
+#include <util/delay.h>
+
+ScioSense_ENS160::ScioSense_ENS160 () {
+ _revENS16x = 0;
+
+ //Isotherm, HP0 252°C / HP1 350°C / HP2 250°C / HP3 324°C / measure every 1008ms
+ _seq_steps[0][0] = 0x7c;
+ _seq_steps[0][1] = 0x0a;
+ _seq_steps[0][2] = 0x7e;
+ _seq_steps[0][3] = 0xaf;
+ _seq_steps[0][4] = 0xaf;
+ _seq_steps[0][5] = 0xa2;
+ _seq_steps[0][6] = 0x00;
+ _seq_steps[0][7] = 0x80;
+}
+
+bool ScioSense_ENS160::begin () {
+ i2cDevice.begin(ENS160_I2CADDR_1);
+ _delay_ms(ENS160_BOOTING);
+
+ if (reset()) {
+ if (checkPartID()) {
+ if (setMode(ENS160_OPMODE_IDLE)) {
+ if (clearCommand()) {
+ if (getFirmware()) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+
+}
+
+bool ScioSense_ENS160::write8 (byte reg, byte value) {
+ byte buffer[2];
+ buffer[1] = value;
+ buffer[0] = reg;
+ return i2cDevice.write(buffer, 2);
+}
+
+bool ScioSense_ENS160::read8 (byte reg, byte *value) {
+ uint8_t buffer[1];
+ buffer[0] = uint8_t(reg);
+ return i2cDevice.write_then_read(buffer, 1, value, 1);
+}
+
+bool ScioSense_ENS160::read16 (byte reg, uint16_t *value) {
+ uint8_t buffer[1];
+ buffer[0] = uint8_t(reg);
+ return i2cDevice.write_then_read(buffer, 1, (uint8_t *)value, 2);
+}
+
+bool ScioSense_ENS160::read16LE (byte reg, uint16_t *value) {
+ uint16_t tmp;
+ if (read16(reg, &tmp)) {
+ *value = ((tmp & 0xff) << 8) | (tmp >> 8);
+ return true;
+ }
+ return false;
+}
+
+bool ScioSense_ENS160::readBytes (byte reg, uint8_t *bytes, uint8_t len) {
+ uint8_t buffer[1];
+ buffer[0] = uint8_t(reg);
+ return i2cDevice.write_then_read(buffer, 1, buffer, len);
+}
+
+
+// Sends a reset to the ENS160. Returns false on I2C problems.
+bool ScioSense_ENS160::reset () {
+ if (write8(ENS160_REG_OPMODE, ENS160_OPMODE_RESET)) {
+ _delay_ms(ENS160_BOOTING);
+ return true;
+ }
+ _delay_ms(ENS160_BOOTING);
+ return false;
+}
+
+// Reads the part ID and confirms valid sensor
+bool ScioSense_ENS160::checkPartID () {
+ uint8_t i2cbuf[2];
+ uint16_t part_id;
+
+ read16(ENS160_REG_PART_ID, &part_id);
+ part_id = i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8);
+
+ _delay_ms(ENS160_BOOTING);
+
+ if (part_id == ENS160_PARTID) {
+ _revENS16x = 0;
+ return true;
+
+ } else if (part_id == ENS161_PARTID) {
+ _revENS16x = 1;
+ return true;
+ }
+
+ return false;
+}
+
+// Initialize idle mode and confirms
+bool ScioSense_ENS160::clearCommand () {
+ uint8_t status;
+
+ if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_NOP)) {
+ if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_CLRGPR)) {
+ _delay_ms(ENS160_BOOTING);
+ if (read8(ENS160_REG_DATA_STATUS, &status)) {
+ return true;
+ }
+ }
+ }
+ _delay_ms(ENS160_BOOTING);
+ return false;
+}
+
+// Read firmware revisions
+bool ScioSense_ENS160::getFirmware () {
+ uint8_t i2cbuf[3];
+
+ if (clearCommand()) {
+ _delay_ms(ENS160_BOOTING);
+ if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_GET_APPVER)) {
+ if (readBytes(ENS160_REG_GPR_READ_4, i2cbuf, 3)) {
+ _fw_ver_major = i2cbuf[0];
+ _fw_ver_minor = i2cbuf[1];
+ _fw_ver_build = i2cbuf[2];
+ _revENS16x = this->_fw_ver_major > 6 ? 1 : 0;
+ _delay_ms(ENS160_BOOTING);
+ return true;
+ }
+ }
+ }
+ _delay_ms(ENS160_BOOTING);
+ return false;
+}
+
+// Set operation mode of sensor
+bool ScioSense_ENS160::setMode (uint8_t mode) {
+ //LP only valid for rev>0
+ if ((mode == ENS160_OPMODE_LP) and (_revENS16x == 0)) {
+ return false;
+ }
+ if (write8(ENS160_REG_OPMODE, mode)) {
+ _delay_ms(ENS160_BOOTING);
+ return true;
+ }
+ _delay_ms(ENS160_BOOTING);
+ return false;
+}
+
+// Initialize definition of custom mode with <n> steps
+bool ScioSense_ENS160::initCustomMode (uint16_t stepNum) {
+ if (stepNum > 0) {
+ _stepCount = stepNum;
+ if (setMode(ENS160_OPMODE_IDLE)) {
+ if (clearCommand()) {
+ if (write8(ENS160_REG_COMMAND, ENS160_COMMAND_SETSEQ)) {
+ _delay_ms(ENS160_BOOTING);
+ return true;
+ }
+ }
+ }
+ }
+ _delay_ms(ENS160_BOOTING);
+ return false;
+}
+
+// Add a step to custom measurement profile with definition of duration, enabled data acquisition and temperature for each hotplate
+bool ScioSense_ENS160::addCustomStep (uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3) {
+ uint8_t seq_ack;
+ uint8_t temp;
+
+ _delay_ms(ENS160_BOOTING);
+
+ temp = (uint8_t)(((time / 24) - 1) << 6);
+ if (measureHP0) {
+ temp = temp | 0x20;
+ }
+ if (measureHP1) {
+ temp = temp | 0x10;
+ }
+ if (measureHP2) {
+ temp = temp | 0x08;
+ }
+ if (measureHP3) {
+ temp = temp | 0x04;
+ }
+ if (!write8(ENS160_REG_GPR_WRITE_0, temp)) {
+ return false;
+ }
+ temp = (uint8_t)(((time / 24) - 1) >> 2);
+ if (!write8(ENS160_REG_GPR_WRITE_1, temp)) {
+ return false;
+ }
+ if (!write8(ENS160_REG_GPR_WRITE_2, (uint8_t)(tempHP0 / 2))) {
+ return false;
+ }
+ if (!write8(ENS160_REG_GPR_WRITE_3, (uint8_t)(tempHP1 / 2))) {
+ return false;
+ }
+ if (write8(ENS160_REG_GPR_WRITE_4, (uint8_t)(tempHP2 / 2))) {
+ return false;
+ }
+ if (write8(ENS160_REG_GPR_WRITE_5, (uint8_t)(tempHP3 / 2))) {
+ return false;
+ }
+
+ if (write8(ENS160_REG_GPR_WRITE_6, (uint8_t)(_stepCount - 1))) {
+ return false;
+ }
+
+ if (_stepCount == 1) {
+ if (!write8(ENS160_REG_GPR_WRITE_7, 128)) {
+ return false;
+ }
+ } else {
+ if (!write8(ENS160_REG_GPR_WRITE_7, 0)) {
+ return false;
+ }
+ }
+ _delay_ms(ENS160_BOOTING);
+
+ if (!read8(ENS160_REG_GPR_READ_7, &seq_ack)) {
+ return false;
+ }
+ _delay_ms(ENS160_BOOTING);
+
+ if ((ENS160_SEQ_ACK_COMPLETE | _stepCount) != seq_ack) {
+ _stepCount++;
+ return false;
+ }
+
+ return true;
+}
+
+// Perform prediction measurement and stores result in internal variables
+bool ScioSense_ENS160::measure (bool waitForNew) {
+ uint8_t i2cbuf[8];
+ uint8_t status;
+
+ // Set default status for early bail out
+ if (waitForNew) {
+ do {
+ _delay_ms(1);
+ if (!read8(ENS160_REG_DATA_STATUS, &status)) {
+ return false;
+ }
+ } while (!IS_NEWDAT(status));
+ } else {
+ if (!read8(ENS160_REG_DATA_STATUS, &status)) {
+ return false;
+ }
+ }
+
+ // Read predictions
+ if (IS_NEWDAT(status)) {
+ if (!readBytes(ENS160_REG_DATA_AQI, i2cbuf, 7)) {
+ return false;
+ }
+ _data_aqi = i2cbuf[0];
+ _data_tvoc = i2cbuf[1] | ((uint16_t)i2cbuf[2] << 8);
+ _data_eco2 = i2cbuf[3] | ((uint16_t)i2cbuf[4] << 8);
+ if (_revENS16x > 0) {
+ _data_aqi500 = ((uint16_t)i2cbuf[5]) | ((uint16_t)i2cbuf[6] << 8);
+ } else {
+ _data_aqi500 = 0;
+ }
+ return true;
+ }
+
+ return false;
+}
+
+// Perfrom raw measurement and stores result in internal variables
+bool ScioSense_ENS160::measureRaw (bool waitForNew) {
+ uint8_t i2cbuf[8];
+ uint8_t status;
+
+ // Set default status for early bail out
+ if (waitForNew) {
+ do {
+ _delay_ms(1);
+ if (!read8(ENS160_REG_DATA_STATUS, &status)) {
+ return false;
+ }
+ } while (!IS_NEWGPR(status));
+ } else {
+ if (!read8(ENS160_REG_DATA_STATUS, &status)) {
+ return false;
+ }
+ }
+
+ if (IS_NEWGPR(status)) {
+
+ // Read raw resistance values
+ if (!readBytes(ENS160_REG_GPR_READ_0, i2cbuf, 8)) {
+ return false;
+ }
+ _hp0_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8)));
+ _hp1_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8)));
+ _hp2_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8)));
+ _hp3_rs = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8)));
+
+ // Read baselines
+ if (!readBytes(ENS160_REG_DATA_BL, i2cbuf, 8)) {
+ return false;
+ }
+ _hp0_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[0] | ((uint16_t)i2cbuf[1] << 8)));
+ _hp1_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[2] | ((uint16_t)i2cbuf[3] << 8)));
+ _hp2_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[4] | ((uint16_t)i2cbuf[5] << 8)));
+ _hp3_bl = CONVERT_RS_RAW2OHMS_F((uint32_t)(i2cbuf[6] | ((uint16_t)i2cbuf[7] << 8)));
+
+ if (!read8(ENS160_REG_DATA_MISR, i2cbuf)) {
+ return false;
+ }
+ _misr = i2cbuf[0];
+ return true;
+ }
+
+ return false;
+}
+
+
+// Writes t (degC) and h (%rh) to ENV_DATA. Returns false on I2C problems.
+bool ScioSense_ENS160::set_envdata (float t, float h) {
+ uint16_t t_data = (uint16_t)((t + 273.15f) * 64.0f);
+ uint16_t rh_data = (uint16_t)(h * 512.0f);
+ return this->set_envdata210(t_data, rh_data);
+}
+
+// Writes t and h (in ENS210 format) to ENV_DATA. Returns false on I2C problems.
+bool ScioSense_ENS160::set_envdata210 (uint16_t t, uint16_t h) {
+ //uint16_t temp;
+ uint8_t trh_in[4];
+
+ //temp = (uint16_t)((t + 273.15f) * 64.0f);
+ trh_in[0] = t & 0xff;
+ trh_in[1] = (t >> 8) & 0xff;
+
+ //temp = (uint16_t)(h * 512.0f);
+ trh_in[2] = h & 0xff;
+ trh_in[3] = (h >> 8) & 0xff;
+
+ if (!i2cDevice.writeByteAndBuffer(ENS160_REG_TEMP_IN, trh_in, 4)) {
+ return false;
+ }
+
+ return true;
+}
--- /dev/null
+/*
+ ScioSense_ENS160.h - Library for the ENS160 sensor with I2C interface from ScioSense
+ 2023 Mar 23 v6 Christoph Friese Bugfix measurement routine, prepare next release
+ 2021 July 29 v4 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
+ 2020 Apr 06 v3 Christoph Friese Changed nomenclature to ScioSense as product shifted from ams
+ 2020 Feb 15 v2 Giuseppe Pasetti Corrected firmware flash option
+ 2019 May 05 v1 Christoph Friese Created
+ based on application note "ENS160 Software Integration.pdf" rev 0.01
+*/
+
+#ifndef __SCIOSENSE_ENS160_H_
+#define __SCIOSENSE_ENS160_H_
+
+#include "../i2cdevice.hpp"
+#include <stdint.h>
+#define byte uint8_t
+
+// #if (ARDUINO >= 100)
+// #include "Arduino.h"
+// #else
+// #include "WProgram.h"
+// #endif
+
+// #include <Wire.h>
+
+// Chip constants
+#define ENS160_PARTID 0x0160
+#define ENS161_PARTID 0x0161
+#define ENS160_BOOTING 10
+
+// 7-bit I2C slave address of the ENS160
+#define ENS160_I2CADDR_0 0x52 //ADDR low
+#define ENS160_I2CADDR_1 0x53 //ADDR high
+
+// ENS160 registers for version V0
+#define ENS160_REG_PART_ID 0x00 // 2 byte register
+#define ENS160_REG_OPMODE 0x10
+#define ENS160_REG_CONFIG 0x11
+#define ENS160_REG_COMMAND 0x12
+#define ENS160_REG_TEMP_IN 0x13
+#define ENS160_REG_RH_IN 0x15
+#define ENS160_REG_DATA_STATUS 0x20
+#define ENS160_REG_DATA_AQI 0x21
+#define ENS160_REG_DATA_TVOC 0x22
+#define ENS160_REG_DATA_ECO2 0x24
+#define ENS160_REG_DATA_BL 0x28
+#define ENS160_REG_DATA_T 0x30
+#define ENS160_REG_DATA_RH 0x32
+#define ENS160_REG_DATA_MISR 0x38
+#define ENS160_REG_GPR_WRITE_0 0x40
+#define ENS160_REG_GPR_WRITE_1 ENS160_REG_GPR_WRITE_0 + 1
+#define ENS160_REG_GPR_WRITE_2 ENS160_REG_GPR_WRITE_0 + 2
+#define ENS160_REG_GPR_WRITE_3 ENS160_REG_GPR_WRITE_0 + 3
+#define ENS160_REG_GPR_WRITE_4 ENS160_REG_GPR_WRITE_0 + 4
+#define ENS160_REG_GPR_WRITE_5 ENS160_REG_GPR_WRITE_0 + 5
+#define ENS160_REG_GPR_WRITE_6 ENS160_REG_GPR_WRITE_0 + 6
+#define ENS160_REG_GPR_WRITE_7 ENS160_REG_GPR_WRITE_0 + 7
+#define ENS160_REG_GPR_READ_0 0x48
+#define ENS160_REG_GPR_READ_4 ENS160_REG_GPR_READ_0 + 4
+#define ENS160_REG_GPR_READ_6 ENS160_REG_GPR_READ_0 + 6
+#define ENS160_REG_GPR_READ_7 ENS160_REG_GPR_READ_0 + 7
+
+//ENS160 data register fields
+#define ENS160_COMMAND_NOP 0x00
+#define ENS160_COMMAND_CLRGPR 0xCC
+#define ENS160_COMMAND_GET_APPVER 0x0E
+#define ENS160_COMMAND_SETTH 0x02
+#define ENS160_COMMAND_SETSEQ 0xC2
+
+#define ENS160_OPMODE_RESET 0xF0
+#define ENS160_OPMODE_DEP_SLEEP 0x00
+#define ENS160_OPMODE_IDLE 0x01
+#define ENS160_OPMODE_STD 0x02
+#define ENS160_OPMODE_LP 0x03
+#define ENS160_OPMODE_CUSTOM 0xC0
+
+#define ENS160_BL_CMD_START 0x02
+#define ENS160_BL_CMD_ERASE_APP 0x04
+#define ENS160_BL_CMD_ERASE_BLINE 0x06
+#define ENS160_BL_CMD_WRITE 0x08
+#define ENS160_BL_CMD_VERIFY 0x0A
+#define ENS160_BL_CMD_GET_BLVER 0x0C
+#define ENS160_BL_CMD_GET_APPVER 0x0E
+#define ENS160_BL_CMD_EXITBL 0x12
+
+#define ENS160_SEQ_ACK_NOTCOMPLETE 0x80
+#define ENS160_SEQ_ACK_COMPLETE 0xC0
+
+#define IS_ENS160_SEQ_ACK_NOT_COMPLETE(x) (ENS160_SEQ_ACK_NOTCOMPLETE == (ENS160_SEQ_ACK_NOTCOMPLETE & (x)))
+#define IS_ENS160_SEQ_ACK_COMPLETE(x) (ENS160_SEQ_ACK_COMPLETE == (ENS160_SEQ_ACK_COMPLETE & (x)))
+
+#define ENS160_DATA_STATUS_NEWDAT 0x02
+#define ENS160_DATA_STATUS_NEWGPR 0x01
+
+#define IS_NEWDAT(x) (ENS160_DATA_STATUS_NEWDAT == (ENS160_DATA_STATUS_NEWDAT & (x)))
+#define IS_NEWGPR(x) (ENS160_DATA_STATUS_NEWGPR == (ENS160_DATA_STATUS_NEWGPR & (x)))
+#define IS_NEW_DATA_AVAILABLE(x) (0 != ((ENS160_DATA_STATUS_NEWDAT | ENS160_DATA_STATUS_NEWGPR ) & (x)))
+
+#define CONVERT_RS_RAW2OHMS_I(x) (1 << ((x) >> 11))
+#define CONVERT_RS_RAW2OHMS_F(x) (pow (2, (float)(x) / 2048))
+
+class ScioSense_ENS160 {
+
+ public:
+ ScioSense_ENS160();
+
+ void setI2C(uint8_t sda, uint8_t scl); // Function to redefine I2C pins
+
+ bool begin(); // Init I2C communication, resets ENS160 and checks its PART_ID. Returns false on I2C problems or wrong PART_ID.
+ uint8_t revENS16x() { return this->_revENS16x; } // Report version of sensor (0: ENS160, 1: ENS161)
+ bool setMode(uint8_t mode); // Set operation mode of sensor
+
+ bool initCustomMode(uint16_t stepNum); // Initialize definition of custom mode with <n> steps
+ bool addCustomStep(uint16_t time, bool measureHP0, bool measureHP1, bool measureHP2, bool measureHP3, uint16_t tempHP0, uint16_t tempHP1, uint16_t tempHP2, uint16_t tempHP3);
+ // Add a step to custom measurement profile with definition of duration, enabled data acquisition and temperature for each hotplate
+
+ bool measure(bool waitForNew = true); // Perform measurement and stores result in internal variables
+ bool measureRaw(bool waitForNew = true); // Perform raw measurement and stores result in internal variables
+ bool set_envdata(float t, float h); // Writes t (degC) and h (%rh) to ENV_DATA. Returns "0" if I2C transmission is successful
+ bool set_envdata210(uint16_t t, uint16_t h); // Writes t and h (in ENS210 format) to ENV_DATA. Returns "0" if I2C transmission is successful
+ uint8_t getMajorRev() { return this->_fw_ver_major; } // Get major revision number of used firmware
+ uint8_t getMinorRev() { return this->_fw_ver_minor; } // Get minor revision number of used firmware
+ uint8_t getBuild() { return this->_fw_ver_build; } // Get build revision number of used firmware
+
+ uint8_t getAQI() { return this->_data_aqi; } // Get AQI value of last measurement
+ uint16_t getTVOC() { return this->_data_tvoc; } // Get TVOC value of last measurement
+ uint16_t geteCO2() { return this->_data_eco2; } // Get eCO2 value of last measurement
+ uint16_t getAQI500() { return this->_data_aqi500; } // Get AQI500 value of last measurement
+ uint32_t getHP0() { return this->_hp0_rs; } // Get resistance of HP0 of last measurement
+ uint32_t getHP1() { return this->_hp1_rs; } // Get resistance of HP1 of last measurement
+ uint32_t getHP2() { return this->_hp2_rs; } // Get resistance of HP2 of last measurement
+ uint32_t getHP3() { return this->_hp3_rs; } // Get resistance of HP3 of last measurement
+ uint32_t getHP0BL() { return this->_hp0_bl; } // Get baseline resistance of HP0 of last measurement
+ uint32_t getHP1BL() { return this->_hp1_bl; } // Get baseline resistance of HP1 of last measurement
+ uint32_t getHP2BL() { return this->_hp2_bl; } // Get baseline resistance of HP2 of last measurement
+ uint32_t getHP3BL() { return this->_hp3_bl; } // Get baseline resistance of HP3 of last measurement
+ uint8_t getMISR() { return this->_misr; } // Return status code of sensor
+
+ private:
+ I2cDevice i2cDevice;
+ bool reset(); // Sends a reset to the ENS160. Returns false on I2C problems.
+ bool checkPartID(); // Reads the part ID and confirms valid sensor
+ bool clearCommand(); // Initialize idle mode and confirms
+ bool getFirmware(); // Read firmware revisions
+
+ uint8_t _revENS16x; // ENS160 or ENS161 connected? (FW >7)
+
+ uint8_t _fw_ver_major;
+ uint8_t _fw_ver_minor;
+ uint8_t _fw_ver_build;
+
+ uint16_t _stepCount; // Counter for custom sequence
+
+ uint8_t _data_aqi;
+ uint16_t _data_tvoc;
+ uint16_t _data_eco2;
+ uint16_t _data_aqi500;
+ uint32_t _hp0_rs;
+ uint32_t _hp0_bl;
+ uint32_t _hp1_rs;
+ uint32_t _hp1_bl;
+ uint32_t _hp2_rs;
+ uint32_t _hp2_bl;
+ uint32_t _hp3_rs;
+ uint32_t _hp3_bl;
+ uint16_t _temp;
+ int _slaveaddr; // Slave address of the ENS160
+ uint8_t _misr;
+
+ uint8_t _seq_steps[1][8];
+
+ bool write8(byte reg, byte value);
+ bool read8 (byte reg, byte *value);
+ bool read16 (byte reg, uint16_t *value);
+ bool read16LE (byte reg, uint16_t *value);
+ bool readBytes (byte reg, uint8_t *bytes, uint8_t len);
+};
+
+
+#endif
+++ /dev/null
-// https://github.com/adafruit/Adafruit_Sensor
-
-// #include "Adafruit_Sensor.h"
-#include "sensor.h"
-
-/**************************************************************************/
-/*!
- @brief Prints sensor information to serial console
-*/
-/**************************************************************************/
-void Adafruit_Sensor::printSensorDetails(void) {
-// sensor_t sensor;
-// getSensor(&sensor);
-// Serial.println(F("------------------------------------"));
-// Serial.print(F("Sensor: "));
-// Serial.println(sensor.name);
-// Serial.print(F("Type: "));
-// switch ((sensors_type_t)sensor.type) {
-// case SENSOR_TYPE_ACCELEROMETER:
-// Serial.print(F("Acceleration (m/s2)"));
-// break;
-// case SENSOR_TYPE_MAGNETIC_FIELD:
-// Serial.print(F("Magnetic (uT)"));
-// break;
-// case SENSOR_TYPE_ORIENTATION:
-// Serial.print(F("Orientation (degrees)"));
-// break;
-// case SENSOR_TYPE_GYROSCOPE:
-// Serial.print(F("Gyroscopic (rad/s)"));
-// break;
-// case SENSOR_TYPE_LIGHT:
-// Serial.print(F("Light (lux)"));
-// break;
-// case SENSOR_TYPE_PRESSURE:
-// Serial.print(F("Pressure (hPa)"));
-// break;
-// case SENSOR_TYPE_PROXIMITY:
-// Serial.print(F("Distance (cm)"));
-// break;
-// case SENSOR_TYPE_GRAVITY:
-// Serial.print(F("Gravity (m/s2)"));
-// break;
-// case SENSOR_TYPE_LINEAR_ACCELERATION:
-// Serial.print(F("Linear Acceleration (m/s2)"));
-// break;
-// case SENSOR_TYPE_ROTATION_VECTOR:
-// Serial.print(F("Rotation vector"));
-// break;
-// case SENSOR_TYPE_RELATIVE_HUMIDITY:
-// Serial.print(F("Relative Humidity (%)"));
-// break;
-// case SENSOR_TYPE_AMBIENT_TEMPERATURE:
-// Serial.print(F("Ambient Temp (C)"));
-// break;
-// case SENSOR_TYPE_OBJECT_TEMPERATURE:
-// Serial.print(F("Object Temp (C)"));
-// break;
-// case SENSOR_TYPE_VOLTAGE:
-// Serial.print(F("Voltage (V)"));
-// break;
-// case SENSOR_TYPE_CURRENT:
-// Serial.print(F("Current (mA)"));
-// break;
-// case SENSOR_TYPE_COLOR:
-// Serial.print(F("Color (RGBA)"));
-// break;
-// case SENSOR_TYPE_TVOC:
-// Serial.print(F("Total Volatile Organic Compounds (ppb)"));
-// break;
-// case SENSOR_TYPE_VOC_INDEX:
-// Serial.print(F("Volatile Organic Compounds (Index)"));
-// break;
-// case SENSOR_TYPE_NOX_INDEX:
-// Serial.print(F("Nitrogen Oxides (Index)"));
-// break;
-// case SENSOR_TYPE_CO2:
-// Serial.print(F("Carbon Dioxide (ppm)"));
-// break;
-// case SENSOR_TYPE_ECO2:
-// Serial.print(F("Equivalent/estimated CO2 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM10_STD:
-// Serial.print(F("Standard Particulate Matter 1.0 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM25_STD:
-// Serial.print(F("Standard Particulate Matter 2.5 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM100_STD:
-// Serial.print(F("Standard Particulate Matter 10.0 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM10_ENV:
-// Serial.print(F("Environmental Particulate Matter 1.0 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM25_ENV:
-// Serial.print(F("Environmental Particulate Matter 2.5 (ppm)"));
-// break;
-// case SENSOR_TYPE_PM100_ENV:
-// Serial.print(F("Environmental Particulate Matter 10.0 (ppm)"));
-// break;
-// case SENSOR_TYPE_GAS_RESISTANCE:
-// Serial.print(F("Gas Resistance (ohms)"));
-// break;
-// case SENSOR_TYPE_UNITLESS_PERCENT:
-// Serial.print(F("Unitless Percent (%)"));
-// break;
-// case SENSOR_TYPE_ALTITUDE:
-// Serial.print(F("Altitude (m)"));
-// break;
-// }
-
-// Serial.println();
-// Serial.print(F("Driver Ver: "));
-// Serial.println(sensor.version);
-// Serial.print(F("Unique ID: "));
-// Serial.println(sensor.sensor_id);
-// Serial.print(F("Min Value: "));
-// Serial.println(sensor.min_value);
-// Serial.print(F("Max Value: "));
-// Serial.println(sensor.max_value);
-// Serial.print(F("Resolution: "));
-// Serial.println(sensor.resolution);
-// Serial.println(F("------------------------------------\n"));
-}
-// https://github.com/adafruit/Adafruit_Sensor
-
/*
* Copyright (C) 2008 The Android Open Source Project
*
public:
// Constructor(s)
Adafruit_Sensor() {}
+// virtual ~Adafruit_Sensor() {}
- // These must be defined by the subclass
+// // These must be defined by the subclass
- /*! @brief Whether we should automatically change the range (if possible) for
- higher precision
- @param enabled True if we will try to autorange */
- virtual void enableAutoRange(bool enabled) {
- (void)enabled; /* suppress unused warning */
- };
+// /*! @brief Whether we should automatically change the range (if possible) for
+// higher precision
+// @param enabled True if we will try to autorange */
+// virtual void enableAutoRange(bool enabled) {
+// (void)enabled; /* suppress unused warning */
+// };
- /*! @brief Get the latest sensor event
- @returns True if able to fetch an event */
- virtual bool getEvent(sensors_event_t *) = 0;
- /*! @brief Get info about the sensor itself */
- virtual void getSensor(sensor_t *) = 0;
+// /*! @brief Get the latest sensor event
+// @returns True if able to fetch an event */
+// virtual bool getEvent(sensors_event_t *) = 0;
+// /*! @brief Get info about the sensor itself */
+// virtual void getSensor(sensor_t *) = 0;
- void printSensorDetails(void);
+// void printSensorDetails(void);
};
#endif
--- /dev/null
+#include <avr/io.h>
+#include <stdio.h>
+
+#include "i2cdevice.hpp"
+
+I2cDevice i2cDevice;
+
+I2cDevice::I2cDevice () {
+ address = 0;
+}
+
+bool I2cDevice::begin (uint8_t addr) {
+ this->address = addr;
+ // TWBR = 13; // 100kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 100000) / (2 * 100000 * 4);
+ TWBR = 100; // 50kHz (TWPS1:0 = 00), TWBR = (F_CPU - 16 * 50000) / (2 * 50000 * 4);
+ TWCR = (1 << TWEN);
+ return true;
+}
+
+void I2cDevice::end () {
+ TWCR = (1 << TWEN);
+ TWBR = 0;
+}
+
+bool I2cDevice::write (const uint8_t *buffer, uint8_t len) {
+ if (start(false)) {
+ if (writeBytes(buffer, len)) {
+ if (stop()) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+bool I2cDevice::write_then_read (const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len) {
+ if (start(false)) {
+ if (writeBytes(write_buffer, write_len)) {
+ if (start(true)) {
+ if (readBytes(read_buffer, read_len)) {
+ if (stop()) {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
+bool I2cDevice::readBytes (uint8_t *buffer, uint8_t len) {
+ while (len-- > 0) {
+ if (len > 0) {
+ TWCR = (1 << TWEA) | (1 << TWINT) | (1 << TWEN); // read data byte with ACK enabled
+ } else {
+ TWCR = (1 << TWINT) | (1 << TWEN); // read data byte with ACK disabled
+ }
+ while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+ uint8_t sr = TWSR & 0xf8;
+ if ((len > 0 && sr != 0x50) || (len == 0 && sr != 0x58)) {
+ return false;
+ }
+ *buffer++ = TWDR;
+ }
+ return true;
+}
+
+bool I2cDevice::writeBytes (const uint8_t *buffer, uint8_t len) {
+ while (len-- > 0) {
+ // printf("[wB:len=%d, byte=%02x]", len + 1, *buffer);
+ TWDR = *buffer++;
+ TWCR = (1 << TWINT) | (1 << TWEN); // send data byte
+ while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+ //printf("TWSR=%02x", TWSR);
+ if ((TWSR & 0xf8) != 0x28) {
+ return false;
+ }
+ }
+ return true;
+}
+
+bool I2cDevice::writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len) {
+ do {
+ TWDR = byte;
+ TWCR = (1 << TWINT) | (1 << TWEN); // send byte
+ while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+ if ((TWSR & 0xf8) != 0x28) {
+ return false;
+ }
+ byte = *buffer++;
+ } while (len-- > 0);
+ return true;
+}
+
+bool I2cDevice::start (bool read) {
+ TWCR = (1 << TWINT) | (1 << TWSTA) | (1 << TWEN); // send START condition
+ while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+ uint8_t sr = TWSR & 0xf8;
+ if (sr != 0x08 && sr != 0x10) {
+ return false;
+ }
+ TWDR = (address << 1) | (read ? 1 : 0); // address + R/nW
+ TWCR = (1 << TWINT) | (1 << TWEN); // send address/RW
+ while (!(TWCR & (1 << TWINT))) {}; // wait until last action done
+ sr = TWSR & 0xf8;
+ if ((!read && sr != 0x18) || (read && sr != 0x40)) {
+ return false;
+ }
+ return true;
+}
+
+bool I2cDevice::stop () {
+ TWCR = (1 << TWINT) | (1 << TWEN) | (1 << TWSTO);
+ while (TWCR & ( 1 << TWSTO));
+ return true;
+}
+
--- /dev/null
+#ifndef I2C_DEVICE
+#define I2C_DEVICE
+
+#include <stdint.h>
+
+class I2cDevice {
+ public:
+ static void end ();
+
+ public:
+ I2cDevice ();
+ bool begin (uint8_t addr);
+ bool write(const uint8_t *buffer, uint8_t len);
+ bool write_then_read(const uint8_t *write_buffer, uint8_t write_len, uint8_t *read_buffer, uint8_t read_len);
+ bool writeByteAndBuffer (uint8_t byte, const uint8_t *buffer, uint8_t len);
+
+ private:
+ uint8_t address;
+ bool start (bool read);
+ bool stop ();
+ bool writeBytes (const uint8_t *buffer, uint8_t len);
+ bool readBytes (uint8_t *buffer, uint8_t len);
+};
+
+extern I2cDevice i2cDevice;
+
+#endif
\ No newline at end of file
void __cxa_pure_virtual () {
}
+ int __cxa_guard_acquire(uint8_t *g) {
+ return 0;
+ }
+
+ void __cxa_guard_release(uint8_t *g) {}
+
+ void __cxa_guard_abort(uint8_t *g) {}
+
+
int uart_putchar(char c, FILE *stream) {
if (c == '\n') {
uart_putchar('\r', stream);
#define CTRLC '\003'
extern int wait (uint32_t ms);
-extern int waitOnKey (char key);
extern uint64_t millis ();
class TestUnit {
#include <util/delay.h>
#include "i2c.hpp"
+#include "../i2cdevice.hpp"
#include "../main.hpp"
printf("init");
} else if (subtest == 1 && mode == SparkFunEnvCombo) {
+ printf(" BM280 ... ");
+ if (!bm280.begin()) {
+ printf("ERROR");
+ return -1;
+ }
+ printf("OK, ENS160 ... ");
+ if (!ens160.begin()) {
+ printf("ERROR");
+ return -1;
+ }
+ printf("OK");
+
+ do {
+ float p = bm280.readPressure();
+ printf("\n => pressure: %.3fhPa", (double)p);
+ float t = bm280.readTemperature();
+ printf(", temp: %.2f°C", (double)t);
+ float h = bm280.readHumidity();
+ printf(", humidity: %.2f%%", (double)h);
+ } while (wait(1000) == EOF);
+
+ } else if (subtest == 1) {
int key = EOF;
uint8_t buffer[18];
int errorCode;
errorCode = errorCode != 0 ? 0x3000 | errorCode : 0;
}
if (errorCode == 0) {
- bm280.digT[0] = ((uint16_t)buffer[1] << 8) | buffer[0];
- bm280.digT[1] = ((uint16_t)buffer[3] << 8) | buffer[2];
- bm280.digT[2] = ((uint16_t)buffer[5] << 8) | buffer[4];
- printf(" T(%04x %04x %04x)", bm280.digT[0], bm280.digT[1], bm280.digT[2]);
+ // bm280.digT[0] = ((uint16_t)buffer[1] << 8) | buffer[0];
+ // bm280.digT[1] = ((uint16_t)buffer[3] << 8) | buffer[2];
+ // bm280.digT[2] = ((uint16_t)buffer[5] << 8) | buffer[4];
+ // printf(" T(%04x %04x %04x)", bm280.digT[0], bm280.digT[1], bm280.digT[2]);
} else {
stop();
printf("ERROR(%04x)", errorCode);
} while (wait(5000) == EOF);
} else {
+ I2cDevice::end();
printf("end");
return -1;
}
}
int32_t I2c::compensateBm280T (int32_t adcT) {
- int32_t var1, var2, t;
- var1 = ((((adcT >> 3) - ((int32_t)bm280.digT[0] << 1))) * ((int32_t)bm280.digT[1])) >> 11;
- var2 = (((((adcT >> 4) - ((int32_t)bm280.digT[0])) * ((adcT >> 4) - ((int32_t)bm280.digT[0]))) >> 12) * ((int32_t)bm280.digT[2])) >> 14;
- bm280.tFine = var1 + var2;
- t = (bm280.tFine * 5 + 128) >> 8;
- return t;
+ // int32_t var1, var2, t;
+ // var1 = ((((adcT >> 3) - ((int32_t)bm280.digT[0] << 1))) * ((int32_t)bm280.digT[1])) >> 11;
+ // var2 = (((((adcT >> 4) - ((int32_t)bm280.digT[0])) * ((adcT >> 4) - ((int32_t)bm280.digT[0]))) >> 12) * ((int32_t)bm280.digT[2])) >> 14;
+ // bm280.tFine = var1 + var2;
+ // t = (bm280.tFine * 5 + 128) >> 8;
+ // return t;
+ return -1;
}
\ No newline at end of file
#include <stdint.h>
#include "../main.hpp"
+#include "../adafruit/bme280.h"
+#include "../adafruit/ens160.h"
typedef enum I2cMode { SparkFunEnvCombo, Master, Slave } I2cMode;
-typedef struct {
- int32_t tFine;
- uint16_t digT[3];
-} I2cBm280;
class I2c : public TestUnit {
private:
I2cMode mode;
- I2cBm280 bm280;
+ Adafruit_BME280 bm280;
+ ScioSense_ENS160 ens160;
public:
bool enabled;