How to get the BME280 working on the Raspberry Pi Pico with the arduino framework?

I have a WIZnet W5100S-EVB-Pico (which is a raspberry pi pico clone with ethernet). On this board I have connected a BME280 temperature sensor:

  • SDA on pin GP0
  • SCL on pin GP1

I have already all working on ESP32 boards, but I’m now trying to let everything also work on the pi pico.

For this sensor I’m using the Adafruit BME280 library.

On the ESP32 I’m using it like this:

#include <Arduino.h>
#include <Wire.h>
#include <Adafruit_BME280.h>

Adafruit_BME280 bme; // I2C

void setup() {

  Serial.begin(115200); // Start the Serial communication to send messages to the computer

  Wire.begin(32, 33);
  bool status = bme.begin(0x76);  // Initialize the temperature sensor
  if (!status) 
  {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

float readTemperature()
{
  return truncf(bme.readTemperature() * 10) / 10;
}

float readHumidity()
{
  return truncf(bme.readHumidity() * 10) / 10;
}

int readPressure()
{
  return (int)(bme.readPressure() / 100.0F);
}


void loop() {
  //put your main code here, to run repeatedly:

   float temperatuur = readTemperature();
   Serial.println("Temperature = " + String(temperatuur) + " *C");

  float luchtvochtigheid = readHumidity();
  Serial.println("Humidity = " + String(luchtvochtigheid) + " %");

  int luchtdruk = readPressure();
  Serial.println("Pressure = " + String(luchtdruk) + " hPa");
  delay(10000);

}

With the pico board there is no option for setting the SDA and SCL pinnumbers in the Wire object.

What I have found is that you have to do it like this:

#include <Arduino.h>
#include <Wire.h>
#include <SPI.h>
#include <Adafruit_BME280.h>

Adafruit_BME280 bme; // I2C

#define WIRE1_SDA       0
#define WIRE1_SCL       1
arduino::MbedI2C Wire1(WIRE1_SDA, WIRE1_SCL);

void setup() {
   // put your setup code here, to run once:

  Wire1.begin();
  bool status = bme.begin(0x76);  // Initialize the temperature sensor
  if (!status) 
  {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }
}

But the system hangs. Does anybody know what I’m doing wrong?

Platformio.ini:

[env:pico]
platform = raspberrypi
board = pico
framework = arduino
monitor_speed = 115200
lib_deps = adafruit/Adafruit BME280 Library@^2.2.2

Well you’re not connecting the BME library object Adafruit_BME280 bme with your newly created arduino::MbedI2C Wire1 at all, so those are completely separate objects. With

you would at least have to do

  bool status = bme.begin(0x76, &Wire1);  // Initialize the temperature sensor

Yes I had found that also after I had created this ticket.

On my pcb I have 2 x I2C ports exported.

0 and 1
14 and 15.

When I add the temperature sensor to 14 &15 and in combination with the Wire1 member, the sensor is working.

But when I connect it to 0 and 1, it doesn’t work.

When I look on the picture of the microcontroller:

You see that 0 & 1 are on the I2C0 channel and 14 & 15 are on the I2C1 channel.

So I think i should re-assign the correct pins to Wire (the member that already exists). But there is no method for.

Does the I2C scanner when configured for Wire1 show anyhting?

#include <Arduino.h>
#include <Wire.h>

#define WIRE1_SDA       0
#define WIRE1_SCL       1
arduino::MbedI2C Wire1(WIRE1_SDA, WIRE1_SCL);

void setup()
{
  Wire1.begin();
 
  Serial.begin(9600);
  while (!Serial);             // Leonardo: wait for serial monitor
  Serial.println("\nI2C Scanner");
}
 
 
void loop()
{
  byte error, address;
  int nDevices;
 
  Serial.println("Scanning...");
 
  nDevices = 0;
  for(address = 1; address < 127; address++ )
  {
    // The i2c_scanner uses the return value of
    // the Write.endTransmisstion to see if
    // a device did acknowledge to the address.
    Wire1.beginTransmission(address);
    error = Wire1.endTransmission();
 
    if (error == 0)
    {
      Serial.print("I2C device found at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.print(address,HEX);
      Serial.println("  !");
 
      nDevices++;
    }
    else if (error==4)
    {
      Serial.print("Unknown error at address 0x");
      if (address<16)
        Serial.print("0");
      Serial.println(address,HEX);
    }    
  }
  if (nDevices == 0)
    Serial.println("No I2C devices found\n");
  else
    Serial.println("done\n");
 
  delay(5000);           // wait 5 seconds for next scan
}

Yes the I2C scanner showed my sensor.

But I found it. The solution is

#define WIRE1_SDA       0
#define WIRE1_SCL       1
arduino::MbedI2C Wire1(WIRE1_SDA, WIRE1_SCL);

void setup() {
   // put your setup code here, to run once:
  //Wire.begin();
  Wire1.begin();
  bool status = bme.begin(0x76, &Wire1);  // Initialize the temperature sensor
  if (!status) 
  {
    Serial.println("Could not find a valid BME280 sensor, check wiring!");
    while (1);
  }

So the begin method should only be called of Wire1. (When it was called at Wire and Wire1, the system hangs)

With this code, my sensor is giving correct values.

But there are 2 I2C channels on RP2040. On my pcb there will be 2 I2C devices connected.

So for one connection I could create the Wire1.

But when I will use the second one. How could I change the SDA and SCL pins of the Wire member?