Photon, adafruit BMP280 sensor Wiring Diagram

Hello there,

New to the community of makers and hardware hackers.

I am currently undertaking the momentous task of automating my self designed modular aeroponic grow system over the summer. I am going to be using an open source IoT framework which is found here Common Garden IoT Framework.

Now on to the fun stuff, I have not been able to find an existing wiring diagram, I hate to admit that I am that visual, but it very much helps in understanding and learning for me.

Just for reference I am using this code as a test to get sensor values. Github BMP280

###Wiring Diagram

1 Like

If you are using SPI - which I gather from your use of A4 & A5 - you seem to be missing the connections on A2 & A3
As the comment in the code would suggest

// #define BMP_CS A2
// #define BMP_SCK A3
// #define BMP_MISO A4
// #define BMP_MOSI A5 

On the other hand, if you want to go for I2C, you should use D0/D1.

Since you are using the Shield Shield you can also try way to wire the sensor

@Cloud, there is already a web IDE library for the BMP280. I also suspect that the shield shield is not needed but I’ll need to look at the Adafruit module to confirm.

Nope, Shield Shield is not needed.

Good to know its not (in regards to needing the shield-shield), I am just teaching myself the hard way I guess! Good old diagram of pin remapping.

Are the D0/D1 interchangeable on the shield-shield remapping? So I can use either in their respective corners?

Also if I wanted to change the pinout would I need to change it in the BMP280 library itself?

Thanks for your patience answering these when you get to them, help me keep my sanity.

I will also give it a shot with the added A2 and A3 connections as reccomended in , and go directly from the particle’s risers on the side of the photon on the shield.

One clarification, I don’t need any resistors in any of the data lines or clock feed?

I'd say you could use either of the three locations where you find D0/D1 on the shied. I think the main difference betweene the locations is if there is level translation performed on these or not.

Nope - I2C is I2C no matter which set of pins you'd be using for it.

If you want to use SPI (A2~A5 - which are also on the shield headers - look at the Particle pin names on the bottom of the shield) you'd need to use the respective constructor in code.
But if you don't need the shield don't use it.

You don't need them for this sensor board as it brings its own pull-ups.

One item that may help with the connections is a screw terminal board like https://www.controleverything.com/content/I2C-Master?sku=PESCREW it is made for the Particle Electron but will also take the Photon and makes it easy to connect you module. They also have some particle code that may help you.

Adafruit is a good source of code and tutorials (as well as Photons and things that work with Particle boards).

So I finally got it to work, I am posting a Fritzing Diagram of it might as well, and the code I got to work in an edit shortly.

Edit: Here is link to Fritzing http://fritzing.org/projects/photon-bmp-280 and the code used is:

// Distributed with a free-will license.
// Use it any way you want, profit or free, provided it fits in the licenses of its associated works.
// BME280
// This code is designed to work with the BME280_I2CS I2C Mini Module available from ControlEverything.com.
// https://www.controleverything.com/content/Humidity?sku=BME280_I2CS#tabs-0-product_tabset-2

#include "application.h"
#include "math.h" 

// BME280 I2C address is 0x76(108)
#define Addr 0x76

double cTemp = 0, fTemp = 0, pressure = 0, humidity = 0;
void setup() 
{
    // Set variable
    Particle.variable("i2cdevice", "BME280");
    Particle.variable("cTemp", cTemp);
    Particle.variable("fTemp", fTemp);
    Particle.variable("pressure", pressure);
    Particle.variable("humidity", humidity);
    
    // Initialise I2C communication as MASTER
    Wire.begin();
    // Initialise Serial communication, set baud rate = 9600
    Serial.begin(9600);
    delay(300);
}

