Using both I2C channels on RP2350

The Raspberry Pi Pico series has 2 independent I2C channels. Which is great because I want to run 2x separate AHT21 temperature & humidity sensors to my board without using a multiplexer. (To be clear, I also can't quite grasp how to do this with a multiplexer either, because I will run into all of the same problems below). I'm using the Adafruit_AHTX0 library to connect & query the sensors. Also, I couldn't get my hands on a Pico 2W yet, so I'm using the Pimoroni Pico Plus 2 until the RPi Pico 2W arrives - just to be totally clear about the HW setup.

The biggest issue I'm having is using the second AHT21 on I2C-1.

So, everything works fine with a single sensor (AHT21 on I2C-0 - I'll call this "AHT21-0"). The major issue was that I needed to find the default pins used for I2C, in this case GPIO4 for SDA-0 & GPIO5 for SCL-0. I was able to try all of the pins combos using the I2C_Scan example from the Adafruit Testbed library. When I finally got a combo that registered, we were golden. After that, the adafruit_aht_test example worked flawlessly & I was able to adapt the code into my own sketch. (Hopefully this all helps some newcomer to the RP2350 & I2C scene - there is not a lot of info out there yet to help with these peculiarities).

OUTPUT OF I2C_Scan:

Default port (Wire) I2C scan: 0x38,
Secondary port (Wire1) I2C scan:,

OUTPUT OF adafruit_aht_test:

Temperature: 18.69 degrees C
Humidity: 55.66% rH

Great! So, now I repeat the process all all of the combos of I2C-1 pins. & I discover that for I2C-1, GPIO6 is used for SDA-1 & GPIO7 for SCL-1. Great! It's all recognized as the "Secondary port"

OUTPUT OF I2C_Scan:

Default port (Wire) I2C scan:,
Secondary port (Wire1) I2C scan: 0x38

The problem is that when I now try to use adafruit_aht_test, it doesn't recognize / find the sensor.

OUTPUT OF adafruit_aht_test:

Nothing.

Getting my sensor to work on I2C-1 is the first problem. Once I do get it working, I'll also need to figure out how to query them separately, or switch between them... But I figure it I can get it working on I2C-1, then that might actually answer the second question. The fact that I can connect to both simultaneously using the I2C_Scan sketch s promising.

OUTPUT OF I2C_Scan (with 2x AHT21 sensors connected):

Default port (Wire) I2C scan: 0x38,
Secondary port (Wire1) I2C scan: 0x38,

I'm not a comms expert, and I'd rather not build my own libraries, header files, etc - I'd love to use the existing libraries as is so that I can benefit from updates, don't need to maintain them, others are much smarter than me, etc. So, I'd REALLY like to avoid writing my own AHT21 parser / comms program.

Any help would be GREATLY appreciated! Thank you all SOOOO MUCH.

All of my code (currently comparing many different temp sensors - very hacky exploration-mode code before I tighten it up) is below:

#include "DHT.h"
#define DHT11PIN 15
DHT dht(DHT11PIN, DHT11);

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht0;
//Adafruit_AHTX0 aht1;  // Trying to follow https://forum.arduino.cc/t/connecting-two-aht21b-sensors-to-i2c-and-serial-printing-it/1252379/6

int led = 25;         // the PWM pin the LED is attached to
int brightness = 0;  // how bright the LED is
int fadeAmount = 5;  // how many points to fade the LED by

// Temp Voltage Divider
float Vmax = 3.3;
int ADC_steps = 1024;
float R0 = 82;
float RT = 0;
uint16_t A0_raw = 0;
uint16_t A1_raw = 0;
float T0 = 0;
float T1 = 0;
//float V_A0 = 0;

void setup() {
  Serial.begin(115200);
  pinMode(led, OUTPUT);
  pinMode(23, OUTPUT);
  digitalWrite(23, 1);
  
  if (! aht.begin()) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT10 or AHT20 found");
  //delay(500);
}

void loop() {
  //Serial.printf("Core temperature: %2.1fC\n", analogReadTemp());
  
  // LM335Z Temp Sensor
    A0_raw = analogRead(A0);
    Serial.print(String(A0_raw) + " raw A0, ");
    T0 = (float)A0_raw * (3300/1024) / 10 - 273 + 17;  // +17ÂșC to match temps
    Serial.print(String(T0) + "ÂșC T0, ");
      /*
      //Serial.print(String(A0_raw) + ",");
      //V_A0 = A0_raw * Vmax/ADC_steps;
      //Serial.print(String(V_A0) + ",");
      //RT = R0*V_A0/(Vmax-V_A0);
      //Serial.print(String(RT) + ",");
      //T = 30 + (RT - 100)*10/2.168;
      */
  
  //
  // DF Robotics LM53 Temp Sensor
    A1_raw = analogRead(A1);
    Serial.print(String(A1_raw) + " raw A1, ");
    T1 = A1_raw * 5 / 10.24 - 15;  // -15ÂșC to match temps
    Serial.print(String(T1) + "ÂșC T1, ");
  //
  //DHT11 Temp Sensor
    float t = dht.readTemperature();
    float h = dht.readHumidity();
    Serial.print(t, 0);
    Serial.print("ÂșC DHT11, ");
    Serial.print(h, 0);
    Serial.print("% RH DHT11, ");
  //
  // AHT21 Temp Sensor  
    sensors_event_t humidity, temp;
    aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
    Serial.print(String(temp.temperature) + "ÂșC AHT21, "); 
    Serial.print(String(humidity.relative_humidity) + "% RH AHT21, ");
  //
  // Built-in RP2350 CPU Temp
    Serial.print(String(analogReadTemp()) + "ÂșC CPU");
  //  
  // set the brightness of built-in LED:    
    brightness = abs((long)(millis()/5) % 512 - 256);
    analogWrite(led, brightness);
    // Old brightness code
      /* 
      // change the brightness for next time through the loop:
      //brightness = brightness + fadeAmount;
      reverse the direction of the fading at the ends of the fade:
      //if (brightness <= 0 || brightness >= 100) {
      //  fadeAmount = -fadeAmount;
      //}
      // wait for 30 milliseconds to see the dimming effect
      */
  //
  Serial.println();
  delay(100);
}

You need to create 2 DHT objects, the one you have called dht and a second one call it dht2

1 Like

when connecting a BME280 to I2C0 (GPIO pins 4 and 5) and a MPU6050 to I2C1 I used following to setup the MPU6050 Wire1 to use GPIO pins 18 and 19

#define SDA 18
#define SCL 19

Adafruit_MPU6050 mpu;

void setup(void) {
  Serial.begin(115200);
  Serial.println("\n\nAdafruit MPU6050/BME280 test!");
  Wire1.setSDA(SDA);  // setup SDA and SCL pins
  Wire1.setSCL(SCL);
  Wire1.begin();

  // Try to initialize!
  if (!mpu.begin(0x68, &Wire1, 0)) {

as you can see a reference to Wire1 to passed mpu.begin()
you can probably implement a similar call for the AHT21

1 Like

You need to create 2 DHT objects, the one you have called dht and a second one call it dht2

Thanks so much @sonofcy & @horace. Yes, I think this is exactly what I need to do (but for the AHT, since I won't be using the DHT). Let me clean up my code focus on the problem at hand... thanks for your patience. Here is the part I am trying to figure out in particular:

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht;

void setup() {
  Serial.begin(115200);
  
  if (! aht.begin()) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT10 or AHT20 found");
}

void loop() {
  // AHT21 Temp Sensor  
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  Serial.print(String(temp.temperature) + "ÂșC AHT21, "); 
  Serial.print(String(humidity.relative_humidity) + "% RH AHT21, ");
  
  // Built-in RP2350 CPU Temp
  Serial.print(String(analogReadTemp()) + "ÂșC CPU");

  Serial.println();
  delay(100);
}

I've seen some examples of this, & I think I can do it by doubling up & differentiating all of the AHT commands like this (similar to what @horace showed...):

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht0;
Adafruit_AHTX0 aht1;  // Trying to follow https://forum.arduino.cc/t/connecting-two-aht21b-sensors-to-i2c-and-serial-printing-it/1252379/6

void setup() {
  Serial.begin(115200);
  
  // Setup AHT21-0 on I2C-0
  if (! aht0.begin()) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHTXX found");

  // Setup AHT21-1 on I2C-1
  if (! aht1.begin()) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT1XX found");
}

void loop() {
  // AHT21 Temp Sensors

  // Get data from AHT21-0 on I2C-0 
  sensors_event_t humidity0, temp0;
  aht0.getEvent(&humidity0, &temp0);// populate temp and humidity objects with fresh data
  Serial.print(String(temp0.temperature) + "ÂșC AHT21, "); 
  Serial.print(String(humidity0.relative_humidity) + "% RH AHT21, ");
  
  // Get data from AHT21-0 on I2C-0 
  sensors_event_t humidity1, temp1;
  aht1.getEvent(&humidity1, &temp1);// populate temp and humidity objects with fresh data
  Serial.print(String(temp1.temperature) + "ÂșC AHT21, "); 
  Serial.print(String(humidity1.relative_humidity) + "% RH AHT21, ");

  // Built-in RP2350 CPU Temp
  Serial.print(String(analogReadTemp()) + "ÂșC CPU");

  Serial.println();
  delay(100);
}

There is no way for this to work as far as I can tell because I don't have any way to discern between I2C-0 & I2C-1 buses in the first place. Both in connection mapping aht1 to I2C-1 or in pulling data with sensors_event_t...

A good evidence of my real issue (the 1st hurdle, anyway) is that even with only 1x AHT21 sensor connected to the I2C-1 bus (GPIO6 & GPIO7 & recognized in I2C_Scan as the Secondary port), I can't get adaftuit_aht_test to work. Any ideas would be super helpful.

Again, I don't really want to write my own comms protocol, I want to use libraries if possible, so I think communicating explicitly by Wire might be non-ideal... but I'll take it if there is no other way. Thanks again so much for your immediate & useful help.

Here are some clues. I don't know what sensor_id is, and I assume you will also need 2 wires?, but the 3rd argument to aht1.begin must surely be AHTX0_I2CADDR_ALTERNATE


1 Like

Ahhhh, this is super helpful @sonofcy. In the 1st post the I2C_Scan example shows the address of both, which is the same (0x38). I actually didn't know the tool-tips could be that useful. I didn't know the arguments, so this opens up a whole world of exploration. This is exactly the type of tip I needed. I'll chase this down & update for posterity.

Thank you so much! Prompt replies mean EVERYTHING. Can't thank you enough!

Mark my post as Solved.

I didn't mention that the second screen grab is a 'goto definition' on the .h file. It adds it to the IDE and you can look at the contents (write protected) which was the clue that two can be handled. Then the tool tip sealed the deal.

1 Like

This is actually a solution to use 2 sensors with alternate I2C addresses on the same I2C bus, I'm trying to figure out how to use the 2 separate buses in parallel with the same sensor (not sure if I can use the same address, but I think so). But this is a good solution for now if I can get it to work. I'll try a few things, then post back the code if I can get it to work...

So far this also showed me the tooltip which hinted to the arguments you can pass to aht.begin(). That let me solve my 1st issue - I can connect to & stream data from the sensor on the I2C-1 bus now! I just needed to add the &Wire1 argument to aht.begin().

image

Streaming from I2C-1 code below. I'll try to combine the 2 next.

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht;

void setup() {
  Serial.begin(115200);
  
  if (! aht.begin(&Wire1)) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT10 or AHT20 found");
}

void loop() {
  // AHT21 Temp Sensor  
  sensors_event_t humidity, temp;
  aht.getEvent(&humidity, &temp);// populate temp and humidity objects with fresh data
  Serial.print(String(temp.temperature) + "ÂșC AHT21, "); 
  Serial.print(String(humidity.relative_humidity) + "% RH AHT21, ");
  
  // Built-in RP2350 CPU Temp
  Serial.print(String(analogReadTemp()) + "ÂșC CPU");

  Serial.println();
  delay(100);
}

Okay, well shoot. This just totally worked without any issues. It was too easy that I'm worried, mostly because I have no idea how sensors_event_t works & I used the same command for both AHT21-0 & AHT21-1. But the data is streaming away perfectly. I have the AHT21-0 sensor in an ice cup (inside a ziploc).

OUTPUT:

8.47ÂșC AHT21-0, 58.80% RH AHT21-0, 19.68ÂșC AHT21-1, 54.72% RH AHT21-1, 25.27ÂșC CPU
8.48ÂșC AHT21-0, 58.80% RH AHT21-0, 19.66ÂșC AHT21-1, 54.66% RH AHT21-1, 25.27ÂșC CPU
8.49ÂșC AHT21-0, 58.76% RH AHT21-0, 19.66ÂșC AHT21-1, 54.67% RH AHT21-1, 25.27ÂșC CPU
...

FULL CODE SOLUTION:

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht0;
Adafruit_AHTX0 aht1;  // Trying to follow https://forum.arduino.cc/t/connecting-two-aht21b-sensors-to-i2c-and-serial-printing-it/1252379/6

void setup() {
  Serial.begin(115200);
  
  // Setup AHT21-0 on I2C-0
  if (! aht0.begin(&Wire)) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHTXX found");

  // Setup AHT21-1 on I2C-1
  if (! aht1.begin(&Wire1)) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT1XX found");
}

void loop() {
  // AHT21 Temp Sensors

  // Get data from AHT21-0 on I2C-0 
  sensors_event_t humidity0, temp0;
  aht0.getEvent(&humidity0, &temp0);// populate temp and humidity objects with fresh data
  Serial.print(String(temp0.temperature) + "ÂșC AHT21-0, "); 
  Serial.print(String(humidity0.relative_humidity) + "% RH AHT21-0, ");
  
  // Get data from AHT21-0 on I2C-0 
  sensors_event_t humidity1, temp1;
  aht1.getEvent(&humidity1, &temp1);// populate temp and humidity objects with fresh data
  Serial.print(String(temp1.temperature) + "ÂșC AHT21-1, "); 
  Serial.print(String(humidity1.relative_humidity) + "% RH AHT21-1, ");

  // Built-in RP2350 CPU Temp
  Serial.print(String(analogReadTemp()) + "ÂșC CPU");

  Serial.println();
  delay(100);
}

Again, praise to @sonofcy - you done solved it.

I like this version of the code better because I declare the variables that I use repeatedly outside of the loop. Took me a while to figure out that the sensors_event_t lines was a datatype declaration. This reads better to me. Enjoy everyone!

#include <Adafruit_AHTX0.h>
Adafruit_AHTX0 aht0;
sensors_event_t humidity0, temp0;
Adafruit_AHTX0 aht1;
sensors_event_t humidity1, temp1;


void setup() {
  Serial.begin(115200);
  
  // Setup AHT21-0 on I2C-0
  if (! aht0.begin(&Wire)) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHTXX found");

  // Setup AHT21-1 on I2C-1
  if (! aht1.begin(&Wire1)) {
    Serial.println("Could not find AHT? Check wiring");
    while (1) delay(10);
  }
  Serial.println("AHT1XX found");
}

void loop() {
  // AHT21 Temp Sensors

  // Get data from AHT21-0 on I2C-0 
  aht0.getEvent(&humidity0, &temp0);// populate temp and humidity objects with fresh data
  Serial.print(String(temp0.temperature) + "ÂșC AHT21-0, "); 
  Serial.print(String(humidity0.relative_humidity) + "% RH AHT21-0, ");
  
  // Get data from AHT21-1 on I2C-1 
  aht1.getEvent(&humidity1, &temp1);// populate temp and humidity objects with fresh data
  Serial.print(String(temp1.temperature) + "ÂșC AHT21-1, "); 
  Serial.print(String(humidity1.relative_humidity) + "% RH AHT21-1, ");

  // Built-in RP2350 CPU Temp
  Serial.print(String(analogReadTemp()) + "ÂșC CPU");

  Serial.println();
  delay(100);
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.