Teensy 4.0 - How to use two I2C ports with two BMP280 on same address?

Status
Not open for further replies.

DSC

New member
Hello,
I´ve done a quick project on a Teensy 4.0 with two BMP280 sensors, connected via I2C (SCL0, SDA0 and SCL1, SDA1).
Actually I did not get how to proper initialize the second bus to get valid data from the second sensor because both sensor have the same address (0x76).

ArduinoIDE (1.8.13)
Libraries: <Wire.h>, "cactus_io_BME280_I2C.h", <Servo.h>

Attached please find my code:

Code:
#include <Wire.h>
#include "cactus_io_BME280_I2C.h"
#include <Servo.h>


#define RelayHPin 4                // Relay Pin D4
#define RelayTPin 5                // Relay Pin D5
#define ServoPin 9                 // Servo PWM out D9

int relayH = 4;                      // Relay on Pin D4
int relayT = 5;                      // Relay on Pin D5
int analogPin = A0;                // potentiometer wiper (middle terminal) connected to analog pin 0
                                         // outside leads to ground and +5V
int val = 0;                          // variable to store the value read

Servo mainServo;
int position = 0;
int previousPosition;

// Create BME280 object
BME280_I2C bme1(0x76);       // I2C using address 0x76 // connected to I2C SCL0 Pin 19, SDA0 Pin 18

void setup() {
  
  mainServo.attach(ServoPin);
  pinMode(relayH, OUTPUT);         // Pin for relay module set as OUTPUT
  pinMode(relayT, OUTPUT);         // Pin for relay module set as OUTPUT
  
  Serial.begin(9600);

  Serial.println("Bosch BME280 Pressure - Humidity - Temp Sensor | cactus.io");

  if (!bme1.begin()) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
  }

  bme1.setTempCal(-1);// Temp was reading high so subtract 1 degree

  Serial.println("tHumdity\t\tTemp");
 
}

void loop() {

  // ***************** Potentiometer reading *****************
  // val = analogRead(analogPin);  // read the input pin
  int setpoint = map(analogRead(analogPin), 0, 1024, 0, 50); // mapping from 0-1024 to 0-50

// ****************** BMP280 sensor reading ********************
  bme1.readSensor();

  // ******************* Humidity and Temp values + Offset ****************
    float h1Offset = bme1.getHumidity() + 0.0;     // Humidity Sensor1
    float t1Offset = bme1.getTemperature_C() + 0.0;     // Temperature Sensor1
    
  // ******************* Humidity scale to servo *************

  // This maps humidity to degrees open for the flap + Operator setpoint
   int position = map(h1Offset - setpoint, 30, 100, 60, 20); // mapping flap min - max incl. Poti offset /act 30, 100, 101, 40
   if(previousPosition != position){
     mainServo.write(position); 
  }
    previousPosition = position;

  // Relay ON/OFF by Servo position
   if (position < 55){                 // Relay OFF if Servoposition < setpoint
     digitalWrite(relayH, LOW);         // Relay OFF 
   }    
   else if (position > 65){            // Relay ON if Servoposition > setpoint
     digitalWrite(relayH, HIGH);        // Relay ON
   }
   
  // Relay ON/OFF by Temperature
   if (t1Offset < 27){                   // Relay ON if Temperature bigger
     digitalWrite(relayT, HIGH);         // Relay ON 
   }
   else if (t1Offset > 28){              // Relay OFF if Temperature smaler
     digitalWrite(relayT, LOW);        // Relay OFF
   }


  Serial.print(F("HumSens1: ")); Serial.print(bme1.getHumidity()); Serial.print(" %\t");
  Serial.print(F("TempSens1: ")); Serial.print(bme1.getTemperature_C()); Serial.print(" °C\t");
  Serial.print(F("HumSens1Offset: ")); Serial.print(h1Offset); Serial.print(" %\t");
  Serial.print(F("TempSens1Offset: "));Serial.print(t1Offset); Serial.print(" °C\t");
  Serial.print(F("ServoPos: ")); Serial.print(position); Serial.print(" °\t");
  Serial.print(F("PotiPos: ")); Serial.print(setpoint); Serial.println(" °\t");

// Add a 2 second delay.
delay(100); //just here to slow down the output.
}
 
Just a cursory look at the cactus bme280 library looks like its hardcoded to just use 1 Wire bus. So simple answer is that with the library you are using you can't use 2 BME280's. However, with that said you can check out the Adafruit BME280 library: https://github.com/adafruit/Adafruit_BME280_Library which allows you to use multiple 280's.

Hope that helps
 
Thanks for that hint!
Unfortunately the library don´t work with my sensors because they are not "Adafruit" brand.
So if I start the example sketch the Teensy compile properly but don´t show any sensor data afterwards.
 
Actually then you could probably quick and dirty update the two files associated with that library.

I don't know if I have the version of the library you have, but quick and dirty (edited did not try to compile let alone run)

The Header file:
Code:
/***************************************************************************
 
 cactus.io
  
 This is a library for the BME280 humidity, temperature & pressure sensor. It
 only supports the I2C bus. It does not support the SPI bus connection.
 
 
 ***************************************************************************/

#ifndef __BME280_I2C_H__

#define __BME280_I2C_H__

#include "Arduino.h"

#define BME280_ADDRESS      0x77          // define the default I2C address

// Name of Registers used in the BME280

#define    BME280_DIG_T1_REG   0x88
#define    BME280_DIG_T2_REG   0x8A
#define    BME280_DIG_T3_REG   0x8C
#define    BME280_DIG_P1_REG   0x8E
#define    BME280_DIG_P2_REG   0x90
#define    BME280_DIG_P3_REG   0x92
#define    BME280_DIG_P4_REG   0x94
#define    BME280_DIG_P5_REG   0x96
#define    BME280_DIG_P6_REG   0x98
#define    BME280_DIG_P7_REG   0x9A
#define    BME280_DIG_P8_REG   0x9C
#define    BME280_DIG_P9_REG   0x9E
    
    
#define    BME280_DIG_H1_REG   0xA1
#define    BME280_DIG_H2_REG   0xE1
#define    BME280_DIG_H3_REG   0xE3
#define    BME280_DIG_H4_REG   0xE4
#define    BME280_DIG_H5_REG   0xE5
#define    BME280_DIG_H6_REG   0xE7
    
    
#define    BME280_REGISTER_CHIPID       0xD0
#define    BME280_REGISTER_VERSION      0xD1
#define    BME280_REGISTER_SOFTRESET    0xE0
#define    BME280_REGISTER_CAL26        0xE1
#define    BME280_REGISTER_CONTROLHUMID     0xF2
#define    BME280_REGISTER_CONTROL          0xF4
#define    BME280_REGISTER_CONFIG           0xF5
#define    BME280_REGISTER_PRESSUREDATA     0xF7
#define    BME280_REGISTER_TEMPDATA         0xFA
#define    BME280_REGISTER_HUMIDDATA        0xFD


// structure to hold the calibration data that is programmed into the sensor in the factory
// during manufacture

struct BME280_Calibration_Data
{
    public:
    
        uint16_t dig_T1;
        int16_t  dig_T2;
        int16_t  dig_T3;
    
        uint16_t dig_P1;
        int16_t  dig_P2;
        int16_t  dig_P3;
        int16_t  dig_P4;
        int16_t  dig_P5;
        int16_t  dig_P6;
        int16_t  dig_P7;
        int16_t  dig_P8;
        int16_t  dig_P9;
    
        uint8_t  dig_H1;
        int16_t  dig_H2;
        uint8_t  dig_H3;
        int16_t  dig_H4;
        int16_t  dig_H5;
        int8_t   dig_H6;
    
};

/*=========================================================================

Main Class for the BME280 library

=========================================================================*/


class BME280_I2C

{
    
public:
    
    BME280_I2C(TwoWire *pwire=&Wire);							// uses the default 0x77 address and no cal

    BME280_I2C(uint8_t, *pwire = &Wire);						// use when using 0x76 address
    
    bool  begin(void);
    
	void setTempCal(float);						// we can set a calibration ofsset for the temperature. 
												// this offset is in degrees celsius

    void readSensor(void);                      // read the sensor for data
    
    float getTemperature_C(void);
    float getTemperature_F(void);
    float getHumidity(void);
    float getPressure_HP(void);                 // pressure in hectapascals
    float getPressure_MB(void);                 // pressure in millibars
    
    
private:
    
    BME280_Calibration_Data cal_data;			// holds all of the sensor calibration data
    
    void readTemperature(void);
	void readPressure(void);
    void readHumidity(void);
    void readSensorCoefficients(void);
    
	float    tempcal;							// stores the temp offset calibration
    float    temperature;                       // stores temperature value
    float    humidity;                          // stores humidity value
    float    pressure;                          // stores pressure value
    
    // functions used for sensor communications
    
    // uint8_t spixfer(uint8_t x);
    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;
    int32_t   _sensorID;
    int32_t   t_fine;
    TwoWire   *_pwire;

};

#endif

The .cpp file
Code:
/***************************************************************************
 
 cactus.io
 
 This is a library for the BME280 humidity, temperature & pressure sensor. It
 only supports the I2C bus. It does not support the SPI bus connection.
 
 It supports up to 2 BME280 sensors connected on the I2C bus

 No warranty is given
 
 7/1/18 Bug Fix by Wilhelm  Fixed getTemperature_C and getTemperature_F
 
***************************************************************************/

#include "cactus_io_BME280_I2C.h"

#include <math.h>
#include <Wire.h>

/***************************************************************************
 
 PUBLIC FUNCTIONS
 
 ***************************************************************************/

BME280_I2C::BME280_I2C(TwoWire *pwire) : _pwire(pwire)
{
    _i2caddr = BME280_ADDRESS;

	tempcal = 0.0;
    temperature = 0.0;
    humidity = 0.0;
    pressure = 0.0;
}

BME280_I2C::BME280_I2C(uint8_t addr, TwoWire *pwire) : _pwire(pwire)
{
    _i2caddr = addr;
    tempcal = 0.0;
	tempcal = 0.0;
    temperature = 0.0;
    humidity = 0.0;
}

void BME280_I2C::setTempCal(float tcal)
{
	tempcal = tcal;
}

void BME280_I2C::readSensor(void)
{
    readTemperature();
    readHumidity();
    readPressure();
}

float BME280_I2C::getTemperature_C(void)
{
     return (temperature + tempcal);
}

float BME280_I2C::getTemperature_F(void)
{
    return (temperature + tempcal) * 1.8 + 32;
}

float BME280_I2C::getHumidity(void) {
    return humidity;
}

// Gets the pressure in millibars
float BME280_I2C::getPressure_MB(void) {
    
    return pressure / 100.0F;
}

// Gets the pressure in hectapascals
float BME280_I2C::getPressure_HP(void) {
    
    return pressure;
}

/***************************************************************************
 
 PRIVATE FUNCTIONS
 
 ***************************************************************************/


bool BME280_I2C::begin() {
    
    _pwire->begin();
    
    
    if (read8(BME280_REGISTER_CHIPID) != 0x60)
        
        return false;
    
    readSensorCoefficients();
    
    // Set Humidity oversampling to 1
    write8(BME280_REGISTER_CONTROLHUMID, 0x01); // Set before CONTROL (DS 5.4.3)
    
    write8(BME280_REGISTER_CONTROL, 0x3F);
    
    return true;
    
}

void BME280_I2C::readTemperature(void)
{
    
    int32_t var1, var2;
    
    int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
        
    adc_T >>= 4;
    
    var1  = ((((adc_T>>3) - ((int32_t)cal_data.dig_T1 <<1))) *
             
             ((int32_t)cal_data.dig_T2)) >> 11;
    
    var2  = (((((adc_T>>4) - ((int32_t)cal_data.dig_T1)) *
               
               ((adc_T>>4) - ((int32_t)cal_data.dig_T1))) >> 12) *
             
             ((int32_t)cal_data.dig_T3)) >> 14;
    
    t_fine = var1 + var2;
    
    
    temperature  = (t_fine * 5 + 128) >> 8;
    
    temperature = temperature / 100;
    
}


void BME280_I2C::readPressure(void) {
    
    int64_t var1, var2, p;
    
    int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);    
    adc_P >>= 4;
    
    var1 = ((int64_t)t_fine) - 128000;
    
    var2 = var1 * var1 * (int64_t)cal_data.dig_P6;
    
    var2 = var2 + ((var1*(int64_t)cal_data.dig_P5)<<17);
    
    var2 = var2 + (((int64_t)cal_data.dig_P4)<<35);
    
    var1 = ((var1 * var1 * (int64_t)cal_data.dig_P3)>>8) +
    
    ((var1 * (int64_t)cal_data.dig_P2)<<12);
    
    var1 = (((((int64_t)1)<<47)+var1))*((int64_t)cal_data.dig_P1)>>33;
    
    
    if (var1 == 0) {
        
        // return 0;  // avoid exception caused by division by zero
        pressure = 0.0;
    }
    
    p = 1048576 - adc_P;
    
    p = (((p<<31) - var2)*3125) / var1;
    
    var1 = (((int64_t)cal_data.dig_P9) * (p>>13) * (p>>13)) >> 25;
    
    var2 = (((int64_t)cal_data.dig_P8) * p) >> 19;
    
    
    p = ((p + var1 + var2) >> 8) + (((int64_t)cal_data.dig_P7)<<4);
    
    // return (float)p/256;
    pressure = (float)p/256;
}