void loop()
{
    unsigned int b1[24];
    unsigned int data[8];
    int dig_H1 = 0;
    for(int i = 0; i < 24; i++)
    {
        // Start I2C Transmission
        Wire.beginTransmission(Addr);
        // Select data register
        Wire.write((136+i));
        // Stop I2C Transmission
        Wire.endTransmission();
        
        // Request 1 byte of data
        Wire.requestFrom(Addr, 1);
        
        // Read 24 bytes of data
        if(Wire.available() == 1)
        {
        b1[i] = Wire.read();
        }
    }
    
    // Convert the data
    // temp coefficents
    int dig_T1 = (b1[0] & 0xff) + ((b1[1] & 0xff) * 256);
    int dig_T2 = b1[2] + (b1[3] * 256);
    int dig_T3 = b1[4] + (b1[5] * 256);
    
    // pressure coefficents
    int dig_P1 = (b1[6] & 0xff) + ((b1[7] & 0xff ) * 256);
    int dig_P2 = b1[8] + (b1[9] * 256);
    int dig_P3 = b1[10] + (b1[11] * 256);
    int dig_P4 = b1[12] + (b1[13] * 256);
    int dig_P5 = b1[14] + (b1[15] * 256);
    int dig_P6 = b1[16] + (b1[17] * 256);
    int dig_P7 = b1[18] + (b1[19] * 256);
    int dig_P8 = b1[20] + (b1[21] * 256);
    int dig_P9 = b1[22] + (b1[23] * 256);
    
    for(int i = 0; i < 7; i++)
    {
        // Start I2C Transmission
        Wire.beginTransmission(Addr);
        // Select data register
        Wire.write((225+i));
        // Stop I2C Transmission
        Wire.endTransmission();
        
        // Request 1 byte of data
        Wire.requestFrom(Addr, 1);
        
        // Read 7 bytes of data
        if(Wire.available() == 1)
        {
            b1[i] = Wire.read();
        }
    }
    
    // Convert the data
    // humidity coefficents
    int dig_H2 = b1[0] + (b1[1] * 256);
    int dig_H3 = b1[2] & 0xFF ;
    int dig_H4 = (b1[3] * 16) + (b1[4] & 0xF);
    int dig_H5 = (b1[4] / 16) + (b1[5] * 16);
    int dig_H6 = b1[6];
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select data register
    Wire.write(161);
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Request 1 byte of data
    Wire.requestFrom(Addr, 1);
    
    // Read 1 byte of data
    if(Wire.available() == 1)
    {
        dig_H1 = Wire.read();
    }
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select control humidity register
    Wire.write(0xF2);
    // Humidity over sampling rate = 1
    Wire.write(0x01);
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select control measurement register
    Wire.write(0xF4);
    // Normal mode, temp and pressure over sampling rate = 1
    Wire.write(0x27);
    // Stop I2C Transmission
    Wire.endTransmission();
    
    // Start I2C Transmission
    Wire.beginTransmission(Addr);
    // Select config register
    Wire.write(0xF5);
    // Stand_by time = 1000ms
    Wire.write(0xA0);
    // Stop I2C Transmission
    Wire.endTransmission();
    
    for(int i = 0; i < 8; i++)
    {
        // Start I2C Transmission
        Wire.beginTransmission(Addr);
        // Select data register
        Wire.write((247+i));
        // Stop I2C Transmission
        Wire.endTransmission();
        
        // Request 1 byte of data
        Wire.requestFrom(Addr, 1);
        
        // Read 8 bytes of data
        if(Wire.available() == 1)
        {
            data[i] = Wire.read();
        }   
    }
    
    // Convert pressure and temperature data to 19-bits
    long adc_p = (((long)(data[0] & 0xFF) * 65536) + ((long)(data[1] & 0xFF) * 256) + (long)(data[2] & 0xF0)) / 16;
    long adc_t = (((long)(data[3] & 0xFF) * 65536) + ((long)(data[4] & 0xFF) * 256) + (long)(data[5] & 0xF0)) / 16;
    // Convert the humidity data
    long adc_h = ((long)(data[6] & 0xFF) * 256 + (long)(data[7] & 0xFF));
    
    // Temperature offset calculations
    double var1 = (((double)adc_t) / 16384.0 - ((double)dig_T1) / 1024.0) * ((double)dig_T2);
    double var2 = ((((double)adc_t) / 131072.0 - ((double)dig_T1) / 8192.0) *
    (((double)adc_t)/131072.0 - ((double)dig_T1)/8192.0)) * ((double)dig_T3);
    double t_fine = (long)(var1 + var2);
    double cTemp = (var1 + var2) / 5120.0;
    double fTemp = cTemp * 1.8 + 32;
    
    // Pressure offset calculations
    var1 = ((double)t_fine / 2.0) - 64000.0;
    var2 = var1 * var1 * ((double)dig_P6) / 32768.0;
    var2 = var2 + var1 * ((double)dig_P5) * 2.0;
    var2 = (var2 / 4.0) + (((double)dig_P4) * 65536.0);
    var1 = (((double) dig_P3) * var1 * var1 / 524288.0 + ((double) dig_P2) * var1) / 524288.0;
    var1 = (1.0 + var1 / 32768.0) * ((double)dig_P1);
    double p = 1048576.0 - (double)adc_p;
    p = (p - (var2 / 4096.0)) * 6250.0 / var1;
    var1 = ((double) dig_P9) * p * p / 2147483648.0;
    var2 = p * ((double) dig_P8) / 32768.0;
    double pressure = (p + (var1 + var2 + ((double)dig_P7)) / 16.0) / 100 ;
    
    // Humidity offset calculations
    double var_H = (((double)t_fine) - 76800.0);
    var_H = (adc_h - (dig_H4 * 64.0 + dig_H5 / 16384.0 * var_H)) * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * var_H * (1.0 + dig_H3 / 67108864.0 * var_H))); 
    double humidity = var_H * (1.0 -  dig_H1 * var_H / 524288.0);
    if(humidity > 100.0)
    {
        humidity = 100.0;
    }
    else if(humidity < 0.0) 
    {
        humidity = 0.0;
    }
    
    // Output data to dashboard
    Particle.publish("Temperature in Celsius : ", String(cTemp));
    Particle.publish("Temperature in Fahrenheit : ", String(fTemp));
    Particle.publish("Pressure : ", String(pressure));
    Particle.publish("Relative Humidity : ", String(humidity));
    delay(1000);
}

