RobTillaart / AM2315

Arduino library for the I2C AM2315 temperature and humidity sensor.
MIT License
3 stars 1 forks source link

AM2315 and more I2C devices - problems #8

Closed JopWerff closed 2 years ago

JopWerff commented 2 years ago

Hi Rob,

The AM2315-library works good, also when I use other I2C-pins, in my case SCL (19) and SDA (5).

Problems come up, with a BME280 and connected, in my case, to SCL 18 and SDA 23. The AM2315 is still ok, but the BME280 is giving weird values as you see below:

image

For the BME280 I'm using these Adafruit-libraries.

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

Attached an extract of my sketch showing these problems. #define enableAM2315 false // if true then weird values from BME280 Set this compiler directive to true and see the output in Serial monitor

Thanks,

Jop

Multiple_-_AM2315_en_BME280.zip

RobTillaart commented 2 years ago

If the BME is used stand alone does it give faulty errors?

RobTillaart commented 2 years ago

include "Switch.h"

      ^~~~~~~~~~

compilation terminated.

Which library is this?

RobTillaart commented 2 years ago

created a minimal version with these 2 sensors - can you give it a try?

weather_station.zip

RobTillaart commented 2 years ago

Done some reading about BME280 and causes found so far is (1) wiring and (2) incorrect calibration data.

I am working a lot with the MS5611 last couple of days - https://www.amazon.de/gp/product/B07Y1QZKF4/ https://github.com/RobTillaart/MS5611 - library is pretty stable, last release will be tested tomorrow.

JopWerff commented 2 years ago

include "Switch.h" ^~~~~~ compilation terminated.

Which library is this?

library I discovered here: TTGO ESP32 MINI

this is also the ESP32 I use. Because of possibility external Wifi-antenna. (this is really a problem - to find such ESP32 boards)

JopWerff commented 2 years ago

If the BME is used stand alone does it give faulty errors?

No - if I leave out by #define enableAM2315 false no weird values from BME280 I disabled also the power to the AM2315

RobTillaart commented 2 years ago

mmm could indeed be a power problem.

I would test the following.

1) Can you connect the power of the sensors to the VIN pin of the ESP? Then it will be directly powered from the power supply. (dont know if the BME280 is a 5V device, if not stick to 3V3

2) Can you add a delay of 10 seconds between reading teh AM2315 and the BME280?

3) Can you change the order in which the sensors are read?

JopWerff commented 2 years ago

created a minimal version with these 2 sensors - can you give it a try?

weather_station.zip