void BME280_I2C::readHumidity(void) {
    
    int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
    
    int32_t v_x1_u32r;
    
    v_x1_u32r = (t_fine - ((int32_t)76800));
    
    v_x1_u32r = (((((adc_H << 14) - (((int32_t)cal_data.dig_H4) << 20) -
                    
                    (((int32_t)cal_data.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
                 
                 (((((((v_x1_u32r * ((int32_t)cal_data.dig_H6)) >> 10) *
                      
                      (((v_x1_u32r * ((int32_t)cal_data.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
                    
                    ((int32_t)2097152)) * ((int32_t)cal_data.dig_H2) + 8192) >> 14));
    
    
    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
                               
                               ((int32_t)cal_data.dig_H1)) >> 4));
    
    
    v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
    
    v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
    
    float h = (v_x1_u32r>>12);
    
    // return  h / 1024.0;
    humidity = h / 1024.0;
}


/**************************************************************************

Read the values that are programmed into the sensor during amanufacture

**************************************************************************/

void BME280_I2C::readSensorCoefficients(void)
{
    
    cal_data.dig_T1 = read16_LE(BME280_DIG_T1_REG);
    
    cal_data.dig_T2 = readS16_LE(BME280_DIG_T2_REG);
    
    cal_data.dig_T3 = readS16_LE(BME280_DIG_T3_REG);
    
    cal_data.dig_P1 = read16_LE(BME280_DIG_P1_REG);
    
    cal_data.dig_P2 = readS16_LE(BME280_DIG_P2_REG);
    
    cal_data.dig_P3 = readS16_LE(BME280_DIG_P3_REG);
    
    cal_data.dig_P4 = readS16_LE(BME280_DIG_P4_REG);
    
    cal_data.dig_P5 = readS16_LE(BME280_DIG_P5_REG);
    
    cal_data.dig_P6 = readS16_LE(BME280_DIG_P6_REG);
    
    cal_data.dig_P7 = readS16_LE(BME280_DIG_P7_REG);
    
    cal_data.dig_P8 = readS16_LE(BME280_DIG_P8_REG);
    
    cal_data.dig_P9 = readS16_LE(BME280_DIG_P9_REG);
    
    cal_data.dig_H1 = read8(BME280_DIG_H1_REG);
    
    cal_data.dig_H2 = readS16_LE(BME280_DIG_H2_REG);
    
    cal_data.dig_H3 = read8(BME280_DIG_H3_REG);
    
    cal_data.dig_H4 = (read8(BME280_DIG_H4_REG) << 4) | (read8(BME280_DIG_H4_REG+1) & 0xF);
    
    cal_data.dig_H5 = (read8(BME280_DIG_H5_REG+1) << 4) | (read8(BME280_DIG_H5_REG) >> 4);
    
    cal_data.dig_H6 = (int8_t)read8(BME280_DIG_H6_REG);
    
}



/**************************************************************************

Writes an 8 bit value over I2C

**************************************************************************/

void BME280_I2C::write8(byte reg, byte value)
{
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->write((uint8_t)value);
    
    _pwire->endTransmission();
    
}

/**************************************************************************
 
 Reads a signed 8 bit value over the I2C bus_REG
 
 **************************************************************************/

uint8_t BME280_I2C::read8(byte reg)
{
    
    uint8_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)1);
    
    value = _pwire->read();
    
    return value;
    
}


/**************************************************************************

Reads a signed 16 bit value over the I2C bus_REG

**************************************************************************/

int16_t BME280_I2C::readS16(byte reg)
{
    return (int16_t)read16(reg);
}

int16_t BME280_I2C::readS16_LE(byte reg)
{
    return (int16_t)read16_LE(reg);
}

uint16_t BME280_I2C::read16(byte reg)
{
    
    uint16_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)2);
    
    value = (_pwire->read() << 8) | _pwire->read();
        
    return value;
    
}

uint16_t BME280_I2C::read16_LE(byte reg) {
    
    uint16_t temp = read16(reg);
    
    return (temp >> 8) | (temp << 8);
}

/**************************************************************************

Reads a signed 24 bit value over the I2C bus_REG

**************************************************************************/

uint32_t BME280_I2C::read24(byte reg)
{
    
    uint32_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)3);

    value = _pwire->read();
    
	value <<= 8;

	value |= _pwire->read();

	value <<= 8;

	value |= _pwire->read();
    
    return value;
    
}

The constructor takes an optional parameter of which Wire object to use and defaults to &Wire...

Again not sure but...
 
A couple of things.

First I gave you a link to the BME280, keep getting them backwards. The link to the adafruit lib is: https://github.com/adafruit/Adafruit_BMP280_Library

Second adafruit libraries will work with other than adafruit sensors as long as it supports either SPI or I2C which they all do. Try just attaching one sensor to Wire and running the BMP280test sketch. It should work. A link to your sensor might help. Remember that the Teensy4 is a 3.3v device so make sure your sensor operates at 3.3v.

With the Adadfruit lib you can attach 2 sensors real easy:
Code:
 Adafruit_BMP280 bmp0(Wire)
Adafruit_BMP280 bmp1(Wire1);
thats pretty much all you need to set up which wire bus you need.

EDIT: @KurtE's changes should work as well.
 
Actually then you could probably quick and dirty update the two files associated with that library.

I don't know if I have the version of the library you have, but quick and dirty (edited did not try to compile let alone run)

The Header file:
Code:
/***************************************************************************
 
 cactus.io
  
 This is a library for the BME280 humidity, temperature & pressure sensor. It
 only supports the I2C bus. It does not support the SPI bus connection.
 
 
 ***************************************************************************/

#ifndef __BME280_I2C_H__

#define __BME280_I2C_H__

#include "Arduino.h"

#define BME280_ADDRESS      0x77          // define the default I2C address

// Name of Registers used in the BME280

#define    BME280_DIG_T1_REG   0x88
#define    BME280_DIG_T2_REG   0x8A
#define    BME280_DIG_T3_REG   0x8C
#define    BME280_DIG_P1_REG   0x8E
#define    BME280_DIG_P2_REG   0x90
#define    BME280_DIG_P3_REG   0x92
#define    BME280_DIG_P4_REG   0x94
#define    BME280_DIG_P5_REG   0x96
#define    BME280_DIG_P6_REG   0x98
#define    BME280_DIG_P7_REG   0x9A
#define    BME280_DIG_P8_REG   0x9C
#define    BME280_DIG_P9_REG   0x9E
    
    
#define    BME280_DIG_H1_REG   0xA1
#define    BME280_DIG_H2_REG   0xE1
#define    BME280_DIG_H3_REG   0xE3
#define    BME280_DIG_H4_REG   0xE4
#define    BME280_DIG_H5_REG   0xE5
#define    BME280_DIG_H6_REG   0xE7
    
    
#define    BME280_REGISTER_CHIPID       0xD0
#define    BME280_REGISTER_VERSION      0xD1
#define    BME280_REGISTER_SOFTRESET    0xE0
#define    BME280_REGISTER_CAL26        0xE1
#define    BME280_REGISTER_CONTROLHUMID     0xF2
#define    BME280_REGISTER_CONTROL          0xF4
#define    BME280_REGISTER_CONFIG           0xF5
#define    BME280_REGISTER_PRESSUREDATA     0xF7
#define    BME280_REGISTER_TEMPDATA         0xFA
#define    BME280_REGISTER_HUMIDDATA        0xFD


// structure to hold the calibration data that is programmed into the sensor in the factory
// during manufacture

struct BME280_Calibration_Data
{
    public:
    
        uint16_t dig_T1;
        int16_t  dig_T2;
        int16_t  dig_T3;
    
        uint16_t dig_P1;
        int16_t  dig_P2;
        int16_t  dig_P3;
        int16_t  dig_P4;
        int16_t  dig_P5;
        int16_t  dig_P6;
        int16_t  dig_P7;
        int16_t  dig_P8;
        int16_t  dig_P9;
    
        uint8_t  dig_H1;
        int16_t  dig_H2;
        uint8_t  dig_H3;
        int16_t  dig_H4;
        int16_t  dig_H5;
        int8_t   dig_H6;
    
};

/*=========================================================================

Main Class for the BME280 library

=========================================================================*/


class BME280_I2C

{
    
public:
    
    BME280_I2C(TwoWire *pwire=&Wire);							// uses the default 0x77 address and no cal

    BME280_I2C(uint8_t, *pwire = &Wire);						// use when using 0x76 address
    
    bool  begin(void);
    
	void setTempCal(float);						// we can set a calibration ofsset for the temperature. 
												// this offset is in degrees celsius

    void readSensor(void);                      // read the sensor for data
    
    float getTemperature_C(void);
    float getTemperature_F(void);
    float getHumidity(void);
    float getPressure_HP(void);                 // pressure in hectapascals
    float getPressure_MB(void);                 // pressure in millibars
    
    
private:
    
    BME280_Calibration_Data cal_data;			// holds all of the sensor calibration data
    
    void readTemperature(void);
	void readPressure(void);
    void readHumidity(void);
    void readSensorCoefficients(void);
    
	float    tempcal;							// stores the temp offset calibration
    float    temperature;                       // stores temperature value
    float    humidity;                          // stores humidity value
    float    pressure;                          // stores pressure value
    
    // functions used for sensor communications
    
    // uint8_t spixfer(uint8_t x);
    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;
    int32_t   _sensorID;
    int32_t   t_fine;
    TwoWire   *_pwire;

};

#endif

The .cpp file
Code:
/***************************************************************************
 
 cactus.io
 
 This is a library for the BME280 humidity, temperature & pressure sensor. It
 only supports the I2C bus. It does not support the SPI bus connection.
 
 It supports up to 2 BME280 sensors connected on the I2C bus

 No warranty is given
 
 7/1/18 Bug Fix by Wilhelm  Fixed getTemperature_C and getTemperature_F
 
***************************************************************************/

#include "cactus_io_BME280_I2C.h"

#include <math.h>
#include <Wire.h>

/***************************************************************************
 
 PUBLIC FUNCTIONS
 
 ***************************************************************************/

BME280_I2C::BME280_I2C(TwoWire *pwire) : _pwire(pwire)
{
    _i2caddr = BME280_ADDRESS;

	tempcal = 0.0;
    temperature = 0.0;
    humidity = 0.0;
    pressure = 0.0;
}

BME280_I2C::BME280_I2C(uint8_t addr, TwoWire *pwire) : _pwire(pwire)
{
    _i2caddr = addr;
    tempcal = 0.0;
	tempcal = 0.0;
    temperature = 0.0;
    humidity = 0.0;
}

void BME280_I2C::setTempCal(float tcal)
{
	tempcal = tcal;
}

void BME280_I2C::readSensor(void)
{
    readTemperature();
    readHumidity();
    readPressure();
}

float BME280_I2C::getTemperature_C(void)
{
     return (temperature + tempcal);
}

float BME280_I2C::getTemperature_F(void)
{
    return (temperature + tempcal) * 1.8 + 32;
}

float BME280_I2C::getHumidity(void) {
    return humidity;
}

// Gets the pressure in millibars
float BME280_I2C::getPressure_MB(void) {
    
    return pressure / 100.0F;
}

// Gets the pressure in hectapascals
float BME280_I2C::getPressure_HP(void) {
    
    return pressure;
}

/***************************************************************************
 
 PRIVATE FUNCTIONS
 
 ***************************************************************************/


bool BME280_I2C::begin() {
    
    _pwire->begin();
    
    
    if (read8(BME280_REGISTER_CHIPID) != 0x60)
        
        return false;
    
    readSensorCoefficients();
    
    // Set Humidity oversampling to 1
    write8(BME280_REGISTER_CONTROLHUMID, 0x01); // Set before CONTROL (DS 5.4.3)
    
    write8(BME280_REGISTER_CONTROL, 0x3F);
    
    return true;
    
}

void BME280_I2C::readTemperature(void)
{
    
    int32_t var1, var2;
    
    int32_t adc_T = read24(BME280_REGISTER_TEMPDATA);
        
    adc_T >>= 4;
    
    var1  = ((((adc_T>>3) - ((int32_t)cal_data.dig_T1 <<1))) *
             
             ((int32_t)cal_data.dig_T2)) >> 11;
    
    var2  = (((((adc_T>>4) - ((int32_t)cal_data.dig_T1)) *
               
               ((adc_T>>4) - ((int32_t)cal_data.dig_T1))) >> 12) *
             
             ((int32_t)cal_data.dig_T3)) >> 14;
    
    t_fine = var1 + var2;
    
    
    temperature  = (t_fine * 5 + 128) >> 8;
    
    temperature = temperature / 100;
    
}


void BME280_I2C::readPressure(void) {
    
    int64_t var1, var2, p;
    
    int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA);    
    adc_P >>= 4;
    
    var1 = ((int64_t)t_fine) - 128000;
    
    var2 = var1 * var1 * (int64_t)cal_data.dig_P6;
    
    var2 = var2 + ((var1*(int64_t)cal_data.dig_P5)<<17);
    
    var2 = var2 + (((int64_t)cal_data.dig_P4)<<35);
    
    var1 = ((var1 * var1 * (int64_t)cal_data.dig_P3)>>8) +
    
    ((var1 * (int64_t)cal_data.dig_P2)<<12);
    
    var1 = (((((int64_t)1)<<47)+var1))*((int64_t)cal_data.dig_P1)>>33;
    
    
    if (var1 == 0) {
        
        // return 0;  // avoid exception caused by division by zero
        pressure = 0.0;
    }
    
    p = 1048576 - adc_P;
    
    p = (((p<<31) - var2)*3125) / var1;
    
    var1 = (((int64_t)cal_data.dig_P9) * (p>>13) * (p>>13)) >> 25;
    
    var2 = (((int64_t)cal_data.dig_P8) * p) >> 19;
    
    
    p = ((p + var1 + var2) >> 8) + (((int64_t)cal_data.dig_P7)<<4);
    
    // return (float)p/256;
    pressure = (float)p/256;
}


void BME280_I2C::readHumidity(void) {
    
    int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA);
    
    int32_t v_x1_u32r;
    
    v_x1_u32r = (t_fine - ((int32_t)76800));
    
    v_x1_u32r = (((((adc_H << 14) - (((int32_t)cal_data.dig_H4) << 20) -
                    
                    (((int32_t)cal_data.dig_H5) * v_x1_u32r)) + ((int32_t)16384)) >> 15) *
                 
                 (((((((v_x1_u32r * ((int32_t)cal_data.dig_H6)) >> 10) *
                      
                      (((v_x1_u32r * ((int32_t)cal_data.dig_H3)) >> 11) + ((int32_t)32768))) >> 10) +
                    
                    ((int32_t)2097152)) * ((int32_t)cal_data.dig_H2) + 8192) >> 14));
    
    
    v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) *
                               
                               ((int32_t)cal_data.dig_H1)) >> 4));
    
    
    v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r;
    
    v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r;
    
    float h = (v_x1_u32r>>12);
    
    // return  h / 1024.0;
    humidity = h / 1024.0;
}


/**************************************************************************

Read the values that are programmed into the sensor during amanufacture

**************************************************************************/

void BME280_I2C::readSensorCoefficients(void)
{
    
    cal_data.dig_T1 = read16_LE(BME280_DIG_T1_REG);
    
    cal_data.dig_T2 = readS16_LE(BME280_DIG_T2_REG);
    
    cal_data.dig_T3 = readS16_LE(BME280_DIG_T3_REG);
    
    cal_data.dig_P1 = read16_LE(BME280_DIG_P1_REG);
    
    cal_data.dig_P2 = readS16_LE(BME280_DIG_P2_REG);
    
    cal_data.dig_P3 = readS16_LE(BME280_DIG_P3_REG);
    
    cal_data.dig_P4 = readS16_LE(BME280_DIG_P4_REG);
    
    cal_data.dig_P5 = readS16_LE(BME280_DIG_P5_REG);
    
    cal_data.dig_P6 = readS16_LE(BME280_DIG_P6_REG);
    
    cal_data.dig_P7 = readS16_LE(BME280_DIG_P7_REG);
    
    cal_data.dig_P8 = readS16_LE(BME280_DIG_P8_REG);
    
    cal_data.dig_P9 = readS16_LE(BME280_DIG_P9_REG);
    
    cal_data.dig_H1 = read8(BME280_DIG_H1_REG);
    
    cal_data.dig_H2 = readS16_LE(BME280_DIG_H2_REG);
    
    cal_data.dig_H3 = read8(BME280_DIG_H3_REG);
    
    cal_data.dig_H4 = (read8(BME280_DIG_H4_REG) << 4) | (read8(BME280_DIG_H4_REG+1) & 0xF);
    
    cal_data.dig_H5 = (read8(BME280_DIG_H5_REG+1) << 4) | (read8(BME280_DIG_H5_REG) >> 4);
    
    cal_data.dig_H6 = (int8_t)read8(BME280_DIG_H6_REG);
    
}



