Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 7 of 7

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

  1. #1
    Junior Member
    Join Date
    Sep 2020
    Posts
    3

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

    Hello,
    Ive 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.
    }

  2. #2
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,601
    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

  3. #3
    Junior Member
    Join Date
    Sep 2020
    Posts
    3
    Thanks for that hint!
    Unfortunately the library dont work with my sensors because they are not "Adafruit" brand.
    So if I start the example sketch the Teensy compile properly but dont show any sensor data afterwards.

  4. #4
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,658
    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...

  5. #5
    Senior Member+ mjs513's Avatar
    Join Date
    Jul 2014
    Location
    New York
    Posts
    5,601
    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.

  6. #6
    Junior Member
    Join Date
    Sep 2020
    Posts
    3
    Quote Originally Posted by KurtE View Post
    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_2xBMP 280_Servo_2xRelay_V21_Plot_Poti_Teensy_09_20\DSC_2 xBMP280_Servo_2xRelay_V21_Plot_Poti_Teensy_09_20.i no: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.
    }

  7. #7
    Senior Member+ KurtE's Avatar
    Join Date
    Jan 2014
    Posts
    7,658
    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);

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •