Commit a655f2090f5cf8b7332f5c4db30a78a77b79f0e8
receivedThu, 1. Aug 2024, 19:16:53 (by user sx)
Thu, 1 Aug 2024 17:16:53 +0000 (19:16 +0200)
authorManfred Steiner <sx@htl-kaindorf.at>
Thu, 1 Aug 2024 17:16:46 +0000 (19:16 +0200)
committerManfred Steiner <sx@htl-kaindorf.at>
Thu, 1 Aug 2024 17:16:46 +0000 (19:16 +0200)
14 files changed:
software/test_2024-07-23/src/adafruit/arduino.cpp [deleted file]
software/test_2024-07-23/src/adafruit/arduino.h [deleted file]
software/test_2024-07-23/src/adafruit/bme280.cpp
software/test_2024-07-23/src/adafruit/bme280.h
software/test_2024-07-23/src/adafruit/ens160.cpp [new file with mode: 0644]
software/test_2024-07-23/src/adafruit/ens160.h [new file with mode: 0644]
software/test_2024-07-23/src/adafruit/sensor.cpp [deleted file]
software/test_2024-07-23/src/adafruit/sensor.h
software/test_2024-07-23/src/i2cdevice.cpp [new file with mode: 0644]
software/test_2024-07-23/src/i2cdevice.hpp [new file with mode: 0644]
software/test_2024-07-23/src/main.cpp
software/test_2024-07-23/src/main.hpp
software/test_2024-07-23/src/units/i2c.cpp
software/test_2024-07-23/src/units/i2c.hpp

diff --git a/software/test_2024-07-23/src/adafruit/arduino.cpp b/software/test_2024-07-23/src/adafruit/arduino.cpp
deleted file mode 100644 (file)
index 055b842..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#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;
-}
diff --git a/software/test_2024-07-23/src/adafruit/arduino.h b/software/test_2024-07-23/src/adafruit/arduino.h
deleted file mode 100644 (file)
index 8ec8334..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-#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
index 049e9a6bad5c68aefeac515343e7cb706d68b316..6ff5bc8394edb10bb98486f42e20e886064105cc 100644 (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;
 }
 
 /*!
@@ -119,11 +56,11 @@ bool Adafruit_BME280::init() {
  *   @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;
@@ -154,8 +91,8 @@ void Adafruit_BME280::write8(byte reg, byte value) {
   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);
   }
 }
 
@@ -167,8 +104,8 @@ void Adafruit_BME280::write8(byte reg, byte value) {
 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];
 }
@@ -182,8 +119,8 @@ uint16_t Adafruit_BME280::read16(byte reg) {
   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]);
 }
@@ -223,16 +160,16 @@ uint32_t Adafruit_BME280::read24(byte reg) {
   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;
@@ -241,21 +178,21 @@ bool Adafruit_BME280::takeForcedMeasurement(void) {
   // 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;
 }
@@ -282,9 +219,9 @@ void Adafruit_BME280::readCoefficients(void) {
   _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);
 }
 
@@ -307,7 +244,7 @@ float Adafruit_BME280::readTemperature(void) {
 
   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));
@@ -333,7 +270,7 @@ float Adafruit_BME280::readPressure(void) {
 
   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;
@@ -341,18 +278,18 @@ float Adafruit_BME280::readPressure(void) {
   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);
 
@@ -372,7 +309,7 @@ float Adafruit_BME280::readHumidity(void) {
 
   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);
@@ -456,7 +393,7 @@ void Adafruit_BME280::setTemperatureCompensation(float adjustment) {
 
 /**************************************************************************/
 /*!
-    @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) {
@@ -477,9 +414,9 @@ 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) {
@@ -496,7 +433,7 @@ 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) {
@@ -517,9 +454,9 @@ 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) {
@@ -536,7 +473,7 @@ 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) {
@@ -557,9 +494,9 @@ 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) {
index dd59f79197b76d464023dec09adc5f89b6ed8778..94c3927a6449957c138befce9b08576a14c5ea95 100644 (file)
 // #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"
 
 /*!
@@ -241,8 +246,8 @@ public:
   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;
diff --git a/software/test_2024-07-23/src/adafruit/ens160.cpp b/software/test_2024-07-23/src/adafruit/ens160.cpp
new file mode 100644 (file)
index 0000000..85b98fa
--- /dev/null
@@ -0,0 +1,365 @@
+/*
+  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;
+}
diff --git a/software/test_2024-07-23/src/adafruit/ens160.h b/software/test_2024-07-23/src/adafruit/ens160.h
new file mode 100644 (file)
index 0000000..e3ecdcf
--- /dev/null
@@ -0,0 +1,180 @@
+/*
+  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
diff --git a/software/test_2024-07-23/src/adafruit/sensor.cpp b/software/test_2024-07-23/src/adafruit/sensor.cpp
deleted file mode 100644 (file)
index c180fd1..0000000
+++ /dev/null
@@ -1,123 +0,0 @@
-// 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"));
-}
index 72cf98110dee0d544aa69abbdaeebb6a46bc946a..ac7e4545f23ef33f4d848ad903ae717214718cec 100644 (file)
@@ -1,5 +1,3 @@
-// https://github.com/adafruit/Adafruit_Sensor
-
 /*
  * Copyright (C) 2008 The Android Open Source Project
  *
@@ -203,23 +201,24 @@ class Adafruit_Sensor {
 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
diff --git a/software/test_2024-07-23/src/i2cdevice.cpp b/software/test_2024-07-23/src/i2cdevice.cpp
new file mode 100644 (file)
index 0000000..47be4af
--- /dev/null
@@ -0,0 +1,117 @@
+#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;
+}
+
diff --git a/software/test_2024-07-23/src/i2cdevice.hpp b/software/test_2024-07-23/src/i2cdevice.hpp
new file mode 100644 (file)
index 0000000..e59d737
--- /dev/null
@@ -0,0 +1,27 @@
+#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
index 1079eb00cf852b4077524951348b83e2df397263..d64b6e0601473f4c066ed7ec3450294f06721528 100644 (file)
@@ -25,6 +25,15 @@ extern "C" {
    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);
index 4490ff39a75193bf12db6ff6cda761522b8d3d42..de2c1e141fe3a89c935b7539a96ff268c65e468e 100644 (file)
@@ -7,7 +7,6 @@
 #define CTRLC '\003'
 
 extern int wait (uint32_t ms);
-extern int waitOnKey (char key);
 extern uint64_t millis ();
 
 class TestUnit {
index 9858aa1244f6e136a317c5e89790e53fda5a7932..df1fe75aad807e9d7830a1755d201b2b2ee54ffd 100644 (file)
@@ -3,6 +3,7 @@
 #include <util/delay.h>
 
 #include "i2c.hpp"
+#include "../i2cdevice.hpp"
 #include "../main.hpp"
 
 
@@ -37,6 +38,28 @@ int8_t I2c::run (uint8_t subtest) {
       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;
@@ -92,10 +115,10 @@ int8_t I2c::run (uint8_t subtest) {
             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);
@@ -169,6 +192,7 @@ int8_t I2c::run (uint8_t subtest) {
       } while (wait(5000) == EOF);
 
    } else {
+      I2cDevice::end();
       printf("end");
       return -1;
    }
@@ -255,10 +279,11 @@ uint16_t I2c::readData (uint8_t size, uint8_t *data) {
 }
 
 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
index 96a3f233822df52cf77647118bb21bb52c754ead..6e4a5334ff261594d9398c4d413c7b74bceec578 100644 (file)
@@ -3,18 +3,17 @@
 
 #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;