/**************************************************************************

Writes an 8 bit value over I2C

**************************************************************************/

void BME280_I2C::write8(byte reg, byte value)
{
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->write((uint8_t)value);
    
    _pwire->endTransmission();
    
}

/**************************************************************************
 
 Reads a signed 8 bit value over the I2C bus_REG
 
 **************************************************************************/

uint8_t BME280_I2C::read8(byte reg)
{
    
    uint8_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)1);
    
    value = _pwire->read();
    
    return value;
    
}


/**************************************************************************

Reads a signed 16 bit value over the I2C bus_REG

**************************************************************************/

int16_t BME280_I2C::readS16(byte reg)
{
    return (int16_t)read16(reg);
}

int16_t BME280_I2C::readS16_LE(byte reg)
{
    return (int16_t)read16_LE(reg);
}

uint16_t BME280_I2C::read16(byte reg)
{
    
    uint16_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)2);
    
    value = (_pwire->read() << 8) | _pwire->read();
        
    return value;
    
}

uint16_t BME280_I2C::read16_LE(byte reg) {
    
    uint16_t temp = read16(reg);
    
    return (temp >> 8) | (temp << 8);
}

/**************************************************************************

Reads a signed 24 bit value over the I2C bus_REG

**************************************************************************/

uint32_t BME280_I2C::read24(byte reg)
{
    
    uint32_t value;
    
    _pwire->beginTransmission((uint8_t)_i2caddr);
    
    _pwire->write((uint8_t)reg);
    
    _pwire->endTransmission();
    
    _pwire->requestFrom((uint8_t)_i2caddr, (byte)3);

    value = _pwire->read();
    
	value <<= 8;

	value |= _pwire->read();

	value <<= 8;

	value |= _pwire->read();
    
    return value;
    
}