ok, but what pins you planned me to use as well voor the BME280 as for the AM2315? (no info about that in the sketch you've sent me)

JopWerff commented 2 years ago

mmm could indeed be a power problem.

I would test the following.

  1. Can you connect the power of the sensors to the VIN pin of the ESP? Then it will be directly powered from the power supply. (dont know if the BME280 is a 5V device, if not stick to 3V3
  2. Can you add a delay of 10 seconds between reading teh AM2315 and the BME280?
  3. Can you change the order in which the sensors are read?

Order of reading the sensors and increasing delay between reads to f.e. 10 secs. doesn't help. Still weird data read from BME280.

But here a new hint. I discovered that the orde of initializing AM2315 and BME280 in setup() makes a big difference. When initializing the BME280 after the AM2315 the latter one is giving problems with weird data. Here the output:

CleanShot 2022-01-16 at 11 37 12@2x

Here relevant code in setup() as it is now and giving results a above:

  #if enableAM2315
  initAM2315();    
  #endif

  #if enableBME280  
  initBME280();  
  #endif

So when changing this order back to initBME before initAM2315 we read weird data from BME280. I checked this twice.

Apparently the initializing code of the one is disturbing the code of the other and the other way around.

Do you have yourself a BME280 to try?

RobTillaart commented 2 years ago

I assume both the BME and AM initialize the Wire object. If they do this with different pins one of the two devices becomes unreachable.

Solution is to have both devices on the same i2c pins.

Other possible point of attention is to keep the i2c clock to 100 KHz. Think that is not the problem.

I don't know if I have a BME280 around, do not recall seeing it recently.

JopWerff commented 2 years ago

Hi Rob, Here is the solution and we solved it together. For the other pins a second Wire-object should be initialized. And this object (Wire1) is available. I forgot this a bit, but my previous code was implementing this already for an BMP280 aside of the BME280. See also the links in the comments coming from Random Nerd Tuturials.

The initBME280 in the code I've sent you should be extended. Now part in this code is:

`

   Wire.begin(BME280_SDA_PIN, BME280_SCL_PIN);    

                                                // NB: niet Wire1()  !!
                                                // default settings
                                                // (you can also pass in a Wire library object like &Wire2)
                                                //unsigned statusBME = bme.begin(&Wire);  
    unsigned statusBME = bme.begin(0x76);  
            // see: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/#7
            // and: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ 

change it in this code:

#if enableAM2315   
Wire1.begin(BME280_SDA_PIN, BME280_SCL_PIN);  
unsigned statusBME = bme.begin(0x76, &Wire1);  
#else
Wire.begin(BME280_SDA_PIN, BME280_SCL_PIN);  // NB: niet Wire1()  !!
                                          // default settings
                                          // (you can also pass in a Wire library object like &Wire2)
                                          //unsigned statusBME = bme.begin(&Wire);  
unsigned statusBME = bme.begin(0x76);  
#endif   
        // see: https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide/#7
        // and: https://randomnerdtutorials.com/esp32-pinout-reference-gpios/ 

This runs ok. You should know I'm a novice in the area of I2C and Wire.

Thnx for all your support. I think we can close this issue.

Have a nice day,

 Jop
RobTillaart commented 2 years ago

Good to hear it is solved.

Do you have a reason why not to use the same I2C pins for the 2 devices? It can handle up to ~100 devices on 2 pins.

https://randomnerdtutorials.com/esp32-i2c-communication-arduino-ide

Good explanation.

JopWerff commented 2 years ago

It's a good idea to use the same I2C pins for these 2 devices: AM2315 and BME280.

After some struggle (finding the I2C-address of this AM2315 with an i2c scanner sketch working bad for unknown reasons) I managed to get this done. But I read now that the AM2315 needs two pull-up resistors 2K-10K on SCL and SDA. https://learn.adafruit.com/am2315-encased-i2c-temperature-humidity-sensor/arduino-code

That's not a problem when connecting a BME280 on same pins?

RobTillaart commented 2 years ago

I am very pragmatic with pull ups, standard one set of 4K7 on the whole I2C bus. If the line is longer than a few meter it drops e,g 1K at 5-8meter. If you need longer wires other tech is needed to be robust.

You need to check is if there are already pull ups on e.g. a breadboard.

Tip: https://www.amazon.nl/Practical-Electronics-Inventors-Paul-Scherz/dp/1259587541 (cheaper in germany)

JopWerff commented 2 years ago

Thnx for the hint.

About connecting these 2 I2C-devices on one set of pins is working good on SDA 23 and SCL 18 and I can use either Wire or Wire1. But I can NOT get this don - the same trick - with the other set of pins SDA 5 and SCL 19, I originally planned to use for the AM2315. (so connecting both devices on these pins).

RobTillaart commented 2 years ago

Think it can be done if you initialize thing in right order (been there struggling) From my head:


#include "Wire.h"
#include "AM2315.h"
#include "Adafruit_Sensor.h"
#include "Adafruit_BME280.h"

Adafruit_BME280 bme;
AM2315 sensor(&Wire);     // connect to Wire

void setup()
{
  Serial.begin(115200);

  Wire.begin(5, 19);     // assign pins of Wire  only once)

  sensor.begin();
  BME.begin(&Wire);     // connect to Wire

....
}

Should also work for Wire1

RobTillaart commented 2 years ago

mmm, BME.begin(&Wire) calls init() which calls Wire.begin() again. seems a bit more tricky ... can't test it myself

JopWerff commented 2 years ago

The constructor for bme is bme.begin( 0x76. [, &] ). // address: 0x76 or 0x77

But what you gave above is working, as well for Wire as for Wire1

Still don't know what was wrong with my implementation. But it's ok.

RobTillaart commented 2 years ago

Still don't know what was wrong with my implementation. But it's ok.

It looks a bit confusing with all the conditional ifdefs. Write for maintainability, just imagine you have to understand your code 6 months from now. That is one important lesson I learned in Computer Science :)

JopWerff commented 2 years ago

I understand quite well what you wanna say. It has pros and cons. Leaving out the ifdefs could mean I have to split up in different sketches for creating different configurations. In that case the total overview is is suffering more and I have to maintain more different sketches.

And I'm lucky with having a rather good memory, so even after a long time I easily remember why I did it like I did. Anyway, the code is meant for myself... ;)