I actually see data being streamed in the logs, but none of it is correct. I see some of it like

//Temperature offset calculations

Are these even needed? Mind you I found this code somewhere referencing the photon, it was buried wherever it was.

1 Like

I can't see your Fritzing image at that link

And have you not considered @peekay123 already said

https://build.particle.io/libs/567ef1d0fa156c453900069f/tab/Adafruit_BMP280.cpp

Yes I have tried this library not touching any wire from how I have it

Photon >>> BMP280

D0 >>> SDI
D1 >>> SCK
GND >>> GND
3V >>> VIN

I get the error

could not find Valid BMP280 sensor, check wiring!

In my logs instead of the incorrect data from the previous firmware.

Looking more closely at the picture at the beginning, you have an SPI version of the BMP280.
SDI (SPI Data In) connects to MOSI (Master Out Slave In) A5 on Photon
SDO (SPI Data Out) connects to MISO (Master In Slave Out) A4
SCK connects to SCK (Serial Clock) on A3
CS (Chip Select) connects to SS (Slave Select) on A2

EDIT: Actually, that board can be either, and in I2C mode:
SCK connects to SCL (I2C Clock) on D1
SDI connects to SDA (I2C Data) on D0

Back of chip says SPI or i2c Vin logic 3-5V.

If anyone wants, I can send them an extra one I have if it would help figure it out.

The thing that’s odd in that lib is that it uses a different address

/*=========================================================================
    I2C ADDRESS/BITS
    -----------------------------------------------------------------------*/
    #define BMP280_ADDRESS                (0x77)
/*=========================================================================*/

(that’s also the address in the Adafruit original lib)

where you got 0x76, so either redefine BMP280_ADDRESS or pull in the library files as project tabs and alter the address there.

Sorry it didnt upload the photo I guess, here it is again.

Wiring Diagram

I did notice that you ask about the BMP280 and the code uses BME280 they are similar, but I would have to check that the address is the same for both chips.

Also the particle.publish will allow the 4 publishes in one second, but may make you wait before you send another four. I normally put delay(1000) between each publish. I am still new to the photons and particle in general but that is what I read and after I did that I stopped having problems publishing my information.
Chuck

I think what @ScruffR said is on point, I did check the address with a serial scan and its a 00x76 address, the library defined it as 00x77. Will give it another go this AM.

That's correct. After a burst publish of four events you'd have to wait at least for seconds for the limit to lift.
But the better solution might be to incorporate all your data into one publish
e.g. like this

    Particle.publish("EnvironmentData", String::format("Temp: %.1f °C / %.1f °F, Pressure %.1f mbar, Humidity %.1f %%", cTemp, fTemp, pressure, humidity), PRIVATE);

OK, I got a case of what am I doing wrong, I can NOT import a library to particle build no MATTER how I have tried to modify it.

Originally it was only telling me I was missing data fields in README.md

Now it is telling me nothing is even there?

Also is it not just as trivial as renaming core files and their includes?

I actually kind of gave up on the particle dashboard and using it from these struggles, I plugged in my Arduino UNO and INSTANTLY had a BMP280 working, connected a wifi serial device and INSTANTLY had it talking with my raspberry pi!

I don’t think you can use 1.0.4b as version number in spark.json

Cloud,

This may not help, but it has caused me problems in the past.

  1. With some of the Adafruit libraries I have to put include /Adafruit/Adafruit_BMP280_Library (add an extra /Adafruit) for the code to compile correctly.
  2. When using the dashboard and a few other things like Mobicle.io, they don’t always play well with internet explorer (sometimes it does play at all), when in doubt always try chrome. My default is still IE only because that is what I have to use for work.
  3. Mobicle I believe will work with any particle board (photon or electron) and shows the variables, allows function calls and installs buttons. It works on windows, apple IOS, and Android.

I hope it helps.