The constructor takes an optional parameter of which Wire object to use and defaults to &Wire...




Again not sure but...




So I did the modification on the HEADER and CCP file as supplied by you but still not sure whats wrong!
I now try to adress first one sensor to get back into function but it shows the error

"no matching function for call to 'TwoWire::TwoWire(int)'"
"In file included from C:\Users\Administrator\Documents\Arduino\DSC_2xBMP280_Servo_2xRelay_V21_Plot_Poti_Teensy_09_20\DSC_2xBMP280_Servo_2xRelay_V21_Plot_Poti_Teensy_09_20.ino:14:0:
C:\Users\Administrator\Documents\Arduino\libraries\cactus_io_BME280_I2C/cactus_io_BME280_I2C.h:101:25: error: expected identifier before '*' token
BME280_I2C(uint8_t, *pwire = &Wire); // use when using 0x76 address
^
C:\Users\Administrator\Documents\Arduino\libraries\cactus_io_BME280_I2C/cactus_io_BME280_I2C.h:101:35: error: could not convert '& Wire' from 'TwoWire*' to 'int*'
BME280_I2C(uint8_t, *pwire = &Wire); // use when using 0x76 address
^
DSC_2xBMP280_Servo_2xRelay_V21_Plot_Poti_Teensy_09_20:36: error: no matching function for call to 'TwoWire::TwoWire(int)'
TwoWire Wire = TwoWire(0);
"

