[SOLVED] AM2315 + Photon Weather Shield = no humidity reading

I think you are using the Adafruit_AM2315 from WebIDE, @Michele - right?
If so you will find this in CPP-File:

float Adafruit_AM2315::readHumidity(void) {
  if (! readData()) return 0;
  return humidity;
}

that means that in case of a problem it should output a zero.

So if it works without the Sparkfun Weather Shield and the error message appears after using the Weather Shield, you should follow this trail. Do you like to post your code?

The mystery deepens. I loaded the simple test program onto the Weather Shield and got valid temperature and humidity readings. But my weather station code on the Weather Shield always returns valid temperature but zero for humidity. So the problem can’t be interference from the Shield’s onboard I2C sensors.

I ran the weather code on the stand-alone Photon. Again, I got valid temp. but zero humidity. So there must be something in the weather code it doesn’t like. But what? This program is 3000 lines long.

I tried adding the Sparkfun Weather library and the calls to the Weather Shield’s onboard I2C sensors to the simple code. I still got valid humidity. I tried placing the humidity read call at the very top of the weather code right after the am2315 object is defined before any other routines are run. I still get zero humidity from that program.

The am2315 library is looking for a device at 0x5C. But there is a Github post (http://github.com/kizniche/Mycodo/issues/315) claiming that newer AM2315’s use 0x57. So I tried setting
#define AM2315_I2CADDR 0x57
in both programs, but that didn’t change anything. I still get no humidity when running the weather code.

Then I ran the I2C scanner again. Now it’s saying “no devices found” on the standalone Photon, and only the two onboard sensors on the Shield Photon. I’m like, how does that happen? How can it not find the am2315 but I can still get readings from it - unless I’m using it from my long program.

At this point I don’t even know how to troubleshoot this issue.

Right.

The error happens only when using my long program, on both the standalone Photon and the Photon Weather Shield. It must be something in the code but darned if I know where, or even where to look.

I’ve posted the code (with my API keys redacted) here:

https://go.particle.io/shared_apps/5c043af4926451c18c0001d8

The am2315 object is defined on line 319 and the sensor is started in a block at lines 678-694. The calls to the sensor are in getWeather() at line 1139.

This code should run on any Photon even without a Weather Shield (though the sensor reads will fail obviously).

So I found a function in the library that supposedly reads both t and h in one call eliminating I2C timing issues. But when I put
readTemperatureAndHumidity(t, h) ;
in my program, it won’t compile:
am2315test.ino:72:36: 'readTemperatureAndHumidity' was not declared in this scope
That code is posted here:
https://go.particle.io/shared_apps/5c043ec99264517dfa0001f3

Why you read the humidity 2x? Could you remark out the second reading, pls? @Michele

    if (am2315.begin ()) // Start the Sparkfun BME280
      {
       Particle.publish("AM2315 sensor works!",PRIVATE);
       Serial.println ("AM2315 OK") ;
       delay (100) ; // Very important to allow next I2C call to work.
       humidity = min (am2315.readHumidity(), 99) ;
       delay (100) ;
       humidity = min (am2315.readHumidity(), 99) ;
       Serial.print ("At the top, H=") ;
       Serial.println (humidity) ;
       delay(5000) ;
      }
      else
      {
       Particle.publish("AM2315 sensor bad!",PRIVATE); 
       Serial.println ("AM2315 bad") ;
      }

Maybe you are also able to include a seriallog-handler to get to the root of the problem?https://docs.particle.io/reference/device-os/firmware/argon/#log-handlers

In getWeather() there is also a double reading:

 // H sensor goes to sleep after 3 seconds so 1st call is to wake it up.
    humidity = min (am2315.readHumidity(), 99) ;  
      byte n ;

  for (n=0; n < 10; n++)
    {
    delay (100) ; // Very important to allow next I2C call to work.
    humidity = min (am2315.readHumidity(), 99) ; // Read H twice according to spec sheet.   
    Serial.print ("am2315 H=") ;
    Serial.println (humidity) ;
    }

Could you comment out the for-loop? - I’m not sure if your sensor is really sleeping.
Eventually it will be swallowed when reading the values.

Because there’s a piece in the am2315 datasheet to the effect that the humidity sensor goes to sleep after some period of time and it takes two consecutive reads to wake it up.
clipboard1
I originally had a single read there. That didn’t work either.

That loop was there just to try to get the sensor to respond Originally it was just a single read, which returned zero.

Apparently I’m not the only one to have troubles with this device:

The latter thread included the comment:

I had some issues with waking up the sensor. Not sure exactly what I did differently

but kicking it a few times seems to have helped

So I tried that. Didn’t help me.

Meanwhile, I decided to nail down the I2C address issue. Scoping the wire, I see:


This sure looks like 0x5C (1011100b) to me. SDA (data) is on top, SCL (clock) is below. From the start point (where both signals go low) you can clearly make out the bits. So my device, even though it’s new as of late 2018, is not 0x57.

Notice also that there is very little lag in the rising edges, suggesting that pullup resistance is not the issue.

UPDATE:

I’ve discovered something else interesting. In the AM2315 library, the functions readTemperature and readHumidity are essentially identical. They both send a query to the sensor for temperature and humidity. The only difference is that readTemperature only returns only the temperature value and readHumidity only returns the humidity value.

What worked for me is here:

Wiring diagram is here:

I think the key for me was putting +5v with pullup resistors on SCL and SDA

1 Like

I’m having trouble reading my AM2315 temperature/humidity sensor. The temperature always works but the humidity always returns zero. Here is a sample of what the I2C bus is doing. SDA is on top, SCL is on the bottom. Notice how there are three spots near the left, center, and right where it looks like the clock stayed high for two cycles. I understand that the clock does not run when there is no data but that doesn’t look like the case here.

But I also see that it looks like this happens every nine cycles, corresponding perhaps to byte boundaries (plus an accept bit). Does anyone understand what this trace is showing? As an I2C noob, I’d appreciate any help.

clipboard

I have moved your new thread back to this one, since it’s still the same question and double posting is frowned upon.

You had a reply in this thread so there is no use in scattering the same discussion over multiple threads.

Well I actually considered that aspect and decided that this question was more a general I2C hardware issue as it’s about the SCL line and not really the AM2315 in particular.

But I suppose if you disagree then who am I to say anything.

Interesting. I will give that a try. But from your Fritzy diagram it looks like you’ve got 3.3 V on the pullups, not 5 V. Or am I reading it wrong?

Ah, yes. I forgot the photon was 3.3v. 3.3v works with the AM2315 IIRC

Also, if you are using multiple I2C devices, it may be that the 3.3v w/ pullups should go into the breadboard’s side rails per the diagram rather than directly into the one device. I can’t remember if the BMP085 that I had was working per that diagram.

I was wondering. The datasheet says it works between 3.3 and 5.5 V, and they recommend 5.0.

In any case, the problem is solved, thanks to you. I added the 10K pullups and noticed that you were calling readTemperatureAndHumidity rather than readHumidity. Now that shouldn’t make any difference since readTemperature, readHumidity, and readTemperatureAndHumidity all simply call readData and then return just the piece(s) of info requested. But apparently it matters.

I changed my code from readTemperature followed by readHumidity to a single call to readTemperatureAndHumidity and it started working, with my simple program on the standalone Photon. I then put that readTemperatureAndHumidity call in my weather code and it still worked. I then ran my weather code on the WeatherShield and it still works (even though I didn’t add the pullups on that board).

So go figure. I still have no idea why this should work, nor why the I2C scanner doesn’t find this sensor but the pragmatist in me says it’s just time to let it go.

I think the morals here are:

  1. To use this sensor, call readTemperatureAndHumidity, not readTemperature or readHumidity.

  2. You may or may not need extra pullups on the I2C.

  3. Be sure you know if you have a 0x5C or 0x57 sensor.

Anyway, mega thanks for replying. Now maybe I can get a good night’s sleep :slight_smile:

I still don’t know why the SCL clock looks funny, but that’s probably because I2C hardware experts aren’t particularly going to be attracted to a thread called AM2315 Humidity.

1 Like

Yeah I think I remember that calling the functions individually didn’t work but never investigated.

Pullups reduce the amperage through the sensor so it depends on how much it can tolerate. So it may or may not work or it may or may not affect the life of the sensor. I think it’s usually safer to have them.

1 Like

The “stretched” SCL is created by an I2C STOP condition which brings the bus HIGH (pull-ups). In that period you will notice the SDA goes from HIGH to LOW while the SCL is HIGH. This is a START condition. The nine (9) LOW-to-HIGH SCL transitions are clocking data presented on SDA. The ninth transition is for the ACK bit. You will note that SDA is HIGH on that ninth clock indicating a NACK. So the device is NACKing the transaction.

1 Like

I think I’m good. The Weather Shield has onboard pullups for I2C:
clipboard

OK, thanks very much for the explanation. Do you know of any stand-alone I2C decoders? I know some scopes can do this but mine can’t. Sometimes it’s handy to be able to actually read the wire directly.

You are looking for a logic analyzer. You can get low cost ones which are clones of Saleae units. I have a DSLogic unit that works quite well. The Kingst logic analyzers seem to be good value as well though I have not tested either.

Kingst LA lowest cost unit
Kingst LA with capture memory

1 Like

Great suggestion. I’ve been wanting a logic analyzer for a while but didn’t realize they could decode I2C too. Hopefully Santa will bring me one of these for Christmas!

1 Like

Cheapest one I found for I2C: