diff --git a/BottomGrowControl-Körper.3mf b/BottomGrowControl-Körper.3mf index a6363bb..af39d5b 100644 Binary files a/BottomGrowControl-Körper.3mf and b/BottomGrowControl-Körper.3mf differ diff --git a/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp b/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp new file mode 100644 index 0000000..4c82e05 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/Adafruit_BME280.cpp @@ -0,0 +1,646 @@ +/*! + * @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" + +/*! + * @brief class constructor + */ +Adafruit_BME280::Adafruit_BME280() {} + +/*! + * @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 class constructor if using software SPI + * @param cspin the chip select pin to use + * @param mosipin the MOSI pin to use + * @param misopin the MISO pin to use + * @param sckpin the SCK pin to use + */ +Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, + int8_t sckpin) { + spi_dev = new Adafruit_SPIDevice(cspin, sckpin, misopin, mosipin); +} + +Adafruit_BME280::~Adafruit_BME280(void) { + if (spi_dev) { + delete spi_dev; + } + if (i2c_dev) { + delete i2c_dev; + } + if (temp_sensor) { + delete temp_sensor; + } + if (pressure_sensor) { + delete pressure_sensor; + } + if (humidity_sensor) { + delete humidity_sensor; + } +} + +/*! + * @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, TwoWire *theWire) { + if (spi_dev == NULL) { + // I2C mode + if (i2c_dev) + delete i2c_dev; + i2c_dev = new Adafruit_I2CDevice(addr, theWire); + if (!i2c_dev->begin()) + return false; + } else { + // SPI mode + if (!spi_dev->begin()) + 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(10); + + // if chip is still reading calibration, delay + while (isReadingCalibration()) + delay(10); + + readCoefficients(); // read trimming parameters, see DS 4.2.2 + + setSampling(); // use defaults + + delay(100); + + return true; +} + +/*! + * @brief setup sensor with given parameters / settings + * + * This is simply a overload to the normal begin()-function, so SPI users + * don't get confused about the library requiring an address. + * @param mode the power mode to use for the sensor + * @param tempSampling the temp samping rate to use + * @param pressSampling the pressure sampling rate to use + * @param humSampling the humidity sampling rate to use + * @param filter the filter mode to use + * @param duration the standby duration to use + */ +void Adafruit_BME280::setSampling(sensor_mode mode, + 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; + + _humReg.osrs_h = humSampling; + _configReg.filter = filter; + _configReg.t_sb = duration; + _configReg.spi3w_en = 0; + + // making sure sensor is in sleep mode before setting configuration + // as it otherwise may be ignored + write8(BME280_REGISTER_CONTROL, MODE_SLEEP); + + // you must make sure to also set REGISTER_CONTROL after setting the + // CONTROLHUMID register, otherwise the values won't be applied (see + // DS 5.4.3) + write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); + write8(BME280_REGISTER_CONFIG, _configReg.get()); + write8(BME280_REGISTER_CONTROL, _measReg.get()); +} + +/*! + * @brief Writes an 8 bit value over I2C or SPI + * @param reg the register address to write to + * @param value the value to write to the register + */ +void Adafruit_BME280::write8(byte reg, byte value) { + byte buffer[2]; + buffer[1] = value; + if (i2c_dev) { + buffer[0] = reg; + i2c_dev->write(buffer, 2); + } else { + buffer[0] = reg & ~0x80; + spi_dev->write(buffer, 2); + } +} + +/*! + * @brief Reads an 8 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the data byte read from the device + */ +uint8_t Adafruit_BME280::read8(byte reg) { + uint8_t buffer[1]; + if (i2c_dev) { + buffer[0] = uint8_t(reg); + i2c_dev->write_then_read(buffer, 1, buffer, 1); + } else { + buffer[0] = uint8_t(reg | 0x80); + spi_dev->write_then_read(buffer, 1, buffer, 1); + } + return buffer[0]; +} + +/*! + * @brief Reads a 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +uint16_t Adafruit_BME280::read16(byte reg) { + uint8_t buffer[2]; + + if (i2c_dev) { + buffer[0] = uint8_t(reg); + i2c_dev->write_then_read(buffer, 1, buffer, 2); + } else { + buffer[0] = uint8_t(reg | 0x80); + spi_dev->write_then_read(buffer, 1, buffer, 2); + } + return uint16_t(buffer[0]) << 8 | uint16_t(buffer[1]); +} + +/*! + * @brief Reads a signed 16 bit little endian value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +uint16_t Adafruit_BME280::read16_LE(byte reg) { + uint16_t temp = read16(reg); + return (temp >> 8) | (temp << 8); +} + +/*! + * @brief Reads a signed 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); } + +/*! + * @brief Reads a signed little endian 16 bit value over I2C or SPI + * @param reg the register address to read from + * @returns the 16 bit data value read from the device + */ +int16_t Adafruit_BME280::readS16_LE(byte reg) { + return (int16_t)read16_LE(reg); +} + +/*! + * @brief Reads a 24 bit value over I2C + * @param reg the register address to read from + * @returns the 24 bit data value read from the device + */ +uint32_t Adafruit_BME280::read24(byte reg) { + uint8_t buffer[3]; + + if (i2c_dev) { + buffer[0] = uint8_t(reg); + i2c_dev->write_then_read(buffer, 1, buffer, 3); + } else { + buffer[0] = uint8_t(reg | 0x80); + spi_dev->write_then_read(buffer, 1, buffer, 3); + } + + return uint32_t(buffer[0]) << 16 | uint32_t(buffer[1]) << 8 | + uint32_t(buffer[2]); +} + +/*! + * @brief Take a new measurement (only possible in forced mode) + @returns true in case of success else false + */ +bool Adafruit_BME280::takeForcedMeasurement(void) { + bool return_value = false; + // If we are in forced mode, the BME sensor goes back to sleep after each + // measurement and we need to set it to forced mode once at this point, so + // 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(1); + } + } + return return_value; +} + +/*! + * @brief Reads the factory-set coefficients + */ +void Adafruit_BME280::readCoefficients(void) { + _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); + _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); + _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); + + _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); + _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); + _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); + _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); + _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); + _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); + _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); + _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); + _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); + + _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); + _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); + _bme280_calib.dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) | + (read8(BME280_REGISTER_DIG_H5) >> 4); + _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); +} + +/*! + * @brief return true if chip is busy reading cal data + * @returns true if reading calibration, false otherwise + */ +bool Adafruit_BME280::isReadingCalibration(void) { + uint8_t const rStatus = read8(BME280_REGISTER_STATUS); + + return (rStatus & (1 << 0)) != 0; +} + +/*! + * @brief Returns the temperature from the sensor + * @returns the temperature read from the device + */ +float Adafruit_BME280::readTemperature(void) { + int32_t var1, var2; + + int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); + if (adc_T == 0x800000) // value in case temp measurement was disabled + return NAN; + adc_T >>= 4; + + var1 = (int32_t)((adc_T / 8) - ((int32_t)_bme280_calib.dig_T1 * 2)); + var1 = (var1 * ((int32_t)_bme280_calib.dig_T2)) / 2048; + var2 = (int32_t)((adc_T / 16) - ((int32_t)_bme280_calib.dig_T1)); + var2 = (((var2 * var2) / 4096) * ((int32_t)_bme280_calib.dig_T3)) / 16384; + + t_fine = var1 + var2 + t_fine_adjust; + + int32_t T = (t_fine * 5 + 128) / 256; + + return (float)T / 100; +} + +/*! + * @brief Returns the pressure from the sensor + * @returns the pressure value (in Pascal) read from the device + */ +float Adafruit_BME280::readPressure(void) { + int64_t var1, var2, var3, var4; + + readTemperature(); // must be done first to get t_fine + + int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); + if (adc_P == 0x800000) // value in case pressure measurement was disabled + return NAN; + adc_P >>= 4; + + var1 = ((int64_t)t_fine) - 128000; + var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; + 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)); + 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 + } + + var4 = 1048576 - adc_P; + var4 = (((var4 * 2147483648) - var2) * 3125) / var1; + var1 = (((int64_t)_bme280_calib.dig_P9) * (var4 / 8192) * (var4 / 8192)) / + 33554432; + var2 = (((int64_t)_bme280_calib.dig_P8) * var4) / 524288; + var4 = ((var4 + var1 + var2) / 256) + (((int64_t)_bme280_calib.dig_P7) * 16); + + float P = var4 / 256.0; + + return P; +} + +/*! + * @brief Returns the humidity from the sensor + * @returns the humidity value read from the device + */ +float Adafruit_BME280::readHumidity(void) { + int32_t var1, var2, var3, var4, var5; + + readTemperature(); // must be done first to get t_fine + + int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); + if (adc_H == 0x8000) // value in case humidity measurement was disabled + return NAN; + + var1 = t_fine - ((int32_t)76800); + var2 = (int32_t)(adc_H * 16384); + var3 = (int32_t)(((int32_t)_bme280_calib.dig_H4) * 1048576); + var4 = ((int32_t)_bme280_calib.dig_H5) * var1; + var5 = (((var2 - var3) - var4) + (int32_t)16384) / 32768; + var2 = (var1 * ((int32_t)_bme280_calib.dig_H6)) / 1024; + var3 = (var1 * ((int32_t)_bme280_calib.dig_H3)) / 2048; + var4 = ((var2 * (var3 + (int32_t)32768)) / 1024) + (int32_t)2097152; + var2 = ((var4 * ((int32_t)_bme280_calib.dig_H2)) + 8192) / 16384; + var3 = var5 * var2; + var4 = ((var3 / 32768) * (var3 / 32768)) / 128; + var5 = var3 - ((var4 * ((int32_t)_bme280_calib.dig_H1)) / 16); + var5 = (var5 < 0 ? 0 : var5); + var5 = (var5 > 419430400 ? 419430400 : var5); + uint32_t H = (uint32_t)(var5 / 4096); + + return (float)H / 1024.0; +} + +/*! + * Calculates the altitude (in meters) from the specified atmospheric + * pressure (in hPa), and sea-level pressure (in hPa). + * @param seaLevel Sea-level pressure in hPa + * @returns the altitude value read from the device + */ +float Adafruit_BME280::readAltitude(float seaLevel) { + // Equation taken from BMP180 datasheet (page 16): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + float atmospheric = readPressure() / 100.0F; + return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); +} + +/*! + * Calculates the pressure at sea level (in hPa) from the specified + * altitude (in meters), and atmospheric pressure (in hPa). + * @param altitude Altitude in meters + * @param atmospheric Atmospheric pressure in hPa + * @returns the pressure at sea level (in hPa) from the specified altitude + */ +float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) { + // Equation taken from BMP180 datasheet (page 17): + // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf + + // Note that using the equation from wikipedia can give bad results + // at high altitude. See this thread for more information: + // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 + + return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255); +} + +/*! + * Returns Sensor ID found by init() for diagnostics + * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 + */ +uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; } + +/*! + * Returns the current temperature compensation value in degrees Celsius + * @returns the current temperature compensation value in degrees Celsius + */ +float Adafruit_BME280::getTemperatureCompensation(void) { + return float((t_fine_adjust * 5) >> 8) / 100.0; +}; + +/*! + * Sets a value to be added to each temperature reading. This adjusted + * temperature is used in pressure and humidity readings. + * @param adjustment Value to be added to each temperature reading in Celsius + */ +void Adafruit_BME280::setTemperatureCompensation(float adjustment) { + // convert the value in C into and adjustment to t_fine + t_fine_adjust = ((int32_t(adjustment * 100) << 8)) / 5; +}; + +/*! + @brief Gets an Adafruit Unified Sensor object for the temp sensor component + @return Adafruit_Sensor pointer to temperature sensor + */ +Adafruit_Sensor *Adafruit_BME280::getTemperatureSensor(void) { + if (!temp_sensor) { + temp_sensor = new Adafruit_BME280_Temp(this); + } + + return temp_sensor; +} + +/*! + @brief Gets an Adafruit Unified Sensor object for the pressure sensor + component + @return Adafruit_Sensor pointer to pressure sensor + */ +Adafruit_Sensor *Adafruit_BME280::getPressureSensor(void) { + if (!pressure_sensor) { + pressure_sensor = new Adafruit_BME280_Pressure(this); + } + return pressure_sensor; +} + +/*! + @brief Gets an Adafruit Unified Sensor object for the humidity sensor + component + @return Adafruit_Sensor pointer to humidity sensor + */ +Adafruit_Sensor *Adafruit_BME280::getHumiditySensor(void) { + if (!humidity_sensor) { + humidity_sensor = new Adafruit_BME280_Humidity(this); + } + return humidity_sensor; +} + +/**************************************************************************/ +/*! + @brief Gets the sensor_t data for the BME280's temperature sensor +*/ +/**************************************************************************/ +void Adafruit_BME280_Temp::getSensor(sensor_t *sensor) { + /* Clear the sensor_t object */ + memset(sensor, 0, sizeof(sensor_t)); + + /* Insert the sensor name in the fixed length char array */ + strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); + sensor->name[sizeof(sensor->name) - 1] = 0; + sensor->version = 1; + sensor->sensor_id = _sensorID; + sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; + sensor->min_delay = 0; + sensor->min_value = -40.0; /* Temperature range -40 ~ +85 C */ + sensor->max_value = +85.0; + sensor->resolution = 0.01; /* 0.01 C */ +} + +/**************************************************************************/ +/*! + @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) { + /* Clear the event */ + memset(event, 0, sizeof(sensors_event_t)); + + event->version = sizeof(sensors_event_t); + event->sensor_id = _sensorID; + event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; + event->timestamp = millis(); + event->temperature = _theBME280->readTemperature(); + return true; +} + +/**************************************************************************/ +/*! + @brief Gets the sensor_t data for the BME280's pressure sensor +*/ +/**************************************************************************/ +void Adafruit_BME280_Pressure::getSensor(sensor_t *sensor) { + /* Clear the sensor_t object */ + memset(sensor, 0, sizeof(sensor_t)); + + /* Insert the sensor name in the fixed length char array */ + strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); + sensor->name[sizeof(sensor->name) - 1] = 0; + sensor->version = 1; + sensor->sensor_id = _sensorID; + sensor->type = SENSOR_TYPE_PRESSURE; + sensor->min_delay = 0; + sensor->min_value = 300.0; /* 300 ~ 1100 hPa */ + sensor->max_value = 1100.0; + sensor->resolution = 0.012; /* 0.12 hPa relative */ +} + +/**************************************************************************/ +/*! + @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) { + /* Clear the event */ + memset(event, 0, sizeof(sensors_event_t)); + + event->version = sizeof(sensors_event_t); + event->sensor_id = _sensorID; + event->type = SENSOR_TYPE_PRESSURE; + event->timestamp = millis(); + event->pressure = _theBME280->readPressure() / 100; // convert Pa to hPa + return true; +} + +/**************************************************************************/ +/*! + @brief Gets the sensor_t data for the BME280's humidity sensor +*/ +/**************************************************************************/ +void Adafruit_BME280_Humidity::getSensor(sensor_t *sensor) { + /* Clear the sensor_t object */ + memset(sensor, 0, sizeof(sensor_t)); + + /* Insert the sensor name in the fixed length char array */ + strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); + sensor->name[sizeof(sensor->name) - 1] = 0; + sensor->version = 1; + sensor->sensor_id = _sensorID; + sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY; + sensor->min_delay = 0; + sensor->min_value = 0; + sensor->max_value = 100; /* 0 - 100 % */ + sensor->resolution = 3; /* 3% accuracy */ +} + +/**************************************************************************/ +/*! + @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) { + /* Clear the event */ + memset(event, 0, sizeof(sensors_event_t)); + + event->version = sizeof(sensors_event_t); + event->sensor_id = _sensorID; + event->type = SENSOR_TYPE_RELATIVE_HUMIDITY; + event->timestamp = millis(); + event->relative_humidity = _theBME280->readHumidity(); + return true; +} diff --git a/libraries/Adafruit_BME280_Library/Adafruit_BME280.h b/libraries/Adafruit_BME280_Library/Adafruit_BME280.h new file mode 100644 index 0000000..ffa8018 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/Adafruit_BME280.h @@ -0,0 +1,372 @@ +/*! + * @file Adafruit_BME280.h + * + * Designed specifically to work with the Adafruit BME280 Breakout + * ----> http://www.adafruit.com/products/2650 + * + * These sensors use I2C or SPI to communicate, 2 or 4 pins are required + * to interface. + * + * Adafruit invests time and resources providing this open source code, + * please support Adafruit and open-source hardware by purchasing + * products from Adafruit! + * + * Written by Kevin "KTOWN" Townsend for Adafruit Industries. + * + * BSD license, all text here must be included in any redistribution. + * See the LICENSE file for details. + * + */ + +#ifndef __BME280_H__ +#define __BME280_H__ + +#include "Arduino.h" + +#include +#include +#include + +/*! + * @brief default I2C address + */ +#define BME280_ADDRESS (0x77) // Primary I2C Address + /*! + * @brief alternate I2C address + */ +#define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address + +/*! + * @brief Register addresses + */ +enum { + BME280_REGISTER_DIG_T1 = 0x88, + BME280_REGISTER_DIG_T2 = 0x8A, + BME280_REGISTER_DIG_T3 = 0x8C, + + BME280_REGISTER_DIG_P1 = 0x8E, + BME280_REGISTER_DIG_P2 = 0x90, + BME280_REGISTER_DIG_P3 = 0x92, + BME280_REGISTER_DIG_P4 = 0x94, + BME280_REGISTER_DIG_P5 = 0x96, + BME280_REGISTER_DIG_P6 = 0x98, + BME280_REGISTER_DIG_P7 = 0x9A, + BME280_REGISTER_DIG_P8 = 0x9C, + BME280_REGISTER_DIG_P9 = 0x9E, + + BME280_REGISTER_DIG_H1 = 0xA1, + BME280_REGISTER_DIG_H2 = 0xE1, + BME280_REGISTER_DIG_H3 = 0xE3, + BME280_REGISTER_DIG_H4 = 0xE4, + BME280_REGISTER_DIG_H5 = 0xE5, + BME280_REGISTER_DIG_H6 = 0xE7, + + BME280_REGISTER_CHIPID = 0xD0, + BME280_REGISTER_VERSION = 0xD1, + BME280_REGISTER_SOFTRESET = 0xE0, + + BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 + + BME280_REGISTER_CONTROLHUMID = 0xF2, + BME280_REGISTER_STATUS = 0XF3, + BME280_REGISTER_CONTROL = 0xF4, + BME280_REGISTER_CONFIG = 0xF5, + BME280_REGISTER_PRESSUREDATA = 0xF7, + BME280_REGISTER_TEMPDATA = 0xFA, + BME280_REGISTER_HUMIDDATA = 0xFD +}; + +/**************************************************************************/ +/*! + @brief calibration data +*/ +/**************************************************************************/ +typedef struct { + uint16_t dig_T1; ///< temperature compensation value + int16_t dig_T2; ///< temperature compensation value + int16_t dig_T3; ///< temperature compensation value + + uint16_t dig_P1; ///< pressure compensation value + int16_t dig_P2; ///< pressure compensation value + int16_t dig_P3; ///< pressure compensation value + int16_t dig_P4; ///< pressure compensation value + int16_t dig_P5; ///< pressure compensation value + int16_t dig_P6; ///< pressure compensation value + int16_t dig_P7; ///< pressure compensation value + int16_t dig_P8; ///< pressure compensation value + int16_t dig_P9; ///< pressure compensation value + + uint8_t dig_H1; ///< humidity compensation value + int16_t dig_H2; ///< humidity compensation value + uint8_t dig_H3; ///< humidity compensation value + int16_t dig_H4; ///< humidity compensation value + int16_t dig_H5; ///< humidity compensation value + int8_t dig_H6; ///< humidity compensation value +} bme280_calib_data; +/*=========================================================================*/ + +class Adafruit_BME280; + +/** Adafruit Unified Sensor interface for temperature component of BME280 */ +class Adafruit_BME280_Temp : public Adafruit_Sensor { +public: + /** @brief Create an Adafruit_Sensor compatible object for the temp sensor + @param parent A pointer to the BME280 class */ + Adafruit_BME280_Temp(Adafruit_BME280 *parent) { _theBME280 = parent; } + bool getEvent(sensors_event_t *); + void getSensor(sensor_t *); + +private: + int _sensorID = 280; + Adafruit_BME280 *_theBME280 = NULL; +}; + +/** Adafruit Unified Sensor interface for pressure component of BME280 */ +class Adafruit_BME280_Pressure : public Adafruit_Sensor { +public: + /** @brief Create an Adafruit_Sensor compatible object for the pressure sensor + @param parent A pointer to the BME280 class */ + Adafruit_BME280_Pressure(Adafruit_BME280 *parent) { _theBME280 = parent; } + bool getEvent(sensors_event_t *); + void getSensor(sensor_t *); + +private: + int _sensorID = 280; + Adafruit_BME280 *_theBME280 = NULL; +}; + +/** Adafruit Unified Sensor interface for humidity component of BME280 */ +class Adafruit_BME280_Humidity : public Adafruit_Sensor { +public: + /** @brief Create an Adafruit_Sensor compatible object for the humidity sensor + @param parent A pointer to the BME280 class */ + Adafruit_BME280_Humidity(Adafruit_BME280 *parent) { _theBME280 = parent; } + bool getEvent(sensors_event_t *); + void getSensor(sensor_t *); + +private: + int _sensorID = 280; + Adafruit_BME280 *_theBME280 = NULL; +}; + +/**************************************************************************/ +/*! + @brief Class that stores state and functions for interacting with BME280 IC +*/ +/**************************************************************************/ +class Adafruit_BME280 { +public: + /**************************************************************************/ + /*! + @brief sampling rates + */ + /**************************************************************************/ + enum sensor_sampling { + SAMPLING_NONE = 0b000, + SAMPLING_X1 = 0b001, + SAMPLING_X2 = 0b010, + SAMPLING_X4 = 0b011, + SAMPLING_X8 = 0b100, + SAMPLING_X16 = 0b101 + }; + + /**************************************************************************/ + /*! + @brief power modes + */ + /**************************************************************************/ + enum sensor_mode { + MODE_SLEEP = 0b00, + MODE_FORCED = 0b01, + MODE_NORMAL = 0b11 + }; + + /**************************************************************************/ + /*! + @brief filter values + */ + /**************************************************************************/ + enum sensor_filter { + FILTER_OFF = 0b000, + FILTER_X2 = 0b001, + FILTER_X4 = 0b010, + FILTER_X8 = 0b011, + FILTER_X16 = 0b100 + }; + + /**************************************************************************/ + /*! + @brief standby duration in ms + */ + /**************************************************************************/ + enum standby_duration { + STANDBY_MS_0_5 = 0b000, + STANDBY_MS_10 = 0b110, + STANDBY_MS_20 = 0b111, + STANDBY_MS_62_5 = 0b001, + STANDBY_MS_125 = 0b010, + STANDBY_MS_250 = 0b011, + STANDBY_MS_500 = 0b100, + STANDBY_MS_1000 = 0b101 + }; + + // constructors + Adafruit_BME280(); + Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI); + Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); + ~Adafruit_BME280(void); + bool begin(uint8_t addr = BME280_ADDRESS, TwoWire *theWire = &Wire); + bool init(); + + void setSampling(sensor_mode mode = MODE_NORMAL, + sensor_sampling tempSampling = SAMPLING_X16, + sensor_sampling pressSampling = SAMPLING_X16, + sensor_sampling humSampling = SAMPLING_X16, + sensor_filter filter = FILTER_OFF, + standby_duration duration = STANDBY_MS_0_5); + + bool takeForcedMeasurement(void); + float readTemperature(void); + float readPressure(void); + float readHumidity(void); + + float readAltitude(float seaLevel); + float seaLevelForAltitude(float altitude, float pressure); + uint32_t sensorID(void); + + float getTemperatureCompensation(void); + void setTemperatureCompensation(float); + + Adafruit_Sensor *getTemperatureSensor(void); + Adafruit_Sensor *getPressureSensor(void); + Adafruit_Sensor *getHumiditySensor(void); + +protected: + Adafruit_I2CDevice *i2c_dev = NULL; ///< Pointer to I2C bus interface + Adafruit_SPIDevice *spi_dev = NULL; ///< Pointer to SPI bus interface + + Adafruit_BME280_Temp *temp_sensor = NULL; + //!< Adafruit_Sensor compat temperature sensor component + + Adafruit_BME280_Pressure *pressure_sensor = NULL; + //!< Adafruit_Sensor compat pressure sensor component + + Adafruit_BME280_Humidity *humidity_sensor = NULL; + //!< Adafruit_Sensor compat humidity sensor component + + void readCoefficients(void); + bool isReadingCalibration(void); + + void write8(byte reg, byte value); + uint8_t read8(byte reg); + uint16_t read16(byte reg); + uint32_t read24(byte reg); + int16_t readS16(byte reg); + uint16_t read16_LE(byte reg); // little endian + int16_t readS16_LE(byte reg); // little endian + + uint8_t _i2caddr; //!< I2C addr for the TwoWire interface + int32_t _sensorID; //!< ID of the BME Sensor + int32_t t_fine; //!< temperature with high resolution, stored as an attribute + //!< as this is used for temperature compensation reading + //!< humidity and pressure + + int32_t t_fine_adjust = 0; //!< add to compensate temp readings and in turn + //!< to pressure and humidity readings + + bme280_calib_data _bme280_calib; //!< here calibration data is stored + + /**************************************************************************/ + /*! + @brief config register + */ + /**************************************************************************/ + struct config { + // inactive duration (standby time) in normal mode + // 000 = 0.5 ms + // 001 = 62.5 ms + // 010 = 125 ms + // 011 = 250 ms + // 100 = 500 ms + // 101 = 1000 ms + // 110 = 10 ms + // 111 = 20 ms + unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode + + // filter settings + // 000 = filter off + // 001 = 2x filter + // 010 = 4x filter + // 011 = 8x filter + // 100 and above = 16x filter + unsigned int filter : 3; ///< filter settings + + // unused - don't set + unsigned int none : 1; ///< unused - don't set + unsigned int spi3w_en : 1; ///< unused - don't set + + /// @return combined config register + unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; } + }; + config _configReg; //!< config register object + + /**************************************************************************/ + /*! + @brief ctrl_meas register + */ + /**************************************************************************/ + struct ctrl_meas { + // temperature oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_t : 3; ///< temperature oversampling + + // pressure oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_p : 3; ///< pressure oversampling + + // device mode + // 00 = sleep + // 01 or 10 = forced + // 11 = normal + unsigned int mode : 2; ///< device mode + + /// @return combined ctrl register + unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; } + }; + ctrl_meas _measReg; //!< measurement register object + + /**************************************************************************/ + /*! + @brief ctrl_hum register + */ + /**************************************************************************/ + struct ctrl_hum { + /// unused - don't set + unsigned int none : 5; + + // pressure oversampling + // 000 = skipped + // 001 = x1 + // 010 = x2 + // 011 = x4 + // 100 = x8 + // 101 and above = x16 + unsigned int osrs_h : 3; ///< pressure oversampling + + /// @return combined ctrl hum register + unsigned int get() { return (osrs_h); } + }; + ctrl_hum _humReg; //!< hum register object +}; + +#endif diff --git a/libraries/Adafruit_BME280_Library/LICENSE b/libraries/Adafruit_BME280_Library/LICENSE new file mode 100644 index 0000000..f4db09c --- /dev/null +++ b/libraries/Adafruit_BME280_Library/LICENSE @@ -0,0 +1,27 @@ +Copyright (c) 2015, Limor Fried & Kevin Townsend for Adafruit Industries +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. + * Neither the name of Adafruit Industries nor the names of its + contributors may be used to endorse or promote products derived from + this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + diff --git a/libraries/Adafruit_BME280_Library/README.md b/libraries/Adafruit_BME280_Library/README.md new file mode 100644 index 0000000..039e969 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/README.md @@ -0,0 +1,54 @@ +# Adafruit BME280 Library [![Build Status](https://github.com/adafruit/Adafruit_BME280_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BME280_Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BME280_Library/html/index.html) + + + + +This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor + +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! + +# Installation +To install, use the Arduino Library Manager and search for "Adafruit BME280" and install the library. + +## Dependencies + * [Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor) + +# Contributing + +Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_PM25AQI/blob/master/CODE_OF_CONDUCT.md>) +before contributing to help this project stay welcoming. + +## Documentation and doxygen +Documentation is produced by doxygen. Contributions should include documentation for any new code added. + +Some examples of how to use doxygen can be found in these guide pages: + +https://learn.adafruit.com/the-well-automated-arduino-library/doxygen + +https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips + +## Formatting and clang-format +This library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of `.cpp` and `.h` files. +Contributions should be formatted using `clang-format`: + +The `-i` flag will make the changes to the file. +```bash +clang-format -i *.cpp *.h +``` +If you prefer to make the changes yourself, running `clang-format` without the `-i` flag will print out a formatted version of the file. You can save this to a file and diff it against the original to see the changes. + +Note that the formatting output by `clang-format` is what the automated formatting checker will expect. Any diffs from this formatting will result in a failed build until they are addressed. Using the `-i` flag is highly recommended. + +### clang-format resources + * [Binary builds and source available on the LLVM downloads page](https://releases.llvm.org/download.html) + * [Documentation and IDE integration](https://clang.llvm.org/docs/ClangFormat.html) + +## About this Driver +Written by Ladyada for Adafruit Industries. + +BSD license, check license.txt for more information + +All text above must be included in any redistribution diff --git a/libraries/Adafruit_BME280_Library/assets/board.jpg b/libraries/Adafruit_BME280_Library/assets/board.jpg new file mode 100644 index 0000000..581f4ba Binary files /dev/null and b/libraries/Adafruit_BME280_Library/assets/board.jpg differ diff --git a/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino b/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino new file mode 100644 index 0000000..df1f5eb --- /dev/null +++ b/libraries/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino @@ -0,0 +1,159 @@ +/*************************************************************************** + This is a library for the BME280 humidity, temperature & pressure sensor + + Designed specifically to work with the Adafruit BME280 Breakout + ----> http://www.adafruit.com/products/2650 + + These sensors use I2C or SPI to communicate, 2 or 4 pins are required + to interface. The device's I2C address is either 0x76 or 0x77. + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Written by Limor Fried & Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + See the LICENSE file for details. + ***************************************************************************/ + +#include +#include +#include +#include + +#define BME_SCK 13 +#define BME_MISO 12 +#define BME_MOSI 11 +#define BME_CS 10 + +#define SEALEVELPRESSURE_HPA (1013.25) + +Adafruit_BME280 bme; // I2C +//Adafruit_BME280 bme(BME_CS); // hardware SPI +//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI + +unsigned long delayTime; + +void setup() { + Serial.begin(9600); + Serial.println(F("BME280 test")); + + if (! bme.begin(0x77, &Wire)) { + Serial.println("Could not find a valid BME280 sensor, check wiring!"); + while (1); + } + + Serial.println("-- Default Test --"); + Serial.println("normal mode, 16x oversampling for all, filter off,"); + Serial.println("0.5ms standby period"); + delayTime = 5000; + + + // For more details on the following scenarious, see chapter + // 3.5 "Recommended modes of operation" in the datasheet + +/* + // weather monitoring + Serial.println("-- Weather Station Scenario --"); + Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,"); + Serial.println("filter off"); + bme.setSampling(Adafruit_BME280::MODE_FORCED, + Adafruit_BME280::SAMPLING_X1, // temperature + Adafruit_BME280::SAMPLING_X1, // pressure + Adafruit_BME280::SAMPLING_X1, // humidity + Adafruit_BME280::FILTER_OFF ); + + // suggested rate is 1/60Hz (1m) + delayTime = 60000; // in milliseconds +*/ + +/* + // humidity sensing + Serial.println("-- Humidity Sensing Scenario --"); + Serial.println("forced mode, 1x temperature / 1x humidity / 0x pressure oversampling"); + Serial.println("= pressure off, filter off"); + bme.setSampling(Adafruit_BME280::MODE_FORCED, + Adafruit_BME280::SAMPLING_X1, // temperature + Adafruit_BME280::SAMPLING_NONE, // pressure + Adafruit_BME280::SAMPLING_X1, // humidity + Adafruit_BME280::FILTER_OFF ); + + // suggested rate is 1Hz (1s) + delayTime = 1000; // in milliseconds +*/ + +/* + // indoor navigation + Serial.println("-- Indoor Navigation Scenario --"); + Serial.println("normal mode, 16x pressure / 2x temperature / 1x humidity oversampling,"); + Serial.println("0.5ms standby period, filter 16x"); + bme.setSampling(Adafruit_BME280::MODE_NORMAL, + Adafruit_BME280::SAMPLING_X2, // temperature + Adafruit_BME280::SAMPLING_X16, // pressure + Adafruit_BME280::SAMPLING_X1, // humidity + Adafruit_BME280::FILTER_X16, + Adafruit_BME280::STANDBY_MS_0_5 ); + + // suggested rate is 25Hz + // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) + (2 * H_ovs + 0.5) + // T_ovs = 2 + // P_ovs = 16 + // H_ovs = 1 + // = 40ms (25Hz) + // with standby time that should really be 24.16913... Hz + delayTime = 41; + */ + + /* + // gaming + Serial.println("-- Gaming Scenario --"); + Serial.println("normal mode, 4x pressure / 1x temperature / 0x humidity oversampling,"); + Serial.println("= humidity off, 0.5ms standby period, filter 16x"); + bme.setSampling(Adafruit_BME280::MODE_NORMAL, + Adafruit_BME280::SAMPLING_X1, // temperature + Adafruit_BME280::SAMPLING_X4, // pressure + Adafruit_BME280::SAMPLING_NONE, // humidity + Adafruit_BME280::FILTER_X16, + Adafruit_BME280::STANDBY_MS_0_5 ); + + // Suggested rate is 83Hz + // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) + // T_ovs = 1 + // P_ovs = 4 + // = 11.5ms + 0.5ms standby + delayTime = 12; +*/ + + Serial.println(); +} + + +void loop() { + // Only needed in forced mode! In normal mode, you can remove the next line. + bme.takeForcedMeasurement(); // has no effect in normal mode + + printValues(); + delay(delayTime); +} + + +void printValues() { + Serial.print("Temperature = "); + Serial.print(bme.readTemperature()); + Serial.println(" *C"); + + Serial.print("Pressure = "); + + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + Serial.print("Approx. Altitude = "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.print("Humidity = "); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.println(); +} diff --git a/libraries/Adafruit_BME280_Library/examples/bme280_unified/bme280_unified.ino b/libraries/Adafruit_BME280_Library/examples/bme280_unified/bme280_unified.ino new file mode 100644 index 0000000..8a67af4 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/examples/bme280_unified/bme280_unified.ino @@ -0,0 +1,62 @@ +/*************************************************************************** + This is a library for the BME280 humidity, temperature & pressure sensor + This example shows how to take Sensor Events instead of direct readings + + Designed specifically to work with the Adafruit BME280 Breakout + ----> http://www.adafruit.com/products/2652 + + These sensors use I2C or SPI to communicate, 2 or 4 pins are required + to interface. + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing products + from Adafruit! + + Written by Limor Fried & Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + ***************************************************************************/ + +#include +#include +#include + +Adafruit_BME280 bme; // use I2C interface +Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); +Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); +Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); + +void setup() { + Serial.begin(9600); + Serial.println(F("BME280 Sensor event test")); + + if (!bme.begin()) { + Serial.println(F("Could not find a valid BME280 sensor, check wiring!")); + while (1) delay(10); + } + + bme_temp->printSensorDetails(); + bme_pressure->printSensorDetails(); + bme_humidity->printSensorDetails(); +} + +void loop() { + sensors_event_t temp_event, pressure_event, humidity_event; + bme_temp->getEvent(&temp_event); + bme_pressure->getEvent(&pressure_event); + bme_humidity->getEvent(&humidity_event); + + Serial.print(F("Temperature = ")); + Serial.print(temp_event.temperature); + Serial.println(" *C"); + + Serial.print(F("Humidity = ")); + Serial.print(humidity_event.relative_humidity); + Serial.println(" %"); + + Serial.print(F("Pressure = ")); + Serial.print(pressure_event.pressure); + Serial.println(" hPa"); + + Serial.println(); + delay(1000); +} \ No newline at end of file diff --git a/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino b/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino new file mode 100644 index 0000000..d28ce05 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/examples/bme280test/bme280test.ino @@ -0,0 +1,90 @@ +/*************************************************************************** + This is a library for the BME280 humidity, temperature & pressure sensor + + Designed specifically to work with the Adafruit BME280 Breakout + ----> http://www.adafruit.com/products/2650 + + These sensors use I2C or SPI to communicate, 2 or 4 pins are required + to interface. The device's I2C address is either 0x76 or 0x77. + + Adafruit invests time and resources providing this open source code, + please support Adafruit andopen-source hardware by purchasing products + from Adafruit! + + Written by Limor Fried & Kevin Townsend for Adafruit Industries. + BSD license, all text above must be included in any redistribution + See the LICENSE file for details. + ***************************************************************************/ + +#include +#include +#include +#include + +#define BME_SCK 13 +#define BME_MISO 12 +#define BME_MOSI 11 +#define BME_CS 10 + +#define SEALEVELPRESSURE_HPA (1013.25) + +Adafruit_BME280 bme; // I2C +//Adafruit_BME280 bme(BME_CS); // hardware SPI +//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI + +unsigned long delayTime; + +void setup() { + Serial.begin(9600); + while(!Serial); // time to get serial running + Serial.println(F("BME280 test")); + + unsigned status; + + // default settings + status = bme.begin(); + // You can also pass in a Wire library object like &Wire2 + // status = bme.begin(0x76, &Wire2) + if (!status) { + Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); + Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); + Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); + Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); + Serial.print(" ID of 0x60 represents a BME 280.\n"); + Serial.print(" ID of 0x61 represents a BME 680.\n"); + while (1) delay(10); + } + + Serial.println("-- Default Test --"); + delayTime = 1000; + + Serial.println(); +} + + +void loop() { + printValues(); + delay(delayTime); +} + + +void printValues() { + Serial.print("Temperature = "); + Serial.print(bme.readTemperature()); + Serial.println(" °C"); + + Serial.print("Pressure = "); + + Serial.print(bme.readPressure() / 100.0F); + Serial.println(" hPa"); + + Serial.print("Approx. Altitude = "); + Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + Serial.println(" m"); + + Serial.print("Humidity = "); + Serial.print(bme.readHumidity()); + Serial.println(" %"); + + Serial.println(); +} diff --git a/libraries/Adafruit_BME280_Library/library.properties b/libraries/Adafruit_BME280_Library/library.properties new file mode 100644 index 0000000..7a73557 --- /dev/null +++ b/libraries/Adafruit_BME280_Library/library.properties @@ -0,0 +1,10 @@ +name=Adafruit BME280 Library +version=2.2.4 +author=Adafruit +maintainer=Adafruit +sentence=Arduino library for BME280 sensors. +paragraph=Arduino library for BME280 humidity and pressure sensors. +category=Sensors +url=https://github.com/adafruit/Adafruit_BME280_Library +architectures=* +depends=Adafruit Unified Sensor, Adafruit BusIO diff --git a/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.cpp b/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.cpp new file mode 100644 index 0000000..f3e8187 --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.cpp @@ -0,0 +1,384 @@ +#include + +#if !defined(SPI_INTERFACES_COUNT) || \ + (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0)) + +/*! + * @brief Create a register we access over an I2C Device (which defines the + * bus and address) + * @param i2cdevice The I2CDevice to use for underlying I2C access + * @param reg_addr The address pointer value for the I2C/SMBus register, can + * be 8 or 16 bits + * @param width The width of the register data itself, defaults to 1 byte + * @param byteorder The byte order of the register (used when width is > 1), + * defaults to LSBFIRST + * @param address_width The width of the register address itself, defaults + * to 1 byte + */ +Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, + uint16_t reg_addr, + uint8_t width, + uint8_t byteorder, + uint8_t address_width) { + _i2cdevice = i2cdevice; + _spidevice = nullptr; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; +} + +/*! + * @brief Create a register we access over an SPI Device (which defines the + * bus and CS pin) + * @param spidevice The SPIDevice to use for underlying SPI access + * @param reg_addr The address pointer value for the SPI register, can + * be 8 or 16 bits + * @param type The method we use to read/write data to SPI (which is not + * as well defined as I2C) + * @param width The width of the register data itself, defaults to 1 byte + * @param byteorder The byte order of the register (used when width is > 1), + * defaults to LSBFIRST + * @param address_width The width of the register address itself, defaults + * to 1 byte + */ +Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, + uint16_t reg_addr, + Adafruit_BusIO_SPIRegType type, + uint8_t width, + uint8_t byteorder, + uint8_t address_width) { + _spidevice = spidevice; + _spiregtype = type; + _i2cdevice = nullptr; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; +} + +/*! + * @brief Create a register we access over an I2C or SPI Device. This is a + * handy function because we can pass in nullptr for the unused interface, + * allowing libraries to mass-define all the registers + * @param i2cdevice The I2CDevice to use for underlying I2C access, if + * nullptr we use SPI + * @param spidevice The SPIDevice to use for underlying SPI access, if + * nullptr we use I2C + * @param reg_addr The address pointer value for the I2C/SMBus/SPI register, + * can be 8 or 16 bits + * @param type The method we use to read/write data to SPI (which is not + * as well defined as I2C) + * @param width The width of the register data itself, defaults to 1 byte + * @param byteorder The byte order of the register (used when width is > 1), + * defaults to LSBFIRST + * @param address_width The width of the register address itself, defaults + * to 1 byte + */ +Adafruit_BusIO_Register::Adafruit_BusIO_Register( + Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice, + Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, uint8_t width, + uint8_t byteorder, uint8_t address_width) { + _spidevice = spidevice; + _i2cdevice = i2cdevice; + _spiregtype = type; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; +} + +/*! + * @brief Create a register we access over a GenericDevice + * @param genericdevice Generic device to use + * @param reg_addr Register address we will read/write + * @param width Width of the register in bytes (1-4) + * @param byteorder Byte order of register data (LSBFIRST or MSBFIRST) + * @param address_width Width of the register address in bytes (1 or 2) + */ +Adafruit_BusIO_Register::Adafruit_BusIO_Register( + Adafruit_GenericDevice *genericdevice, uint16_t reg_addr, uint8_t width, + uint8_t byteorder, uint8_t address_width) { + _i2cdevice = nullptr; + _spidevice = nullptr; + _genericdevice = genericdevice; + _addrwidth = address_width; + _address = reg_addr; + _byteorder = byteorder; + _width = width; +} + +/*! + * @brief Write a buffer of data to the register location + * @param buffer Pointer to data to write + * @param len Number of bytes to write + * @return True on successful write (only really useful for I2C as SPI is + * uncheckable) + */ +bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) { + uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), + (uint8_t)(_address >> 8)}; + if (_i2cdevice) { + return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth); + } + if (_spidevice) { + if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { + // very special case! + // pass the special opcode address which we set as the high byte of the + // regaddr + addrbuffer[0] = + (uint8_t)(_address >> 8) & ~0x01; // set bottom bit low to write + // the 'actual' reg addr is the second byte then + addrbuffer[1] = (uint8_t)(_address & 0xFF); + // the address appears to be a byte longer + return _spidevice->write(buffer, len, addrbuffer, _addrwidth + 1); + } + if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { + addrbuffer[0] &= ~0x80; + } + if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { + addrbuffer[0] |= 0x80; + } + if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { + addrbuffer[0] &= ~0x80; + addrbuffer[0] |= 0x40; + } + return _spidevice->write(buffer, len, addrbuffer, _addrwidth); + } + if (_genericdevice) { + return _genericdevice->writeRegister(addrbuffer, _addrwidth, buffer, len); + } + return false; +} + +/*! + * @brief Write up to 4 bytes of data to the register location + * @param value Data to write + * @param numbytes How many bytes from 'value' to write + * @return True on successful write (only really useful for I2C as SPI is + * uncheckable) + */ +bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) { + if (numbytes == 0) { + numbytes = _width; + } + if (numbytes > 4) { + return false; + } + + // store a copy + _cached = value; + + for (int i = 0; i < numbytes; i++) { + if (_byteorder == LSBFIRST) { + _buffer[i] = value & 0xFF; + } else { + _buffer[numbytes - i - 1] = value & 0xFF; + } + value >>= 8; + } + return write(_buffer, numbytes); +} + +/*! + * @brief Read data from the register location. This does not do any error + * checking! + * @return Returns 0xFFFFFFFF on failure, value otherwise + */ +uint32_t Adafruit_BusIO_Register::read(void) { + if (!read(_buffer, _width)) { + return -1; + } + + uint32_t value = 0; + + for (int i = 0; i < _width; i++) { + value <<= 8; + if (_byteorder == LSBFIRST) { + value |= _buffer[_width - i - 1]; + } else { + value |= _buffer[i]; + } + } + + return value; +} + +/*! + * @brief Read cached data from last time we wrote to this register + * @return Returns 0xFFFFFFFF on failure, value otherwise + */ +uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; } + +/*! + @brief Read a number of bytes from a register into a buffer + @param buffer Buffer to read data into + @param len Number of bytes to read into the buffer + @return true on successful read, otherwise false +*/ +bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) { + uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), + (uint8_t)(_address >> 8)}; + if (_i2cdevice) { + return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_spidevice) { + if (_spiregtype == ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE) { + // very special case! + // pass the special opcode address which we set as the high byte of the + // regaddr + addrbuffer[0] = + (uint8_t)(_address >> 8) | 0x01; // set bottom bit high to read + // the 'actual' reg addr is the second byte then + addrbuffer[1] = (uint8_t)(_address & 0xFF); + // the address appears to be a byte longer + return _spidevice->write_then_read(addrbuffer, _addrwidth + 1, buffer, + len); + } + if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { + addrbuffer[0] |= 0x80; + } + if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { + addrbuffer[0] &= ~0x80; + } + if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { + addrbuffer[0] |= 0x80 | 0x40; + } + return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); + } + if (_genericdevice) { + return _genericdevice->readRegister(addrbuffer, _addrwidth, buffer, len); + } + return false; +} + +/*! + * @brief Read 2 bytes of data from the register location + * @param value Pointer to uint16_t variable to read into + * @return True on successful write (only really useful for I2C as SPI is + * uncheckable) + */ +bool Adafruit_BusIO_Register::read(uint16_t *value) { + if (!read(_buffer, 2)) { + return false; + } + + if (_byteorder == LSBFIRST) { + *value = _buffer[1]; + *value <<= 8; + *value |= _buffer[0]; + } else { + *value = _buffer[0]; + *value <<= 8; + *value |= _buffer[1]; + } + return true; +} + +/*! + * @brief Read 1 byte of data from the register location + * @param value Pointer to uint8_t variable to read into + * @return True on successful write (only really useful for I2C as SPI is + * uncheckable) + */ +bool Adafruit_BusIO_Register::read(uint8_t *value) { + if (!read(_buffer, 1)) { + return false; + } + + *value = _buffer[0]; + return true; +} + +/*! + * @brief Pretty printer for this register + * @param s The Stream to print to, defaults to &Serial + */ +void Adafruit_BusIO_Register::print(Stream *s) { + uint32_t val = read(); + s->print("0x"); + s->print(val, HEX); +} + +/*! + * @brief Pretty printer for this register + * @param s The Stream to print to, defaults to &Serial + */ +void Adafruit_BusIO_Register::println(Stream *s) { + print(s); + s->println(); +} + +/*! + * @brief Create a slice of the register that we can address without + * touching other bits + * @param reg The Adafruit_BusIO_Register which defines the bus/register + * @param bits The number of bits wide we are slicing + * @param shift The number of bits that our bit-slice is shifted from LSB + */ +Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits( + Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) { + _register = reg; + _bits = bits; + _shift = shift; +} + +/*! + * @brief Read 4 bytes of data from the register + * @return data The 4 bytes to read + */ +uint32_t Adafruit_BusIO_RegisterBits::read(void) { + uint32_t val = _register->read(); + val >>= _shift; + return val & ((1 << (_bits)) - 1); +} + +/*! + * @brief Write 4 bytes of data to the register + * @param data The 4 bytes to write + * @return True on successful write (only really useful for I2C as SPI is + * uncheckable) + */ +bool Adafruit_BusIO_RegisterBits::write(uint32_t data) { + uint32_t val = _register->read(); + + // mask off the data before writing + uint32_t mask = (1 << (_bits)) - 1; + data &= mask; + + mask <<= _shift; + val &= ~mask; // remove the current data at that spot + val |= data << _shift; // and add in the new data + + return _register->write(val, _register->width()); +} + +/*! + * @brief The width of the register data, helpful for doing calculations + * @returns The data width used when initializing the register + */ +uint8_t Adafruit_BusIO_Register::width(void) { return _width; } + +/*! + * @brief Set the default width of data + * @param width the default width of data read from register + */ +void Adafruit_BusIO_Register::setWidth(uint8_t width) { _width = width; } + +/*! + * @brief Set register address + * @param address the address from register + */ +void Adafruit_BusIO_Register::setAddress(uint16_t address) { + _address = address; +} + +/*! + * @brief Set the width of register address + * @param address_width the width for register address + */ +void Adafruit_BusIO_Register::setAddressWidth(uint16_t address_width) { + _addrwidth = address_width; +} + +#endif // SPI exists diff --git a/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.h b/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.h new file mode 100644 index 0000000..ee7a57e --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_BusIO_Register.h @@ -0,0 +1,112 @@ +#ifndef Adafruit_BusIO_Register_h +#define Adafruit_BusIO_Register_h + +#include + +#if !defined(SPI_INTERFACES_COUNT) || \ + (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0)) + +#include +#include +#include + +typedef enum _Adafruit_BusIO_SPIRegType { + ADDRBIT8_HIGH_TOREAD = 0, + /*!< + * ADDRBIT8_HIGH_TOREAD + * When reading a register you must actually send the value 0x80 + register + * address to the device. e.g. To read the register 0x0B the register value + * 0x8B is sent and to write 0x0B is sent. + */ + AD8_HIGH_TOREAD_AD7_HIGH_TOINC = 1, + + /*!< + * ADDRBIT8_HIGH_TOWRITE + * When writing to a register you must actually send the value 0x80 + + * the register address to the device. e.g. To write to the register 0x19 the + * register value 0x99 is sent and to read 0x19 is sent. + */ + ADDRBIT8_HIGH_TOWRITE = 2, + + /*!< + * ADDRESSED_OPCODE_LOWBIT_TO_WRITE + * Used by the MCP23S series, we send 0x40 |'rd with the opcode + * Then set the lowest bit to write + */ + ADDRESSED_OPCODE_BIT0_LOW_TO_WRITE = 3, + +} Adafruit_BusIO_SPIRegType; + +/*! + * @brief The class which defines a device register (a location to read/write + * data from) + */ +class Adafruit_BusIO_Register { +public: + Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr, + uint8_t width = 1, uint8_t byteorder = LSBFIRST, + uint8_t address_width = 1); + + Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr, + Adafruit_BusIO_SPIRegType type, uint8_t width = 1, + uint8_t byteorder = LSBFIRST, + uint8_t address_width = 1); + + Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, + Adafruit_SPIDevice *spidevice, + Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, + uint8_t width = 1, uint8_t byteorder = LSBFIRST, + uint8_t address_width = 1); + + Adafruit_BusIO_Register(Adafruit_GenericDevice *genericdevice, + uint16_t reg_addr, uint8_t width = 1, + uint8_t byteorder = LSBFIRST, + uint8_t address_width = 1); + + bool read(uint8_t *buffer, uint8_t len); + bool read(uint8_t *value); + bool read(uint16_t *value); + uint32_t read(void); + uint32_t readCached(void); + bool write(uint8_t *buffer, uint8_t len); + bool write(uint32_t value, uint8_t numbytes = 0); + + uint8_t width(void); + + void setWidth(uint8_t width); + void setAddress(uint16_t address); + void setAddressWidth(uint16_t address_width); + + void print(Stream *s = &Serial); + void println(Stream *s = &Serial); + +private: + Adafruit_I2CDevice *_i2cdevice; + Adafruit_SPIDevice *_spidevice; + Adafruit_GenericDevice *_genericdevice; + Adafruit_BusIO_SPIRegType _spiregtype; + uint16_t _address; + uint8_t _width, _addrwidth, _byteorder; + uint8_t _buffer[4]; // we won't support anything larger than uint32 for + // non-buffered read + uint32_t _cached = 0; +}; + +/*! + * @brief The class which defines a slice of bits from within a device register + * (a location to read/write data from) + */ +class Adafruit_BusIO_RegisterBits { +public: + Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, + uint8_t shift); + bool write(uint32_t value); + uint32_t read(void); + +private: + Adafruit_BusIO_Register *_register; + uint8_t _bits, _shift; +}; + +#endif // SPI exists +#endif // BusIO_Register_h diff --git a/libraries/Adafruit_BusIO/Adafruit_GenericDevice.cpp b/libraries/Adafruit_BusIO/Adafruit_GenericDevice.cpp new file mode 100644 index 0000000..7fe5a10 --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_GenericDevice.cpp @@ -0,0 +1,82 @@ +/* + Written with help by Claude! + https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time + chats are not shareable :( +*/ + +#include "Adafruit_GenericDevice.h" + +/*! + * @brief Create a Generic device with the provided read/write functions + * @param obj Pointer to object instance + * @param read_func Function pointer for reading raw data + * @param write_func Function pointer for writing raw data + * @param readreg_func Function pointer for reading registers (optional) + * @param writereg_func Function pointer for writing registers (optional) */ +Adafruit_GenericDevice::Adafruit_GenericDevice( + void *obj, busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func, + busio_genericdevice_writereg_t writereg_func) { + _obj = obj; + _read_func = read_func; + _write_func = write_func; + _readreg_func = readreg_func; + _writereg_func = writereg_func; + _begun = false; +} + +/*! @brief Simple begin function (doesn't do much at this time) + @return true always +*/ +bool Adafruit_GenericDevice::begin(void) { + _begun = true; + return true; +} + +/*! @brief Write a buffer of data + @param buffer Pointer to buffer of data to write + @param len Number of bytes to write + @return true if write was successful, otherwise false */ +bool Adafruit_GenericDevice::write(const uint8_t *buffer, size_t len) { + if (!_begun) + return false; + return _write_func(_obj, buffer, len); +} + +/*! @brief Read data into a buffer + @param buffer Pointer to buffer to read data into + @param len Number of bytes to read + @return true if read was successful, otherwise false */ +bool Adafruit_GenericDevice::read(uint8_t *buffer, size_t len) { + if (!_begun) + return false; + return _read_func(_obj, buffer, len); +} + +/*! @brief Read from a register location + @param addr_buf Buffer containing register address + @param addrsiz Size of register address in bytes + @param buf Buffer to store read data + @param bufsiz Size of data to read in bytes + @return true if read was successful, otherwise false */ +bool Adafruit_GenericDevice::readRegister(uint8_t *addr_buf, uint8_t addrsiz, + uint8_t *buf, uint16_t bufsiz) { + if (!_begun || !_readreg_func) + return false; + return _readreg_func(_obj, addr_buf, addrsiz, buf, bufsiz); +} + +/*! @brief Write to a register location + @param addr_buf Buffer containing register address + @param addrsiz Size of register address in bytes + @param buf Buffer containing data to write + @param bufsiz Size of data to write in bytes + @return true if write was successful, otherwise false */ +bool Adafruit_GenericDevice::writeRegister(uint8_t *addr_buf, uint8_t addrsiz, + const uint8_t *buf, + uint16_t bufsiz) { + if (!_begun || !_writereg_func) + return false; + return _writereg_func(_obj, addr_buf, addrsiz, buf, bufsiz); +} diff --git a/libraries/Adafruit_BusIO/Adafruit_GenericDevice.h b/libraries/Adafruit_BusIO/Adafruit_GenericDevice.h new file mode 100644 index 0000000..14bb8ae --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_GenericDevice.h @@ -0,0 +1,55 @@ +#ifndef ADAFRUIT_GENERICDEVICE_H +#define ADAFRUIT_GENERICDEVICE_H + +#include + +typedef bool (*busio_genericdevice_read_t)(void *obj, uint8_t *buffer, + size_t len); +typedef bool (*busio_genericdevice_write_t)(void *obj, const uint8_t *buffer, + size_t len); +typedef bool (*busio_genericdevice_readreg_t)(void *obj, uint8_t *addr_buf, + uint8_t addrsiz, uint8_t *data, + uint16_t datalen); +typedef bool (*busio_genericdevice_writereg_t)(void *obj, uint8_t *addr_buf, + uint8_t addrsiz, + const uint8_t *data, + uint16_t datalen); + +/*! + * @brief Class for communicating with a device via generic read/write functions + */ +class Adafruit_GenericDevice { +public: + Adafruit_GenericDevice( + void *obj, busio_genericdevice_read_t read_func, + busio_genericdevice_write_t write_func, + busio_genericdevice_readreg_t readreg_func = nullptr, + busio_genericdevice_writereg_t writereg_func = nullptr); + + bool begin(void); + + bool read(uint8_t *buffer, size_t len); + bool write(const uint8_t *buffer, size_t len); + bool readRegister(uint8_t *addr_buf, uint8_t addrsiz, uint8_t *buf, + uint16_t bufsiz); + bool writeRegister(uint8_t *addr_buf, uint8_t addrsiz, const uint8_t *buf, + uint16_t bufsiz); + +protected: + /*! @brief Function pointer for reading raw data from the device */ + busio_genericdevice_read_t _read_func; + /*! @brief Function pointer for writing raw data to the device */ + busio_genericdevice_write_t _write_func; + /*! @brief Function pointer for reading a 'register' from the device */ + busio_genericdevice_readreg_t _readreg_func; + /*! @brief Function pointer for writing a 'register' to the device */ + busio_genericdevice_writereg_t _writereg_func; + + bool _begun; ///< whether we have initialized yet (in case the function needs + ///< to do something) + +private: + void *_obj; ///< Pointer to object instance +}; + +#endif // ADAFRUIT_GENERICDEVICE_H diff --git a/libraries/Adafruit_BusIO/Adafruit_I2CDevice.cpp b/libraries/Adafruit_BusIO/Adafruit_I2CDevice.cpp new file mode 100644 index 0000000..2633cf1 --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_I2CDevice.cpp @@ -0,0 +1,320 @@ +#include "Adafruit_I2CDevice.h" + +// #define DEBUG_SERIAL Serial + +/*! + * @brief Create an I2C device at a given address + * @param addr The 7-bit I2C address for the device + * @param theWire The I2C bus to use, defaults to &Wire + */ +Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) { + _addr = addr; + _wire = theWire; + _begun = false; +#ifdef ARDUINO_ARCH_SAMD + _maxBufferSize = 250; // as defined in Wire.h's RingBuffer +#elif defined(ESP32) + _maxBufferSize = I2C_BUFFER_LENGTH; +#else + _maxBufferSize = 32; +#endif +} + +/*! + * @brief Initializes and does basic address detection + * @param addr_detect Whether we should attempt to detect the I2C address + * with a scan. 99% of sensors/devices don't mind, but once in a while they + * don't respond well to a scan! + * @return True if I2C initialized and a device with the addr found + */ +bool Adafruit_I2CDevice::begin(bool addr_detect) { + _wire->begin(); + _begun = true; + + if (addr_detect) { + return detected(); + } + return true; +} + +/*! + * @brief De-initialize device, turn off the Wire interface + */ +void Adafruit_I2CDevice::end(void) { + // Not all port implement Wire::end(), such as + // - ESP8266 + // - AVR core without WIRE_HAS_END + // - ESP32: end() is implemented since 2.0.1 which is latest at the moment. + // Temporarily disable for now to give time for user to update. +#if !(defined(ESP8266) || \ + (defined(ARDUINO_ARCH_AVR) && !defined(WIRE_HAS_END)) || \ + defined(ARDUINO_ARCH_ESP32)) + _wire->end(); + _begun = false; +#endif +} + +/*! + * @brief Scans I2C for the address - note will give a false-positive + * if there's no pullups on I2C + * @return True if I2C initialized and a device with the addr found + */ +bool Adafruit_I2CDevice::detected(void) { + // Init I2C if not done yet + if (!_begun && !begin()) { + return false; + } + + // A basic scanner, see if it ACK's + _wire->beginTransmission(_addr); +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("Address 0x")); + DEBUG_SERIAL.print(_addr, HEX); +#endif +#ifdef ARDUINO_ARCH_MBED + _wire->write(0); // forces a write request instead of a read +#endif + if (_wire->endTransmission() == 0) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F(" Detected")); +#endif + return true; + } +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F(" Not detected")); +#endif + return false; +} + +/*! + * @brief Write a buffer or two to the I2C device. Cannot be more than + * maxBufferSize() bytes. + * @param buffer Pointer to buffer of data to write. This is const to + * ensure the content of this buffer doesn't change. + * @param len Number of bytes from buffer to write + * @param prefix_buffer Pointer to optional array of data to write before + * buffer. Cannot be more than maxBufferSize() bytes. This is const to + * ensure the content of this buffer doesn't change. + * @param prefix_len Number of bytes from prefix buffer to write + * @param stop Whether to send an I2C STOP signal on write + * @return True if write was successful, otherwise false. + */ +bool Adafruit_I2CDevice::write(const uint8_t *buffer, size_t len, bool stop, + const uint8_t *prefix_buffer, + size_t prefix_len) { + if ((len + prefix_len) > maxBufferSize()) { + // currently not guaranteed to work if more than 32 bytes! + // we will need to find out if some platforms have larger + // I2C buffer sizes :/ +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer")); +#endif + return false; + } + + _wire->beginTransmission(_addr); + + // Write the prefix data (usually an address) + if ((prefix_len != 0) && (prefix_buffer != nullptr)) { + if (_wire->write(prefix_buffer, prefix_len) != prefix_len) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); +#endif + return false; + } + } + + // Write the data itself + if (_wire->write(buffer, len) != len) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); +#endif + return false; + } + +#ifdef DEBUG_SERIAL + + DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x")); + DEBUG_SERIAL.print(_addr, HEX); + DEBUG_SERIAL.print(F(" :: ")); + if ((prefix_len != 0) && (prefix_buffer != nullptr)) { + for (uint16_t i = 0; i < prefix_len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(prefix_buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + } + } + for (uint16_t i = 0; i < len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (i % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + + if (stop) { + DEBUG_SERIAL.print("\tSTOP"); + } +#endif + + if (_wire->endTransmission(stop) == 0) { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println(); + // DEBUG_SERIAL.println("Sent!"); +#endif + return true; + } else { +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.println("\tFailed to send!"); +#endif + return false; + } +} + +/*! + * @brief Read from I2C into a buffer from the I2C device. + * Cannot be more than maxBufferSize() bytes. + * @param buffer Pointer to buffer of data to read into + * @param len Number of bytes from buffer to read. + * @param stop Whether to send an I2C STOP signal on read + * @return True if read was successful, otherwise false. + */ +bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) { + size_t pos = 0; + while (pos < len) { + size_t read_len = + ((len - pos) > maxBufferSize()) ? maxBufferSize() : (len - pos); + bool read_stop = (pos < (len - read_len)) ? false : stop; + if (!_read(buffer + pos, read_len, read_stop)) + return false; + pos += read_len; + } + return true; +} + +bool Adafruit_I2CDevice::_read(uint8_t *buffer, size_t len, bool stop) { +#if defined(TinyWireM_h) + size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len); +#elif defined(ARDUINO_ARCH_MEGAAVR) + size_t recv = _wire->requestFrom(_addr, len, stop); +#else + size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop); +#endif + + if (recv != len) { + // Not enough data available to fulfill our obligation! +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: ")); + DEBUG_SERIAL.println(recv); +#endif + return false; + } + + for (uint16_t i = 0; i < len; i++) { + buffer[i] = _wire->read(); + } + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tI2CREAD @ 0x")); + DEBUG_SERIAL.print(_addr, HEX); + DEBUG_SERIAL.print(F(" :: ")); + for (uint16_t i = 0; i < len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (len % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + DEBUG_SERIAL.println(); +#endif + + return true; +} + +/*! + * @brief Write some data, then read some data from I2C into another buffer. + * Cannot be more than maxBufferSize() bytes. The buffers can point to + * same/overlapping locations. + * @param write_buffer Pointer to buffer of data to write from + * @param write_len Number of bytes from buffer to write. + * @param read_buffer Pointer to buffer of data to read into. + * @param read_len Number of bytes from buffer to read. + * @param stop Whether to send an I2C STOP signal between the write and read + * @return True if write & read was successful, otherwise false. + */ +bool Adafruit_I2CDevice::write_then_read(const uint8_t *write_buffer, + size_t write_len, uint8_t *read_buffer, + size_t read_len, bool stop) { + if (!write(write_buffer, write_len, stop)) { + return false; + } + + return read(read_buffer, read_len); +} + +/*! + * @brief Returns the 7-bit address of this device + * @return The 7-bit address of this device + */ +uint8_t Adafruit_I2CDevice::address(void) { return _addr; } + +/*! + * @brief Change the I2C clock speed to desired (relies on + * underlying Wire support! + * @param desiredclk The desired I2C SCL frequency + * @return True if this platform supports changing I2C speed. + * Not necessarily that the speed was achieved! + */ +bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) { +#if defined(__AVR_ATmega328__) || \ + defined(__AVR_ATmega328P__) // fix arduino core set clock + // calculate TWBR correctly + + if ((F_CPU / 18) < desiredclk) { +#ifdef DEBUG_SERIAL + Serial.println(F("I2C.setSpeed too high.")); +#endif + return false; + } + uint32_t atwbr = ((F_CPU / desiredclk) - 16) / 2; + if (atwbr > 16320) { +#ifdef DEBUG_SERIAL + Serial.println(F("I2C.setSpeed too low.")); +#endif + return false; + } + + if (atwbr <= 255) { + atwbr /= 1; + TWSR = 0x0; + } else if (atwbr <= 1020) { + atwbr /= 4; + TWSR = 0x1; + } else if (atwbr <= 4080) { + atwbr /= 16; + TWSR = 0x2; + } else { // if (atwbr <= 16320) + atwbr /= 64; + TWSR = 0x3; + } + TWBR = atwbr; + +#ifdef DEBUG_SERIAL + Serial.print(F("TWSR prescaler = ")); + Serial.println(pow(4, TWSR)); + Serial.print(F("TWBR = ")); + Serial.println(atwbr); +#endif + return true; +#elif (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) && \ + !defined(TinyWireM_h) + _wire->setClock(desiredclk); + return true; + +#else + (void)desiredclk; + return false; +#endif +} diff --git a/libraries/Adafruit_BusIO/Adafruit_I2CDevice.h b/libraries/Adafruit_BusIO/Adafruit_I2CDevice.h new file mode 100644 index 0000000..6bda7ba --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_I2CDevice.h @@ -0,0 +1,36 @@ +#ifndef Adafruit_I2CDevice_h +#define Adafruit_I2CDevice_h + +#include +#include + +///< The class which defines how we will talk to this device over I2C +class Adafruit_I2CDevice { +public: + Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire = &Wire); + uint8_t address(void); + bool begin(bool addr_detect = true); + void end(void); + bool detected(void); + + bool read(uint8_t *buffer, size_t len, bool stop = true); + 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); + bool setSpeed(uint32_t desiredclk); + + /*! @brief How many bytes we can read in a transaction + * @return The size of the Wire receive/transmit buffer */ + size_t maxBufferSize() { return _maxBufferSize; } + +private: + uint8_t _addr; + TwoWire *_wire; + bool _begun; + size_t _maxBufferSize; + bool _read(uint8_t *buffer, size_t len, bool stop); +}; + +#endif // Adafruit_I2CDevice_h diff --git a/libraries/Adafruit_BusIO/Adafruit_I2CRegister.h b/libraries/Adafruit_BusIO/Adafruit_I2CRegister.h new file mode 100644 index 0000000..186850f --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_I2CRegister.h @@ -0,0 +1,10 @@ +#ifndef _ADAFRUIT_I2C_REGISTER_H_ +#define _ADAFRUIT_I2C_REGISTER_H_ + +#include +#include + +typedef Adafruit_BusIO_Register Adafruit_I2CRegister; +typedef Adafruit_BusIO_RegisterBits Adafruit_I2CRegisterBits; + +#endif diff --git a/libraries/Adafruit_BusIO/Adafruit_SPIDevice.cpp b/libraries/Adafruit_BusIO/Adafruit_SPIDevice.cpp new file mode 100644 index 0000000..dc3672b --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_SPIDevice.cpp @@ -0,0 +1,508 @@ +#include "Adafruit_SPIDevice.h" + +// #define DEBUG_SERIAL Serial + +/*! + * @brief Create an SPI device with the given CS pin and settings + * @param cspin The arduino pin number to use for chip select + * @param freq The SPI clock frequency to use, defaults to 1MHz + * @param dataOrder The SPI data order to use for bits within each byte, + * defaults to SPI_BITORDER_MSBFIRST + * @param dataMode The SPI mode to use, defaults to SPI_MODE0 + * @param theSPI The SPI bus to use, defaults to &theSPI + */ +Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, + BusIOBitOrder dataOrder, + uint8_t dataMode, SPIClass *theSPI) { +#ifdef BUSIO_HAS_HW_SPI + _cs = cspin; + _sck = _mosi = _miso = -1; + _spi = theSPI; + _begun = false; + _spiSetting = new SPISettings(freq, dataOrder, dataMode); + _freq = freq; + _dataOrder = dataOrder; + _dataMode = dataMode; +#else + // unused, but needed to suppress compiler warns + (void)cspin; + (void)freq; + (void)dataOrder; + (void)dataMode; + (void)theSPI; +#endif +} + +/*! + * @brief Create an SPI device with the given CS pin and settings + * @param cspin The arduino pin number to use for chip select + * @param sckpin The arduino pin number to use for SCK + * @param misopin The arduino pin number to use for MISO, set to -1 if not + * used + * @param mosipin The arduino pin number to use for MOSI, set to -1 if not + * used + * @param freq The SPI clock frequency to use, defaults to 1MHz + * @param dataOrder The SPI data order to use for bits within each byte, + * defaults to SPI_BITORDER_MSBFIRST + * @param dataMode The SPI mode to use, defaults to SPI_MODE0 + */ +Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, + int8_t misopin, int8_t mosipin, + uint32_t freq, BusIOBitOrder dataOrder, + uint8_t dataMode) { + _cs = cspin; + _sck = sckpin; + _miso = misopin; + _mosi = mosipin; + +#ifdef BUSIO_USE_FAST_PINIO + csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin)); + csPinMask = digitalPinToBitMask(cspin); + if (mosipin != -1) { + mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin)); + mosiPinMask = digitalPinToBitMask(mosipin); + } + if (misopin != -1) { + misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin)); + misoPinMask = digitalPinToBitMask(misopin); + } + clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin)); + clkPinMask = digitalPinToBitMask(sckpin); +#endif + + _freq = freq; + _dataOrder = dataOrder; + _dataMode = dataMode; + _begun = false; +} + +/*! + * @brief Release memory allocated in constructors + */ +Adafruit_SPIDevice::~Adafruit_SPIDevice() { + if (_spiSetting) + delete _spiSetting; +} + +/*! + * @brief Initializes SPI bus and sets CS pin high + * @return Always returns true because there's no way to test success of SPI + * init + */ +bool Adafruit_SPIDevice::begin(void) { + if (_cs != -1) { + pinMode(_cs, OUTPUT); + digitalWrite(_cs, HIGH); + } + + if (_spi) { // hardware SPI +#ifdef BUSIO_HAS_HW_SPI + _spi->begin(); +#endif + } else { + pinMode(_sck, OUTPUT); + + if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) { + // idle low on mode 0 and 1 + digitalWrite(_sck, LOW); + } else { + // idle high on mode 2 or 3 + digitalWrite(_sck, HIGH); + } + if (_mosi != -1) { + pinMode(_mosi, OUTPUT); + digitalWrite(_mosi, HIGH); + } + if (_miso != -1) { + pinMode(_miso, INPUT); + } + } + + _begun = true; + return true; +} + +/*! + * @brief Transfer (send/receive) a buffer over hard/soft SPI, without + * transaction management + * @param buffer The buffer to send and receive at the same time + * @param len The number of bytes to transfer + */ +void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) { + // + // HARDWARE SPI + // + if (_spi) { +#ifdef BUSIO_HAS_HW_SPI +#if defined(SPARK) + _spi->transfer(buffer, buffer, len, nullptr); +#elif defined(STM32) + for (size_t i = 0; i < len; i++) { + _spi->transfer(buffer[i]); + } +#else + _spi->transfer(buffer, len); +#endif + return; +#endif + } + + // + // SOFTWARE SPI + // + uint8_t startbit; + if (_dataOrder == SPI_BITORDER_LSBFIRST) { + startbit = 0x1; + } else { + startbit = 0x80; + } + + bool towrite, lastmosi = !(buffer[0] & startbit); + uint8_t bitdelay_us = (1000000 / _freq) / 2; + + for (size_t i = 0; i < len; i++) { + uint8_t reply = 0; + uint8_t send = buffer[i]; + + /* + Serial.print("\tSending software SPI byte 0x"); + Serial.print(send, HEX); + Serial.print(" -> 0x"); + */ + + // Serial.print(send, HEX); + for (uint8_t b = startbit; b != 0; + b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) { + + if (bitdelay_us) { + delayMicroseconds(bitdelay_us); + } + + if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) { + towrite = send & b; + if ((_mosi != -1) && (lastmosi != towrite)) { +#ifdef BUSIO_USE_FAST_PINIO + if (towrite) + *mosiPort = *mosiPort | mosiPinMask; + else + *mosiPort = *mosiPort & ~mosiPinMask; +#else + digitalWrite(_mosi, towrite); +#endif + lastmosi = towrite; + } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort = *clkPort | clkPinMask; // Clock high +#else + digitalWrite(_sck, HIGH); +#endif + + if (bitdelay_us) { + delayMicroseconds(bitdelay_us); + } + + if (_miso != -1) { +#ifdef BUSIO_USE_FAST_PINIO + if (*misoPort & misoPinMask) { +#else + if (digitalRead(_miso)) { +#endif + reply |= b; + } + } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort = *clkPort & ~clkPinMask; // Clock low +#else + digitalWrite(_sck, LOW); +#endif + } else { // if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort = *clkPort | clkPinMask; // Clock high +#else + digitalWrite(_sck, HIGH); +#endif + + if (bitdelay_us) { + delayMicroseconds(bitdelay_us); + } + + if (_mosi != -1) { +#ifdef BUSIO_USE_FAST_PINIO + if (send & b) + *mosiPort = *mosiPort | mosiPinMask; + else + *mosiPort = *mosiPort & ~mosiPinMask; +#else + digitalWrite(_mosi, send & b); +#endif + } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort = *clkPort & ~clkPinMask; // Clock low +#else + digitalWrite(_sck, LOW); +#endif + + if (_miso != -1) { +#ifdef BUSIO_USE_FAST_PINIO + if (*misoPort & misoPinMask) { +#else + if (digitalRead(_miso)) { +#endif + reply |= b; + } + } + } + if (_miso != -1) { + buffer[i] = reply; + } + } + } + return; +} + +/*! + * @brief Transfer (send/receive) one byte over hard/soft SPI, without + * transaction management + * @param send The byte to send + * @return The byte received while transmitting + */ +uint8_t Adafruit_SPIDevice::transfer(uint8_t send) { + uint8_t data = send; + transfer(&data, 1); + return data; +} + +/*! + * @brief Manually begin a transaction (calls beginTransaction if hardware + * SPI) + */ +void Adafruit_SPIDevice::beginTransaction(void) { + if (_spi) { +#ifdef BUSIO_HAS_HW_SPI + _spi->beginTransaction(*_spiSetting); +#endif + } +} + +/*! + * @brief Manually end a transaction (calls endTransaction if hardware SPI) + */ +void Adafruit_SPIDevice::endTransaction(void) { + if (_spi) { +#ifdef BUSIO_HAS_HW_SPI + _spi->endTransaction(); +#endif + } +} + +/*! + * @brief Assert/Deassert the CS pin if it is defined + * @param value The state the CS is set to + */ +void Adafruit_SPIDevice::setChipSelect(int value) { + if (_cs != -1) { + digitalWrite(_cs, value); + } +} + +/*! + * @brief Write a buffer or two to the SPI device, with transaction + * management. + * @brief Manually begin a transaction (calls beginTransaction if hardware + * SPI) with asserting the CS pin + */ +void Adafruit_SPIDevice::beginTransactionWithAssertingCS() { + beginTransaction(); + setChipSelect(LOW); +} + +/*! + * @brief Manually end a transaction (calls endTransaction if hardware SPI) + * with deasserting the CS pin + */ +void Adafruit_SPIDevice::endTransactionWithDeassertingCS() { + setChipSelect(HIGH); + endTransaction(); +} + +/*! + * @brief Write a buffer or two to the SPI device, with transaction + * management. + * @param buffer Pointer to buffer of data to write + * @param len Number of bytes from buffer to write + * @param prefix_buffer Pointer to optional array of data to write before + * buffer. + * @param prefix_len Number of bytes from prefix buffer to write + * @return Always returns true because there's no way to test success of SPI + * writes + */ +bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len, + const uint8_t *prefix_buffer, + size_t prefix_len) { + beginTransactionWithAssertingCS(); + + // do the writing +#if defined(ARDUINO_ARCH_ESP32) + if (_spi) { + if (prefix_len > 0) { + _spi->transferBytes((uint8_t *)prefix_buffer, nullptr, prefix_len); + } + if (len > 0) { + _spi->transferBytes((uint8_t *)buffer, nullptr, len); + } + } else +#endif + { + for (size_t i = 0; i < prefix_len; i++) { + transfer(prefix_buffer[i]); + } + for (size_t i = 0; i < len; i++) { + transfer(buffer[i]); + } + } + endTransactionWithDeassertingCS(); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); + if ((prefix_len != 0) && (prefix_buffer != nullptr)) { + for (uint16_t i = 0; i < prefix_len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(prefix_buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + } + } + for (uint16_t i = 0; i < len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (i % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + DEBUG_SERIAL.println(); +#endif + + return true; +} + +/*! + * @brief Read from SPI into a buffer from the SPI device, with transaction + * management. + * @param buffer Pointer to buffer of data to read into + * @param len Number of bytes from buffer to read. + * @param sendvalue The 8-bits of data to write when doing the data read, + * defaults to 0xFF + * @return Always returns true because there's no way to test success of SPI + * writes + */ +bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) { + memset(buffer, sendvalue, len); // clear out existing buffer + + beginTransactionWithAssertingCS(); + transfer(buffer, len); + endTransactionWithDeassertingCS(); + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); + for (uint16_t i = 0; i < len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (len % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + DEBUG_SERIAL.println(); +#endif + + return true; +} + +/*! + * @brief Write some data, then read some data from SPI into another buffer, + * with transaction management. The buffers can point to same/overlapping + * locations. This does not transmit-receive at the same time! + * @param write_buffer Pointer to buffer of data to write from + * @param write_len Number of bytes from buffer to write. + * @param read_buffer Pointer to buffer of data to read into. + * @param read_len Number of bytes from buffer to read. + * @param sendvalue The 8-bits of data to write when doing the data read, + * defaults to 0xFF + * @return Always returns true because there's no way to test success of SPI + * writes + */ +bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer, + size_t write_len, uint8_t *read_buffer, + size_t read_len, uint8_t sendvalue) { + beginTransactionWithAssertingCS(); + // do the writing +#if defined(ARDUINO_ARCH_ESP32) + if (_spi) { + if (write_len > 0) { + _spi->transferBytes((uint8_t *)write_buffer, nullptr, write_len); + } + } else +#endif + { + for (size_t i = 0; i < write_len; i++) { + transfer(write_buffer[i]); + } + } + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); + for (uint16_t i = 0; i < write_len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(write_buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (write_len % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + DEBUG_SERIAL.println(); +#endif + + // do the reading + for (size_t i = 0; i < read_len; i++) { + read_buffer[i] = transfer(sendvalue); + } + +#ifdef DEBUG_SERIAL + DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); + for (uint16_t i = 0; i < read_len; i++) { + DEBUG_SERIAL.print(F("0x")); + DEBUG_SERIAL.print(read_buffer[i], HEX); + DEBUG_SERIAL.print(F(", ")); + if (read_len % 32 == 31) { + DEBUG_SERIAL.println(); + } + } + DEBUG_SERIAL.println(); +#endif + + endTransactionWithDeassertingCS(); + + return true; +} + +/*! + * @brief Write some data and read some data at the same time from SPI + * into the same buffer, with transaction management. This is basicaly a wrapper + * for transfer() with CS-pin and transaction management. This /does/ + * transmit-receive at the same time! + * @param buffer Pointer to buffer of data to write/read to/from + * @param len Number of bytes from buffer to write/read. + * @return Always returns true because there's no way to test success of SPI + * writes + */ +bool Adafruit_SPIDevice::write_and_read(uint8_t *buffer, size_t len) { + beginTransactionWithAssertingCS(); + transfer(buffer, len); + endTransactionWithDeassertingCS(); + + return true; +} diff --git a/libraries/Adafruit_BusIO/Adafruit_SPIDevice.h b/libraries/Adafruit_BusIO/Adafruit_SPIDevice.h new file mode 100644 index 0000000..d0d5ae11 --- /dev/null +++ b/libraries/Adafruit_BusIO/Adafruit_SPIDevice.h @@ -0,0 +1,148 @@ +#ifndef Adafruit_SPIDevice_h +#define Adafruit_SPIDevice_h + +#include + +#if !defined(SPI_INTERFACES_COUNT) || \ + (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0)) +// HW SPI available +#include +#define BUSIO_HAS_HW_SPI +#else +// SW SPI ONLY +enum { SPI_MODE0, SPI_MODE1, SPI_MODE2, _SPI_MODE4 }; +typedef uint8_t SPIClass; +#endif + +// some modern SPI definitions don't have BitOrder enum +#if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \ + defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) || \ + defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) || \ + defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) || \ + defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \ + defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \ + defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \ + defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32) || \ + defined(ARDUINO_ARCH_XMC) + +typedef enum _BitOrder { + SPI_BITORDER_MSBFIRST = MSBFIRST, + SPI_BITORDER_LSBFIRST = LSBFIRST, +} BusIOBitOrder; + +#elif defined(ESP32) || defined(__ASR6501__) || defined(__ASR6502__) + +// some modern SPI definitions don't have BitOrder enum and have different SPI +// mode defines +typedef enum _BitOrder { + SPI_BITORDER_MSBFIRST = SPI_MSBFIRST, + SPI_BITORDER_LSBFIRST = SPI_LSBFIRST, +} BusIOBitOrder; + +#else +// Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST +#define SPI_BITORDER_MSBFIRST MSBFIRST +#define SPI_BITORDER_LSBFIRST LSBFIRST +typedef BitOrder BusIOBitOrder; +#endif + +#if defined(__IMXRT1062__) // Teensy 4.x +// *Warning* I disabled the usage of FAST_PINIO as the set/clear operations +// used in the cpp file are not atomic and can effect multiple IO pins +// and if an interrupt happens in between the time the code reads the register +// and writes out the updated value, that changes one or more other IO pins +// on that same IO port, those change will be clobbered when the updated +// values are written back. A fast version can be implemented that uses the +// ports set and clear registers which are atomic. +// typedef volatile uint32_t BusIO_PortReg; +// typedef uint32_t BusIO_PortMask; +// #define BUSIO_USE_FAST_PINIO + +#elif defined(__MBED__) || defined(__ZEPHYR__) +// Boards based on RTOS cores like mbed or Zephyr are not going to expose the +// low level registers needed for fast pin manipulation +#undef BUSIO_USE_FAST_PINIO + +#elif defined(ARDUINO_ARCH_XMC) +#undef BUSIO_USE_FAST_PINIO + +#elif defined(__AVR__) || defined(TEENSYDUINO) +typedef volatile uint8_t BusIO_PortReg; +typedef uint8_t BusIO_PortMask; +#define BUSIO_USE_FAST_PINIO + +#elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \ + defined(ARDUINO_ARCH_SAMD) +typedef volatile uint32_t BusIO_PortReg; +typedef uint32_t BusIO_PortMask; +#define BUSIO_USE_FAST_PINIO + +#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \ + !defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_SILABS) && \ + !defined(ARDUINO_UNOR4_MINIMA) && !defined(ARDUINO_UNOR4_WIFI) +typedef volatile uint32_t BusIO_PortReg; +typedef uint32_t BusIO_PortMask; +#if !defined(__ASR6501__) && !defined(__ASR6502__) +#define BUSIO_USE_FAST_PINIO +#endif + +#else +#undef BUSIO_USE_FAST_PINIO +#endif + +/**! The class which defines how we will talk to this device over SPI **/ +class Adafruit_SPIDevice { +public: +#ifdef BUSIO_HAS_HW_SPI + Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000, + BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST, + uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI); +#else + Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000, + BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST, + uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = nullptr); +#endif + Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi, + uint32_t freq = 1000000, + BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST, + uint8_t dataMode = SPI_MODE0); + ~Adafruit_SPIDevice(); + + bool begin(void); + bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF); + bool write(const uint8_t *buffer, size_t len, + 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, + uint8_t sendvalue = 0xFF); + bool write_and_read(uint8_t *buffer, size_t len); + + uint8_t transfer(uint8_t send); + void transfer(uint8_t *buffer, size_t len); + void beginTransaction(void); + void endTransaction(void); + void beginTransactionWithAssertingCS(); + void endTransactionWithDeassertingCS(); + +private: +#ifdef BUSIO_HAS_HW_SPI + SPIClass *_spi = nullptr; + SPISettings *_spiSetting = nullptr; +#else + uint8_t *_spi = nullptr; + uint8_t *_spiSetting = nullptr; +#endif + uint32_t _freq; + BusIOBitOrder _dataOrder; + uint8_t _dataMode; + void setChipSelect(int value); + + int8_t _cs, _sck, _mosi, _miso; +#ifdef BUSIO_USE_FAST_PINIO + BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort; + BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask; +#endif + bool _begun; +}; + +#endif // Adafruit_SPIDevice_h diff --git a/libraries/Adafruit_BusIO/CMakeLists.txt b/libraries/Adafruit_BusIO/CMakeLists.txt new file mode 100644 index 0000000..ff6496c --- /dev/null +++ b/libraries/Adafruit_BusIO/CMakeLists.txt @@ -0,0 +1,11 @@ +# Adafruit Bus IO Library +# https://github.com/adafruit/Adafruit_BusIO +# MIT License + +cmake_minimum_required(VERSION 3.5) + +idf_component_register(SRCS "Adafruit_I2CDevice.cpp" "Adafruit_BusIO_Register.cpp" "Adafruit_SPIDevice.cpp" + INCLUDE_DIRS "." + REQUIRES arduino-esp32) + +project(Adafruit_BusIO) diff --git a/libraries/Adafruit_BusIO/LICENSE b/libraries/Adafruit_BusIO/LICENSE new file mode 100644 index 0000000..860e3e2 --- /dev/null +++ b/libraries/Adafruit_BusIO/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2017 Adafruit Industries + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/libraries/Adafruit_BusIO/README.md b/libraries/Adafruit_BusIO/README.md new file mode 100644 index 0000000..59712ff --- /dev/null +++ b/libraries/Adafruit_BusIO/README.md @@ -0,0 +1,8 @@ +# Adafruit Bus IO Library [![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions) + + +This is a helper library to abstract away I2C, SPI, and 'generic transport' (e.g. UART) transactions and registers + +Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! + +MIT license, all text above must be included in any redistribution diff --git a/libraries/Adafruit_BusIO/component.mk b/libraries/Adafruit_BusIO/component.mk new file mode 100644 index 0000000..049f190 --- /dev/null +++ b/libraries/Adafruit_BusIO/component.mk @@ -0,0 +1 @@ +COMPONENT_ADD_INCLUDEDIRS = . diff --git a/libraries/Adafruit_BusIO/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino b/libraries/Adafruit_BusIO/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino new file mode 100644 index 0000000..59af308 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/genericdevice_uartregtest/genericdevice_uartregtest.ino @@ -0,0 +1,219 @@ +/* + Advanced example of using bstracted transport for reading and writing + register data from a UART-based device such as a TMC2209 + + Written with help by Claude! + https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time + chats are not shareable :( +*/ + +#include "Adafruit_BusIO_Register.h" +#include "Adafruit_GenericDevice.h" + +// Debugging macros +#define DEBUG_SERIAL Serial + +#ifdef DEBUG_SERIAL +#define DEBUG_PRINT(x) DEBUG_SERIAL.print(x) +#define DEBUG_PRINTLN(x) DEBUG_SERIAL.println(x) +#define DEBUG_PRINT_HEX(x) \ + do { \ + if (x < 0x10) \ + DEBUG_SERIAL.print('0'); \ + DEBUG_SERIAL.print(x, HEX); \ + DEBUG_SERIAL.print(' '); \ + } while (0) +#else +#define DEBUG_PRINT(x) +#define DEBUG_PRINTLN(x) +#define DEBUG_PRINT_HEX(x) +#endif + +#define TMC2209_IOIN 0x06 + +class TMC2209_UART { +private: + Stream *_uart_stream; + uint8_t _addr; + + static bool uart_read(void *thiz, uint8_t *buffer, size_t len) { + TMC2209_UART *dev = (TMC2209_UART *)thiz; + uint16_t timeout = 100; + while (dev->_uart_stream->available() < len && timeout--) { + delay(1); + } + if (timeout == 0) { + DEBUG_PRINTLN("Read timeout!"); + return false; + } + + DEBUG_PRINT("Reading: "); + for (size_t i = 0; i < len; i++) { + buffer[i] = dev->_uart_stream->read(); + DEBUG_PRINT_HEX(buffer[i]); + } + DEBUG_PRINTLN(""); + + return true; + } + + static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) { + TMC2209_UART *dev = (TMC2209_UART *)thiz; + DEBUG_PRINT("Writing: "); + for (size_t i = 0; i < len; i++) { + DEBUG_PRINT_HEX(buffer[i]); + } + DEBUG_PRINTLN(""); + + dev->_uart_stream->write(buffer, len); + return true; + } + + static bool uart_readreg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz, + uint8_t *data, uint16_t datalen) { + TMC2209_UART *dev = (TMC2209_UART *)thiz; + while (dev->_uart_stream->available()) + dev->_uart_stream->read(); + + uint8_t packet[4] = {0x05, uint8_t(dev->_addr << 1), addr_buf[0], 0x00}; + + packet[3] = calcCRC(packet, 3); + if (!uart_write(thiz, packet, 4)) + return false; + + // Read back echo + uint8_t echo[4]; + if (!uart_read(thiz, echo, 4)) + return false; + + // Verify echo + for (uint8_t i = 0; i < 4; i++) { + if (echo[i] != packet[i]) { + DEBUG_PRINTLN("Echo mismatch"); + return false; + } + } + + uint8_t response[8]; // sync + 0xFF + reg + 4 data bytes + CRC + if (!uart_read(thiz, response, 8)) + return false; + + // Verify response + if (response[0] != 0x05) { + DEBUG_PRINTLN("Invalid sync byte"); + return false; + } + + if (response[1] != 0xFF) { + DEBUG_PRINTLN("Invalid reply address"); + return false; + } + + if (response[2] != addr_buf[0]) { + DEBUG_PRINTLN("Register mismatch"); + return false; + } + + uint8_t crc = calcCRC(response, 7); + if (crc != response[7]) { + DEBUG_PRINTLN("CRC mismatch"); + return false; + } + + memcpy(data, &response[3], 4); + return true; + } + + static bool uart_writereg(void *thiz, uint8_t *addr_buf, uint8_t addrsiz, + const uint8_t *data, uint16_t datalen) { + TMC2209_UART *dev = (TMC2209_UART *)thiz; + while (dev->_uart_stream->available()) + dev->_uart_stream->read(); + + uint8_t packet[8] = {0x05, + uint8_t(dev->_addr << 1), + uint8_t(addr_buf[0] | 0x80), + data[0], + data[1], + data[2], + data[3], + 0x00}; + + packet[7] = calcCRC(packet, 7); + if (!uart_write(thiz, packet, 8)) + return false; + + uint8_t echo[8]; + if (!uart_read(thiz, echo, 8)) + return false; + + for (uint8_t i = 0; i < 8; i++) { + if (echo[i] != packet[i]) { + DEBUG_PRINTLN("Write echo mismatch"); + return false; + } + } + + return true; + } + + static uint8_t calcCRC(uint8_t *data, uint8_t length) { + uint8_t crc = 0; + for (uint8_t i = 0; i < length; i++) { + uint8_t currentByte = data[i]; + for (uint8_t j = 0; j < 8; j++) { + if ((crc >> 7) ^ (currentByte & 0x01)) { + crc = (crc << 1) ^ 0x07; + } else { + crc = crc << 1; + } + currentByte = currentByte >> 1; + } + } + return crc; + } + +public: + TMC2209_UART(Stream *serial, uint8_t addr) + : _uart_stream(serial), _addr(addr) {} + + Adafruit_GenericDevice *createDevice() { + return new Adafruit_GenericDevice(this, uart_read, uart_write, uart_readreg, + uart_writereg); + } +}; + +void setup() { + Serial.begin(115200); + while (!Serial) + ; + delay(100); + Serial.println("TMC2209 Generic Device register read/write test!"); + + Serial1.begin(115200); + + TMC2209_UART uart(&Serial1, 0); + Adafruit_GenericDevice *device = uart.createDevice(); + device->begin(); + + // Create register object for IOIN + Adafruit_BusIO_Register ioin_reg(device, + TMC2209_IOIN, // device and register address + 4, // width = 4 bytes + MSBFIRST, // byte order + 1); // address width = 1 byte + Serial.print("IOIN = 0x"); + Serial.println(ioin_reg.read(), HEX); + + // Create RegisterBits for VERSION field (bits 31:24) + Adafruit_BusIO_RegisterBits version_bits( + &ioin_reg, 8, 24); // 8 bits wide, starting at bit 24 + + Serial.println("Reading VERSION..."); + uint8_t version = version_bits.read(); + + Serial.print("VERSION = 0x"); + Serial.println(version, HEX); +} + +void loop() { delay(1000); } \ No newline at end of file diff --git a/libraries/Adafruit_BusIO/examples/genericdevice_uarttest/genericdevice_uarttest.ino b/libraries/Adafruit_BusIO/examples/genericdevice_uarttest/genericdevice_uarttest.ino new file mode 100644 index 0000000..6a11dbf --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/genericdevice_uarttest/genericdevice_uarttest.ino @@ -0,0 +1,98 @@ +/* + Abstracted transport for reading and writing data from a UART-based + device such as a TMC2209 + + Written with help by Claude! + https://claude.ai/chat/335f50b1-3dd8-435e-9139-57ec7ca26a3c (at this time + chats are not shareable :( +*/ + +#include "Adafruit_GenericDevice.h" + +/** + * Basic UART device class that demonstrates using GenericDevice with a Stream + * interface. This example shows how to wrap a Stream (like HardwareSerial or + * SoftwareSerial) with read/write callbacks that can be used by BusIO's + * register functions. + */ +class UARTDevice { +public: + UARTDevice(Stream *serial) : _serial(serial) {} + + // Static callback for writing data to UART + // Called by GenericDevice when data needs to be sent + static bool uart_write(void *thiz, const uint8_t *buffer, size_t len) { + UARTDevice *dev = (UARTDevice *)thiz; + dev->_serial->write(buffer, len); + return true; + } + + // Static callback for reading data from UART + // Includes timeout and will return false if not enough data available + static bool uart_read(void *thiz, uint8_t *buffer, size_t len) { + UARTDevice *dev = (UARTDevice *)thiz; + uint16_t timeout = 100; + while (dev->_serial->available() < len && timeout--) { + delay(1); + } + if (timeout == 0) { + return false; + } + for (size_t i = 0; i < len; i++) { + buffer[i] = dev->_serial->read(); + } + return true; + } + + // Create a GenericDevice instance using our callbacks + Adafruit_GenericDevice *createDevice() { + return new Adafruit_GenericDevice(this, uart_read, uart_write); + } + +private: + Stream *_serial; // Underlying Stream instance (HardwareSerial, etc) +}; + +void setup() { + Serial.begin(115200); + while (!Serial) + ; + delay(100); + + Serial.println("Generic Device test!"); + + // Initialize UART for device communication + Serial1.begin(115200); + + // Create UART wrapper and BusIO device + UARTDevice uart(&Serial1); + Adafruit_GenericDevice *device = uart.createDevice(); + device->begin(); + + // Test write/read cycle + uint8_t write_buf[4] = {0x5, 0x0, 0x0, 0x48}; + uint8_t read_buf[8]; + + Serial.println("Writing data..."); + if (!device->write(write_buf, 4)) { + Serial.println("Write failed!"); + return; + } + + Serial.println("Reading response..."); + if (!device->read(read_buf, 8)) { + Serial.println("Read failed!"); + return; + } + + // Print response bytes + Serial.print("Got response: "); + for (int i = 0; i < 8; i++) { + Serial.print("0x"); + Serial.print(read_buf[i], HEX); + Serial.print(" "); + } + Serial.println(); +} + +void loop() { delay(1000); } \ No newline at end of file diff --git a/libraries/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino b/libraries/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino new file mode 100644 index 0000000..f2e6ba7 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino @@ -0,0 +1,22 @@ +#include + +Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(0x10); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("I2C address detection test"); + + if (!i2c_dev.begin()) { + Serial.print("Did not find device at 0x"); + Serial.println(i2c_dev.address(), HEX); + while (1) + ; + } + Serial.print("Device found on address 0x"); + Serial.println(i2c_dev.address(), HEX); +} + +void loop() {} diff --git a/libraries/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino b/libraries/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino new file mode 100644 index 0000000..4ac2626 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino @@ -0,0 +1,45 @@ +#include + +#define I2C_ADDRESS 0x60 +Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("I2C device read and write test"); + + if (!i2c_dev.begin()) { + Serial.print("Did not find device at 0x"); + Serial.println(i2c_dev.address(), HEX); + while (1) + ; + } + Serial.print("Device found on address 0x"); + Serial.println(i2c_dev.address(), HEX); + + uint8_t buffer[32]; + // Try to read 32 bytes + i2c_dev.read(buffer, 32); + Serial.print("Read: "); + for (uint8_t i = 0; i < 32; i++) { + Serial.print("0x"); + Serial.print(buffer[i], HEX); + Serial.print(", "); + } + Serial.println(); + + // read a register by writing first, then reading + buffer[0] = 0x0C; // we'll reuse the same buffer + i2c_dev.write_then_read(buffer, 1, buffer, 2, false); + Serial.print("Write then Read: "); + for (uint8_t i = 0; i < 2; i++) { + Serial.print("0x"); + Serial.print(buffer[i], HEX); + Serial.print(", "); + } + Serial.println(); +} + +void loop() {} diff --git a/libraries/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino b/libraries/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino new file mode 100644 index 0000000..2d44c83 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino @@ -0,0 +1,43 @@ +#include +#include + +#define I2C_ADDRESS 0x60 +Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("I2C device register test"); + + if (!i2c_dev.begin()) { + Serial.print("Did not find device at 0x"); + Serial.println(i2c_dev.address(), HEX); + while (1) + ; + } + Serial.print("Device found on address 0x"); + Serial.println(i2c_dev.address(), HEX); + + Adafruit_BusIO_Register id_reg = + Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST); + uint16_t id; + id_reg.read(&id); + Serial.print("ID register = 0x"); + Serial.println(id, HEX); + + Adafruit_BusIO_Register thresh_reg = + Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST); + uint16_t thresh; + thresh_reg.read(&thresh); + Serial.print("Initial threshold register = 0x"); + Serial.println(thresh, HEX); + + thresh_reg.write(~thresh); + + Serial.print("Post threshold register = 0x"); + Serial.println(thresh_reg.read(), HEX); +} + +void loop() {} \ No newline at end of file diff --git a/libraries/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino b/libraries/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino new file mode 100644 index 0000000..be04606 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino @@ -0,0 +1,40 @@ +#include + +// Define which interface to use by setting the unused interface to NULL! + +#define SPIDEVICE_CS 10 +Adafruit_SPIDevice *spi_dev = NULL; // new Adafruit_SPIDevice(SPIDEVICE_CS); + +#define I2C_ADDRESS 0x5D +Adafruit_I2CDevice *i2c_dev = new Adafruit_I2CDevice(I2C_ADDRESS); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("I2C or SPI device register test"); + + if (spi_dev && !spi_dev->begin()) { + Serial.println("Could not initialize SPI device"); + } + + if (i2c_dev) { + if (i2c_dev->begin()) { + Serial.print("Device found on I2C address 0x"); + Serial.println(i2c_dev->address(), HEX); + } else { + Serial.print("Did not find I2C device at 0x"); + Serial.println(i2c_dev->address(), HEX); + } + } + + Adafruit_BusIO_Register id_reg = + Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F); + uint8_t id = 0; + id_reg.read(&id); + Serial.print("ID register = 0x"); + Serial.println(id, HEX); +} + +void loop() {} diff --git a/libraries/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino b/libraries/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino new file mode 100644 index 0000000..ebf14f9 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino @@ -0,0 +1,35 @@ +#include + +#define SPIDEVICE_CS 10 +Adafruit_SPIDevice spi_dev = + Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1); +// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11, +// 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("SPI device mode test"); + + if (!spi_dev.begin()) { + Serial.println("Could not initialize SPI device"); + while (1) + ; + } +} + +void loop() { + Serial.println("\n\nTransfer test"); + for (uint16_t x = 0; x <= 0xFF; x++) { + uint8_t i = x; + Serial.print("0x"); + Serial.print(i, HEX); + spi_dev.read(&i, 1, i); + Serial.print("/"); + Serial.print(i, HEX); + Serial.print(", "); + delay(25); + } +} \ No newline at end of file diff --git a/libraries/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino b/libraries/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino new file mode 100644 index 0000000..4b9ecf1 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino @@ -0,0 +1,43 @@ +#include + +#define SPIDEVICE_CS 10 +Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("SPI device read and write test"); + + if (!spi_dev.begin()) { + Serial.println("Could not initialize SPI device"); + while (1) + ; + } + + uint8_t buffer[32]; + + // Try to read 32 bytes + spi_dev.read(buffer, 32); + Serial.print("Read: "); + for (uint8_t i = 0; i < 32; i++) { + Serial.print("0x"); + Serial.print(buffer[i], HEX); + Serial.print(", "); + } + Serial.println(); + + // read a register by writing first, then reading + buffer[0] = 0x8F; // we'll reuse the same buffer + spi_dev.write_then_read(buffer, 1, buffer, 2, false); + Serial.print("Write then Read: "); + for (uint8_t i = 0; i < 2; i++) { + Serial.print("0x"); + Serial.print(buffer[i], HEX); + Serial.print(", "); + } + Serial.println(); +} + +void loop() {} diff --git a/libraries/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino b/libraries/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino new file mode 100644 index 0000000..d11b440 --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino @@ -0,0 +1,268 @@ +/*************************************************** + + This is an example for how to use Adafruit_BusIO_RegisterBits from + Adafruit_BusIO library. + + Designed specifically to work with the Adafruit RTD Sensor + ----> https://www.adafruit.com/products/3328 + uisng a MAX31865 RTD-to-Digital Converter + ----> https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf + + This sensor uses SPI to communicate, 4 pins are required to + interface. + A fifth pin helps to detect when a new conversion is ready. + + Adafruit invests time and resources providing this open source code, + please support Adafruit and open-source hardware by purchasing + products from Adafruit! + + Example written (2020/3) by Andreas Hardtung/AnHard. + BSD license, all text above must be included in any redistribution + ****************************************************/ + +#include +#include + +#define MAX31865_SPI_SPEED (5000000) +#define MAX31865_SPI_BITORDER (SPI_BITORDER_MSBFIRST) +#define MAX31865_SPI_MODE (SPI_MODE1) + +#define MAX31865_SPI_CS (10) +#define MAX31865_READY_PIN (2) + +Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( + MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, + MAX31865_SPI_MODE, &SPI); // Hardware SPI +// Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11, +// MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software +// SPI + +// MAX31865 chip related +// ********************************************************************************************* +Adafruit_BusIO_Register config_reg = + Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST); +Adafruit_BusIO_RegisterBits bias_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 7); +Adafruit_BusIO_RegisterBits auto_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 6); +Adafruit_BusIO_RegisterBits oneS_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 5); +Adafruit_BusIO_RegisterBits wire_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 4); +Adafruit_BusIO_RegisterBits faultT_bits = + Adafruit_BusIO_RegisterBits(&config_reg, 2, 2); +Adafruit_BusIO_RegisterBits faultR_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 1); +Adafruit_BusIO_RegisterBits fi50hz_bit = + Adafruit_BusIO_RegisterBits(&config_reg, 1, 0); + +Adafruit_BusIO_Register rRatio_reg = + Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); +Adafruit_BusIO_RegisterBits rRatio_bits = + Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1); +Adafruit_BusIO_RegisterBits fault_bit = + Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0); + +Adafruit_BusIO_Register maxRratio_reg = + Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); +Adafruit_BusIO_RegisterBits maxRratio_bits = + Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1); + +Adafruit_BusIO_Register minRratio_reg = + Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); +Adafruit_BusIO_RegisterBits minRratio_bits = + Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1); + +Adafruit_BusIO_Register fault_reg = + Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST); +Adafruit_BusIO_RegisterBits range_high_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7); +Adafruit_BusIO_RegisterBits range_low_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6); +Adafruit_BusIO_RegisterBits refin_high_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5); +Adafruit_BusIO_RegisterBits refin_low_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4); +Adafruit_BusIO_RegisterBits rtdin_low_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3); +Adafruit_BusIO_RegisterBits voltage_fault_bit = + Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2); + +// Print the details of the configuration register. +void printConfig(void) { + Serial.print("BIAS: "); + if (bias_bit.read()) + Serial.print("ON"); + else + Serial.print("OFF"); + Serial.print(", AUTO: "); + if (auto_bit.read()) + Serial.print("ON"); + else + Serial.print("OFF"); + Serial.print(", ONES: "); + if (oneS_bit.read()) + Serial.print("ON"); + else + Serial.print("OFF"); + Serial.print(", WIRE: "); + if (wire_bit.read()) + Serial.print("3"); + else + Serial.print("2/4"); + Serial.print(", FAULTCLEAR: "); + if (faultR_bit.read()) + Serial.print("ON"); + else + Serial.print("OFF"); + Serial.print(", "); + if (fi50hz_bit.read()) + Serial.print("50HZ"); + else + Serial.print("60HZ"); + Serial.println(); +} + +// Check and print faults. Then clear them. +void checkFaults(void) { + if (fault_bit.read()) { + Serial.print("MAX: "); + Serial.println(maxRratio_bits.read()); + Serial.print("VAL: "); + Serial.println(rRatio_bits.read()); + Serial.print("MIN: "); + Serial.println(minRratio_bits.read()); + + if (range_high_fault_bit.read()) + Serial.println("Range high fault"); + if (range_low_fault_bit.read()) + Serial.println("Range low fault"); + if (refin_high_fault_bit.read()) + Serial.println("REFIN high fault"); + if (refin_low_fault_bit.read()) + Serial.println("REFIN low fault"); + if (rtdin_low_fault_bit.read()) + Serial.println("RTDIN low fault"); + if (voltage_fault_bit.read()) + Serial.println("Voltage fault"); + + faultR_bit.write(1); // clear fault + } +} + +void setup() { +#if (MAX31865_1_READY_PIN != -1) + pinMode(MAX31865_READY_PIN, INPUT_PULLUP); +#endif + + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("SPI Adafruit_BusIO_RegisterBits test on MAX31865"); + + if (!spi_dev.begin()) { + Serial.println("Could not initialize SPI device"); + while (1) + ; + } + + // Set up for automode 50Hz. We don't care about selfheating. We want the + // highest possible sampling rate. + auto_bit.write(0); // Don't switch filtermode while auto_mode is on. + fi50hz_bit.write(1); // Set filter to 50Hz mode. + faultR_bit.write(1); // Clear faults. + bias_bit.write(1); // In automode we want to have the bias current always on. + delay(5); // Wait until bias current settles down. + // 10.5 time constants of the input RC network is required. + // 10ms worst case for 10kω reference resistor and a 0.1µF capacitor + // across the RTD inputs. Adafruit Module has 0.1µF and only + // 430/4300ω So here 0.43/4.3ms + auto_bit.write( + 1); // Now we can set automode. Automatically starting first conversion. + +// Test the READY_PIN +#if (defined(MAX31865_READY_PIN) && (MAX31865_READY_PIN != -1)) + int i = 0; + while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) { + delay(1); + } + if (i >= 100) { + Serial.print("ERROR: Max31865 Pin detection does not work. PIN:"); + Serial.println(MAX31865_READY_PIN); + } +#else + delay(100); +#endif + + // Set ratio range. + // Setting the temperatures would need some more calculation - not related to + // Adafruit_BusIO_RegisterBits. + uint16_t ratio = rRatio_bits.read(); + maxRratio_bits.write((ratio < 0x8fffu - 1000u) ? ratio + 1000u : 0x8fffu); + minRratio_bits.write((ratio > 1000u) ? ratio - 1000u : 0u); + + printConfig(); + checkFaults(); +} + +void loop() { +#if (defined(MAX31865_READY_PIN) && (MAX31865_1_READY_PIN != -1)) + // Is conversion ready? + if (!digitalRead(MAX31865_READY_PIN)) +#else + // Warant conversion is ready. + delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode. +#endif + { + // Read ratio, calculate temperature, scale, filter and print. + Serial.println(rRatio2C(rRatio_bits.read()) * 100.0f, + 0); // Temperature scaled by 100 + // Check, print, clear faults. + checkFaults(); + } + + // Do something else. + // delay(15000); +} + +// Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C +// ***************************** +float rRatio2C(uint16_t ratio) { + // A simple linear conversion. + const float R0 = 100.0f; + const float Rref = 430.0f; + const float alphaPT = 0.003850f; + const float ADCmax = (1u << 15) - 1.0f; + const float rscale = Rref / ADCmax; + // Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0. + // Rref and MAX at about 22±2°C. Measured temperature in ice/water bath 0.76°C + // with factor a = 1 and b = 0. Rref and MAX at about 22±2°C. + // const float a = 1.0f / (alphaPT * R0); + const float a = (100.0f / 101.08f) / (alphaPT * R0); + // const float b = 0.0f; // 101.08 + const float b = -0.76f; // 100.32 > 101.08 + + return filterRing(((ratio * rscale) - R0) * a + b); +} + +// General purpose +// ********************************************************************************************* +#define RINGLENGTH 250 +float filterRing(float newVal) { + static float ring[RINGLENGTH] = {0.0}; + static uint8_t ringIndex = 0; + static bool ringFull = false; + + if (ringIndex == RINGLENGTH) { + ringFull = true; + ringIndex = 0; + } + ring[ringIndex] = newVal; + uint8_t loopEnd = (ringFull) ? RINGLENGTH : ringIndex + 1; + float ringSum = 0.0f; + for (uint8_t i = 0; i < loopEnd; i++) + ringSum += ring[i]; + ringIndex++; + return ringSum / loopEnd; +} diff --git a/libraries/Adafruit_BusIO/examples/spi_registers/spi_registers.ino b/libraries/Adafruit_BusIO/examples/spi_registers/spi_registers.ino new file mode 100644 index 0000000..af6069b --- /dev/null +++ b/libraries/Adafruit_BusIO/examples/spi_registers/spi_registers.ino @@ -0,0 +1,40 @@ +#include +#include + +#define SPIDEVICE_CS 10 +Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS); + +void setup() { + while (!Serial) { + delay(10); + } + Serial.begin(115200); + Serial.println("SPI device register test"); + + if (!spi_dev.begin()) { + Serial.println("Could not initialize SPI device"); + while (1) + ; + } + + Adafruit_BusIO_Register id_reg = + Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD); + uint8_t id = 0; + id_reg.read(&id); + Serial.print("ID register = 0x"); + Serial.println(id, HEX); + + Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register( + &spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST); + uint16_t thresh = 0; + thresh_reg.read(&thresh); + Serial.print("Initial threshold register = 0x"); + Serial.println(thresh, HEX); + + thresh_reg.write(~thresh); + + Serial.print("Post threshold register = 0x"); + Serial.println(thresh_reg.read(), HEX); +} + +void loop() {} diff --git a/libraries/Adafruit_BusIO/library.properties b/libraries/Adafruit_BusIO/library.properties new file mode 100644 index 0000000..bdff9e1 --- /dev/null +++ b/libraries/Adafruit_BusIO/library.properties @@ -0,0 +1,9 @@ +name=Adafruit BusIO +version=1.17.0 +author=Adafruit +maintainer=Adafruit +sentence=This is a library for abstracting away UART, I2C and SPI interfacing +paragraph=This is a library for abstracting away UART, I2C and SPI interfacing +category=Signal Input/Output +url=https://github.com/adafruit/Adafruit_BusIO +architectures=* diff --git a/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h b/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h index 8c6a07d..ad865da 100644 --- a/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h +++ b/libraries/Adafruit_Unified_Sensor/Adafruit_Sensor.h @@ -151,7 +151,7 @@ typedef struct { float tvoc; /**< Total Volatile Organic Compounds, in ppb */ float voc_index; /**< VOC (Volatile Organic Compound) index where 100 is normal (unitless) */ - float nox_index; /**< NOx (Nitrogen Oxides) index where 100 is normal + float nox_index; /**< NOx (Nitrogen Oxides) index where 1 is normal (unitless) */ float CO2; /**< Measured CO2 in parts per million (ppm) */ float eCO2; /**< equivalent/estimated CO2 in parts per million (ppm diff --git a/libraries/Adafruit_Unified_Sensor/library.properties b/libraries/Adafruit_Unified_Sensor/library.properties index ed5a21b..65ffd6e 100644 --- a/libraries/Adafruit_Unified_Sensor/library.properties +++ b/libraries/Adafruit_Unified_Sensor/library.properties @@ -1,5 +1,5 @@ name=Adafruit Unified Sensor -version=1.1.14 +version=1.1.15 author=Adafruit maintainer=Adafruit sentence=Required for all Adafruit Unified Sensor based libraries. diff --git a/libraries/TFT_eSPI/User_Setup.h b/libraries/TFT_eSPI/User_Setup.h index e89547c..9e57279 100644 --- a/libraries/TFT_eSPI/User_Setup.h +++ b/libraries/TFT_eSPI/User_Setup.h @@ -227,7 +227,7 @@ //#define TFT_RST 33 // Reset pin (could connect to Arduino RESET pin) //#define TFT_BL 22 // LED back-light -#define TOUCH_CS 21 // Chip select pin (T_CS) of touch screen +#define TOUCH_CS 4 // Chip select pin (T_CS) of touch screen //#define TFT_WR 22 // Write strobe for modified Raspberry Pi TFT only diff --git a/ui/ui.ino b/ui/ui.ino index 664b03e..5ea20c5 100644 --- a/ui/ui.ino +++ b/ui/ui.ino @@ -7,6 +7,10 @@ #include #include #include "time.h" +#include +#include +#include + TaskHandle_t Task1; Preferences preferences; @@ -14,6 +18,10 @@ Preferences preferences; // #define DHTTYPE DHT11 // DHT 11 // DHT dht(DHTPIN, DHTTYPE); +#define SEALEVELPRESSURE_HPA (1013.25) + +Adafruit_BME280 bme; // I2C + const char* ntp = "fritz.box"; const int gmt_offset_sec = 3600; const int daylight_offset_sec = 7200; @@ -153,7 +161,7 @@ void switchEventHandler(lv_event_t * e) if (lv_obj_has_state(obj, LV_STATE_CHECKED)) { preferences.begin("g_phase", true); - fan_duty_cycle = preferences.getInt(user_data, 310); + fan_duty_cycle = preferences.getInt(user_data, 0); preferences.end(); fan_active = true; @@ -270,7 +278,7 @@ static void dimmUpBtnEventHandler(lv_event_t * e) if (fan_active) { preferences.begin("g_phase", false); - fan_duty_cycle += preferences.getInt(user_data, 76); + fan_duty_cycle += preferences.getInt(user_data, 0); if (fan_duty_cycle >= 1024) fan_duty_cycle = 1024; preferences.putInt(user_data, fan_duty_cycle); preferences.end(); @@ -318,7 +326,7 @@ static void dimmDownBtnEventHandler(lv_event_t * e) { preferences.begin("g_phase", false); fan_duty_cycle += preferences.getInt(user_data); - if (fan_duty_cycle <= 310) fan_duty_cycle = 310; + if (fan_duty_cycle <= 0) fan_duty_cycle = 0; preferences.putInt(user_data, fan_duty_cycle); preferences.end(); dimm(fan_pwm_pin, fan_duty_cycle, ui_lblfanspeed, ui_lblfanfanspeed); @@ -577,6 +585,17 @@ void setup () 0); WiFi.disconnect(); + + // bool status; + + // // default settings + // // (you can also pass in a Wire library object like &Wire2) + // status = bme.begin(0x76); + // if (!status) + // { + // Serial.println("Could not find a valid BME280 sensor, check wiring!"); + // while (1); + // } } void loopC2(void* pvParameters) { @@ -611,6 +630,7 @@ void loop () if (currentMillis - lastUpdate >= updateInterval) { printTime(); + // printValues(); lastUpdate = currentMillis; } @@ -880,8 +900,8 @@ void growMode() Serial.println(&timeinfo, "Testtime: %A, %B %d %Y %H:%M:%S"); Serial.println(&targettime, "Testtime: %A, %B %d %Y %H:%M:%S"); - // if (diff_start < 0 && diff_start > diff_end) - if (diff_start < 0) + if (diff_start < 0 && diff_start > diff_end) + // if (diff_start < 0) { Serial.println("TRUE"); if(sim_sun) @@ -900,7 +920,7 @@ void growMode() else { modeOn(); - targettime.tm_mday += 1; + // targettime.tm_mday += 1; diff_time = getDiffTime(end_h, end_m); updateVeggieMode = (diff_time * 1000) + 1000; } @@ -922,7 +942,10 @@ void growMode() } } else - { + { + + + Serial.println("LIGHTS ARE ON: "); Serial.println(&timeinfo, "Testtime: %A, %B %d %Y %H:%M:%S"); Serial.println(&targettime, "Testtime: %A, %B %d %Y %H:%M:%S"); @@ -987,93 +1010,36 @@ void printTime() +// void printValues() { + +// char hum[20]; +// char temp[20]; +// sprintf(hum, "%.0f%%",bme.readHumidity()); +// sprintf(temp, "%.0f%%",bme.readTemperature()); +// lv_label_set_text(ui_lblhum, hum); +// lv_label_set_text(ui_fanhum, hum); +// lv_label_set_text(ui_lbltemp, temp); +// lv_label_set_text(ui_fantemp, temp); + // Serial.print("Temperature = "); + // Serial.print(); + // Serial.println(" *C"); + // Convert temperature to Fahrenheit + /*Serial.print("Temperature = "); + Serial.print(1.8 * bme.readTemperature() + 32); + Serial.println(" *F");*/ + + // Serial.print("Pressure = "); + // Serial.print(bme.readPressure() / 100.0F); + // Serial.println(" hPa"); + // Serial.print("Approx. Altitude = "); + // Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); + // Serial.println(" m"); + // Serial.print("Humidity = "); + // Serial.print(bme.readHumidity()); + // Serial.println(" %"); - -// if (diff_start < 0 && diff_end < 0 && diff_start < diff_end) -// { -// Serial.println("IF DIFFS KLEINER THEN 0"); -// Serial.println("DIFFSTART IST KLEINER"); -// modeOff(); -// targettime.tm_mday += 1; -// diff_start = getDiffTime(start_h, start_m); -// updateVeggieMode = (diff_start * 1000) + 1000; -// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); -// Serial.println(&targettime, "Targettime: %A, %B %d %Y %H:%M:%S"); -// Serial.println(diff_start); -// Serial.println("###################"); - -// } -// else if (diff_start < 0 && diff_end < 0 && diff_start > diff_end) -// { -// Serial.println("IF DIFFS KLEINER THEN 0"); -// Serial.println("DIFFSTART IST GRÖßER"); -// if(sim_sun) -// { -// diff_time = getDiffTime(end_h, end_m); -// updateVeggieMode = (diff_time * 1000) + 1000; -// lv_obj_add_state(ui_light1switch, LV_STATE_CHECKED); -// lv_obj_add_state(ui_light2switch, LV_STATE_CHECKED); -// sim_duty_cycle = 860; -// turnOn(led1_pwm_pin, sim_duty_cycle, ui_light1statuslbl, ui_lbllightstatus, ui_light1percent); -// turnOn(led2_pwm_pin, sim_duty_cycle, ui_light2statuslbl, ui_lbllightstatus, ui_light2percent); -// sunrise = true; -// updateSimMode = (60 * 60 * 1000) / (sim_duty_cycle - led1); - -// } -// else -// { -// modeOn(); -// } -// targettime.tm_mday += 1; -// diff_end = getDiffTime(end_h, end_m); -// updateVeggieMode = (diff_end *1000) + 1000; -// Serial.println(diff_end); -// Serial.println(&timeinfo, "%A, %B %d %Y %H:%M:%S"); -// Serial.println(&targettime, "Targettime: %A, %B %d %Y %H:%M:%S"); -// Serial.println("###################"); - -// } -// else if (diff_start > 0 && diff_end > 0 && diff_start > diff_end) -// { -// Serial.println("IF DIFFS GRÖßER THEN 0"); -// Serial.println("DIFFSTART IST GRÖßER"); -// Serial.print("DIFF START: "); -// Serial.println(diff_start); -// Serial.print("DIFF END: "); -// Serial.println(diff_end); -// modeOn(); -// updateVeggieMode = (diff_end* 1000) + 1000; -// Serial.println(updateVeggieMode); -// Serial.println("###################"); - -// } -// else if (diff_start > 0 && diff_end > 0 && diff_start < diff_end) -// { -// Serial.println("IF DIFFS GRÖßER THEN 0"); -// Serial.println("DIFFSTART IST KLEINER"); -// Serial.print("DIFF START: "); -// Serial.println(diff_start); -// Serial.print("DIFF END: "); -// Serial.println(diff_end); -// modeOff(); -// updateVeggieMode = (diff_start* 1000) + 1000; -// Serial.println(updateVeggieMode); -// Serial.println("###################"); - -// } - - - -// else -// { - - - - - - - -// } + // Serial.println(); +// }