So here is my code so fare...

Code:
// Libraries 
// - cactus_io_BME280_I2C.h BMP280 Sensor (I2C)
// - Wire.h
// - Servo

#include <Wire.h>
#include "cactus_io_BME280_I2C.h"
#include <Servo.h>


#define RelayHPin 4                // Relay Pin D4
#define RelayTPin 5                // Relay Pin D5
#define ServoPin 9                 // Servo PWM out D9


int relayH = 4;                    // Relay on Pin D4
int relayT = 5;                    // Relay on Pin D5
int analogPin = A0;                // potentiometer wiper (middle terminal) connected to analog pin 0
                                   // outside leads to ground and +5V
int val = 0;                       // variable to store the value read

Servo mainServo;
int position = 0;
int previousPosition;

TwoWire Wire = TwoWire(0);
//TwoWire Wire1 = TwoWire(1);

// Create BME280 object
BME280_I2C bme1(0x76); // I2C using address 0x76 // connected to I2C SCL0 Pin 19, SDA0 Pin 18
// BME280 bme1(wire, 0x76); // I2C using address 0x76 // connected to I2C SCL0 Pin 19, SDA0 Pin 18
// BME280 bme2(wire1, 0x76); // I2C using address 0x76 // connected to I2C SCL0 Pin 19, SDA0 Pin 18

void setup() {
  
  mainServo.attach(ServoPin);
  pinMode(relayH, OUTPUT);         // Pin for relay module set as OUTPUT
  pinMode(relayT, OUTPUT);         // Pin for relay module set as OUTPUT
  
  Serial.begin(9600);

  Serial.println("Bosch BME280 Pressure - Humidity - Temp Sensor | cactus.io");

  if (!bme1.begin()) {
  Serial.println("Could not find a valid BME280 sensor, check wiring!");
  while (1);
  }

  bme1.setTempCal(-1);// Temp was reading high so subtract 1 degree
  // bme2.setTempCal(-1);// Temp was reading high so subtract 1 degree

  Serial.println("tHumdity\t\tTemp");
 
}

void loop() {

  // ***************** Potentiometer reading *****************
  // val = analogRead(analogPin);  // read the input pin
  int setpoint = map(analogRead(analogPin), 0, 1024, 0, 50); // mapping from 0-1024 to 0-50

// ****************** BMP280 sensor reading ********************
  bme1.readSensor();
// bme2.readSensor();
  // ******************* Humidity and Temp values + Offset ****************
    float h1Offset = bme1.getHumidity() + 0.0;     // Humidity Sensor1
    float t1Offset = bme1.getTemperature_C() + 0.0;     // Temperature Sensor1
    
  // ******************* Humidity scale to servo *************

  // This maps humidity to degrees open for the flap + Operator setpoint
   int position = map(h1Offset - setpoint, 30, 100, 60, 20); // mapping flap min - max incl. Poti offset /act 30, 100, 101, 40
   if(previousPosition != position){
     mainServo.write(position); 
  }
    previousPosition = position;

  // Relay ON/OFF by Servo position
   if (position < 55){                 // Relay OFF if Servoposition < setpoint
     digitalWrite(relayH, LOW);         // Relay OFF 
   }    
   else if (position > 65){            // Relay ON if Servoposition > setpoint
     digitalWrite(relayH, HIGH);        // Relay ON
   }
   
  // Relay ON/OFF by Temperature
   if (t1Offset < 27){                   // Relay ON if Temperature bigger
     digitalWrite(relayT, HIGH);         // Relay ON 
   }
   else if (t1Offset > 28){              // Relay OFF if Temperature smaler
     digitalWrite(relayT, LOW);        // Relay OFF
   }


  Serial.print(F("HumSens1: ")); Serial.print(bme1.getHumidity()); Serial.print(" %\t");
  Serial.print(F("TempSens1: ")); Serial.print(bme1.getTemperature_C()); Serial.print(" °C\t");
  Serial.print(F("HumSens1Offset: ")); Serial.print(h1Offset); Serial.print(" %\t");
  Serial.print(F("TempSens1Offset: "));Serial.print(t1Offset); Serial.print(" °C\t");
  Serial.print(F("ServoPos: ")); Serial.print(position); Serial.print(" °\t");
  Serial.print(F("PotiPos: ")); Serial.print(setpoint); Serial.println(" °\t");

// Add a 2 second delay.
delay(100); //just here to slow down the output.
}
 
The wire parameter is at the end and a pointer, and wire1 should be Wire1 (case sensitive) ... So: BME280 bme2(wire1, 0x76);

Try something like: BME280 bme2(0x76, &Wire1);
 
Status
Not open for further replies.
Back
Top