Temp and Humid reading from two AM2302 Sensors

Hi Community,

Iam now working on my very first Arduino Project. Hardware is Uno R3, SMD and two AM2302 Sensors.

In short, I wish to measure Temperature and Humidity from an Outdoor and Indoor Sensor, to determine if ventilation is a good idea.

Indoor is a Basement with low Temperatures, so hot air at high Humidity from Outside will condensate when let into the cold Basement. And I want to avoid this.

To begin with, I started out with available Example Code and modified it to try reading two identical Sensors.

This resulted in the below:

/*
*	AM2302-Sensor_Example.ino
*
*	Author: Frank Häfele
*	Date:	21.11.2023
*
*	Object: Measure Sensor Data of AM2302-Sensor with Arduino IDE
*/

#include <AM2302-Sensor.h>

constexpr unsigned int O_SENSOR_PIN {7U};

AM2302::AM2302_Sensor Outdoor{O_SENSOR_PIN};

constexpr unsigned int I_SENSOR_PIN {8U};

AM2302::AM2302_Sensor Indoor{I_SENSOR_PIN};


void setup() {
   Serial.begin(115200);
   while (!Serial) {
      yield();
   }
   Serial.print(F("\n >>> AM2302-Sensor_Example <<<\n\n"));

   // set pin and check for sensor
   if (Outdoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Outdoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

   if (Indoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Indoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

}

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

   auto status = Outdoor.read();
   Serial.print("\n\nOutdoor sensor Status(): ");
   Serial.println(status);

   Serial.print("Outdoor Temperature: ");
   Serial.print(Outdoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Outdoor Humidity:    ");
   Serial.print(Outdoor.get_Humidity());
   Serial.println("%RH");



   // I tried to copy the content from line 58-60, to obtain similar functionality for Indoor Sensor. This doesn't work.
   // auto status = Indoor.read();
   // Serial.print("\n\nIndoor sensor Status(): ");
   // Serial.println(status);

   Serial.print("Indoor Temperature: ");
   Serial.print(Indoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Indoor Humidity:    ");
   Serial.print(Indoor.get_Humidity());
   Serial.println("%RH");



   delay(5000);
}

The Output looks like this:

Outdoor sensor Status(): 0
Outdoor Temperature: 25.30°C
Outdoor Humidity: 39.80%RH
Indoor Temperature: 25.10°C
Indoor Humidity: 40.60%RH

Unfortunately, the Indoor Sensor Data never changes, which indicates that I don’t read it properly.

I think that the problem originates from the

// auto status = Indoor.read();

If I uncomment this line, the following Error Message appears:

C:\Users\fnielsen\OneDrive - Agilent Technologies\Dokumenter\Arduino\AM2302_Sensor_Example2\AM2302_Sensor_Example2.ino: In function 'void loop()':C:\Users\fnielsen\OneDrive - Agilent Technologies\Dokumenter\Arduino\AM2302_Sensor_Example2\AM2302_Sensor_Example2.ino:73:9: error: conflicting declaration 'auto status'auto status = Indoor.read();^~~~~~C:\Users\fnielsen\OneDrive - Agilent Technologies\Dokumenter\Arduino\AM2302_Sensor_Example2\AM2302_Sensor_Example2.ino:58:9: note: previous declaration as 'signed char status'auto status = Outdoor.read();^~~~~~exit status 1
Compilation error: conflicting declaration 'auto status'

Basically, I don’t have any desire to use this way of reading the Sensors. If a less complicated way exists then I would prefer this, as long as I’m able to distinguish between Indoor and Outdoor.

Thank you for any help.

Best Regards,

Flemminglassen

Your code declares a variable twice,

Try to declare an unique status variable per sensor.

/*
*	AM2302-Sensor_Example.ino
*
*	Author: Frank Häfele
*	Date:	21.11.2023
*
*	Object: Measure Sensor Data of AM2302-Sensor with Arduino IDE
*/

#include <AM2302-Sensor.h>

constexpr unsigned int O_SENSOR_PIN {7U};

AM2302::AM2302_Sensor Outdoor{O_SENSOR_PIN};

constexpr unsigned int I_SENSOR_PIN {8U};

AM2302::AM2302_Sensor Indoor{I_SENSOR_PIN};


void setup() {
   Serial.begin(115200);
   while (!Serial) {
      yield();
   }
   Serial.print(F("\n >>> AM2302-Sensor_Example <<<\n\n"));

   // set pin and check for sensor
   if (Outdoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Outdoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

   if (Indoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Indoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

}

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

   auto statusO = Outdoor.read();
   Serial.print("\n\nOutdoor sensor Status(): ");
   Serial.println(statusO);

   Serial.print("Outdoor Temperature: ");
   Serial.print(Outdoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Outdoor Humidity:    ");
   Serial.print(Outdoor.get_Humidity());
   Serial.println("%RH");


   auto statusI = Indoor.read();
   // Serial.print("\n\nIndoor sensor Status(): ");
   // Serial.println(statusI);

   Serial.print("Indoor Temperature: ");
   Serial.print(Indoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Indoor Humidity:    ");
   Serial.print(Indoor.get_Humidity());
   Serial.println("%RH");



   delay(5000);
}

Dear robtillaart,

Thank you for your reply.

Unfortunately, I don’t understand what you mean.

Can you point out where I am declaring a Variable twice?

Remember, I am a totally newbie and doesn’t understand much of this :wink:

Best Regards,

Flemminglassen

The variable status is declared (memory is allocated to hold its value) in the line

auto status = Outdoor.read();

When you try to declare it again, the compiler sees a variable with that name is already used so it complains, ==> the error message.

This is the conflicting line.

Change this last line in

status = Indoor.read();

without the AUTO keyword, so the compiler sees you want to reuse the variable instead of redeclare it.

Give it a try.
—-
PS, in the sketch I posted I declared an unique status variable per sensor. This is another way to solve the redeclaration problem

.

Dear robtillaart,

I have now tried out both of your suggestions, and it works! (of course :wink: ).

Thank you for explaining in detail what the Code does and what to expect.

Now, I just need a few calculations and then activating the Output based on the result.

I’ll try to fix this on my own in the first place.

Thank you again.

Best Regards,

Flemminglassen

Dear Forum,

Now my Code seems to do what’s intended, using a simple way of calculating the Dewpoint.

However, there’s a lot of Sensor reading errors:

Outdoor sensor Status(): 0
Outdoor Temperature: 11.20°C
Outdoor Humidity: 31.20%RH
Outdoor Dewpoint: -2.56°C

Indoor sensor Status(): -1
Indoor Temperature: 23.90°C
Indoor Humidity: 40.70%RH
Indoor Dewpoint: 12.04°C

Outdoor sensor Status(): 0
Outdoor Temperature: 24.00°C
Outdoor Humidity: 43.30%RH
Outdoor Dewpoint: 12.66°C

Indoor sensor Status(): 0
Indoor Temperature: 11.00°C
Indoor Humidity: 28.00%RH
Indoor Dewpoint: -3.40°C

Outdoor sensor Status(): -1
Outdoor Temperature: 24.00°C
Outdoor Humidity: 43.30%RH
Outdoor Dewpoint: 12.66°C

Indoor sensor Status(): -1
Indoor Temperature: 11.00°C
Indoor Humidity: 28.00%RH
Indoor Dewpoint: -3.40°C

Outdoor sensor Status(): 0
Outdoor Temperature: 24.00°C
Outdoor Humidity: 43.00%RH
Outdoor Dewpoint: 12.60°C

Indoor sensor Status(): -1
Indoor Temperature: 11.00°C
Indoor Humidity: 28.00%RH
Indoor Dewpoint: -3.40°C

Outdoor sensor Status(): 0
Outdoor Temperature: 24.00°C
Outdoor Humidity: 42.80%RH
Outdoor Dewpoint: 12.56°C

Indoor sensor Status(): -1
Indoor Temperature: 11.00°C
Indoor Humidity: 28.00%RH
Indoor Dewpoint: -3.40°C

Outdoor sensor Status(): -1
Outdoor Temperature: 24.00°C
Outdoor Humidity: 42.80%RH
Outdoor Dewpoint: 12.56°C

Indoor sensor Status(): 0
Indoor Temperature: 23.80°C
Indoor Humidity: 41.10%RH
Indoor Dewpoint: 12.02°C

Outdoor sensor Status(): 0
Outdoor Temperature: 24.00°C
Outdoor Humidity: 43.00%RH
Outdoor Dewpoint: 12.60°C

Indoor sensor Status(): -1
Indoor Temperature: 23.80°C
Indoor Humidity: 41.10%RH
Indoor Dewpoint: 12.02°C

I have soldered the Sensor Wires directly to the Uno Board, so I expect that the physical contact is ok.

I consider twisting the Wires to improve immunity. I also consider shielded Cables for the Sensors.

But I also wonder if the errors origin from a too high communication speed to the Sensors.

How do I change this?

I assume that the

Serial.begin(115200);

is serial communication on the USB Interface. Is this correct?

Here’s the complete Code:

/*
*	AM2302-Sensor_Example.ino
*
*	Author: Frank Häfele
*	Date:	21.11.2023
*
*	Object: Measure Sensor Data of AM2302-Sensor with Arduino IDE
*/

#include <AM2302-Sensor.h>

constexpr unsigned int O_SENSOR_PIN {7U};

AM2302::AM2302_Sensor Outdoor{O_SENSOR_PIN};

constexpr unsigned int I_SENSOR_PIN {8U};

AM2302::AM2302_Sensor Indoor{I_SENSOR_PIN};


void setup() {
   Serial.begin(115200);
   while (!Serial) {
      yield();
   }
   Serial.print(F("\n >>> AM2302-Sensor_Example <<<\n\n"));

   // Definer digitalt output til styring af Fan
   pinMode(13, OUTPUT);

   // set pin and check for sensor
   if (Outdoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Outdoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

   if (Indoor.begin()) {
      // this delay is needed to receive valid data,
      // when the loop directly read again
      delay(3000);
   }
   else {
      while (true) {
      Serial.println("Error: Indoor sensor check. => Please check sensor connection!");
      delay(10000);
      }
   }

}

float OutdoorDewpoint = 0.0;

float IndoorDewpoint = 0.0;



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

   auto statusO = Outdoor.read();
   Serial.print("\n\nOutdoor sensor Status(): ");
   Serial.println(statusO);

   Serial.print("Outdoor Temperature: ");
   Serial.print(Outdoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Outdoor Humidity:    ");
   Serial.print(Outdoor.get_Humidity());
   Serial.println("%RH");

   OutdoorDewpoint = Outdoor.get_Temperature() - ((100 - Outdoor.get_Humidity()) / 5);
   Serial.print("Outdoor Dewpoint: ");
   Serial.print(OutdoorDewpoint);
   Serial.print("°C");


   auto statusI = Indoor.read();
   Serial.print("\n\nIndoor sensor Status(): ");
   Serial.println(statusI);

   Serial.print("Indoor Temperature: ");
   Serial.print(Indoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Indoor Humidity:    ");
   Serial.print(Indoor.get_Humidity());
   Serial.println("%RH");

   IndoorDewpoint = Indoor.get_Temperature() - ((100 - Indoor.get_Humidity()) / 5);
   Serial.print("Indoor Dewpoint: ");
   Serial.print(IndoorDewpoint);
   Serial.print("°C");

if (IndoorDewpoint > OutdoorDewpoint) {
      digitalWrite(13, HIGH);
    }
    else {
      digitalWrite(13, LOW);
}

   delay(2500);
}

Thank you in advance.

Best Regards,

Flemminglassen.

The errors aren’t from the USB baud rate. They’re caused by the fragile nature of the AM2302 one-wire protocol.

Status = -1 means the sensor read failed. That can happen fairly often with DHT/AM2302 sensors because their protocol is timing-sensitive. The library retries, but it’s normal to see occasional bad reads.

If you want to improve stability you can:

  • Add a 4.7 kΩ pull-up resistor on each sensor’s data line.

  • Add a 100 nF capacitor across VCC and GND at the sensor.

  • Keep the wires short(<20cm), or use twisted/shielded wires if you must extend them.

  • Remember DHT22/AM2302 sensors are slow – the datasheet recommends a minimum 2 seconds between reads.

Finally, just accept that an occasional read failure is normal. Program around it: when status = -1, ignore the value, retry, or keep the last good measurement. And if you want check out this article for a detailed walkthrough.

There are some causes for failed reads

  1. reading too early, the AM2302 needs some time between readings (datasheet)

  2. having interrupt during the read(), which causes to miss data bits.

My DHTNew library has means to handle both, you might give it a try.

See - GitHub - RobTillaart/DHTNew: Arduino library for DHT11 and DHT22 with automatic sensor recognition

Hi guys,

Today, I connected the hardware to Mains Supply, using a Solid State Relay.

Everything works as intended. GREAT!

However, things evolve and new ideas come to my mind, and the next level could be, sending a notification if something doesn’t behave as expected. But this will be part of another project.

I disabled the sensor check in the setup, since they never passed. However, they provide valid reads occasionally, and that’s fine for me.

If anyone wish to copy the code, here it is:

#include <AM2302-Sensor.h>

constexpr unsigned int O_SENSOR_PIN {7U}; // Pin 7 defined as Input for Outdoor Sensor
AM2302::AM2302_Sensor Outdoor{O_SENSOR_PIN};

constexpr unsigned int I_SENSOR_PIN {8U}; // Pin 8 defined as Input for Indoor Sensor
AM2302::AM2302_Sensor Indoor{I_SENSOR_PIN};

void setup() {
   Serial.begin(115200); // Initiate Serial Communication
   while (!Serial) {
      yield();
   }
   Serial.print(F("\n >>> AM2302-Sensor_Example <<<\n\n"));

      pinMode(13, OUTPUT); // Define Pin 13 as Digital Output, to control the Fan

   // Check for sensor
   if (Outdoor.begin()) {
      // This delay is needed to receive valid data, when the loop directly read again
      delay(3000);
   }
   else {
      // while (true) {
      // Serial.println("Error: Outdoor sensor check. => Please check sensor connection!");
      // delay(10000);
      // }
   }

   if (Indoor.begin()) {
      // This delay is needed to receive valid data, when the loop directly read again
      delay(3000);
   }
   else {
      // while (true) {
      // Serial.println("Error: Indoor sensor check. => Please check sensor connection!");
      // delay(10000);
      // }
   }

}

float OutdoorDewpoint = 0.0; // Variable to hold Outdoor Dewpoint Value
float IndoorDewpoint = 0.0; // Variable to hold Indoor Dewpoint Value

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

   Outdoor:
   auto statusO = Outdoor.read();
   Serial.print("\n\nOutdoor sensor Status(): ");
   Serial.println(statusO);
   
   if ((statusO) != 0) { // If Sensor Status not OK, then read Sensor again
      delay(2500);
      goto Outdoor;
   }

   Serial.print("Outdoor Temperature: "); // Print Outdoor Temperature
   Serial.print(Outdoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Outdoor Humidity:    "); // Print Outdoor Humidity
   Serial.print(Outdoor.get_Humidity());
   Serial.println("%RH");

   OutdoorDewpoint = Outdoor.get_Temperature() - ((100 - Outdoor.get_Humidity()) / 5); // Calculate Dewpoint
   Serial.print("Outdoor Dewpoint: "); // Print Outdoor Dewpoint
   Serial.print(OutdoorDewpoint);
   Serial.print("°C");

   Indoor:
   auto statusI = Indoor.read();
   Serial.print("\n\nIndoor sensor Status(): ");
   Serial.println(statusI);
      
   if ((statusI) != 0) { // If Sensor Status not OK, then read Sensor again
      delay(2500);
      goto Indoor;
   }

   Serial.print("Indoor Temperature: "); // Print Indoor Temperature
   Serial.print(Indoor.get_Temperature());
   Serial.println("°C");

   Serial.print("Indoor Humidity:    "); // Print Indoor Humidity
   Serial.print(Indoor.get_Humidity());
   Serial.println("%RH");

   IndoorDewpoint = Indoor.get_Temperature() - ((100 - Indoor.get_Humidity()) / 5);
   Serial.print("Indoor Dewpoint: "); // Print Indoor Dewpoint
   Serial.print(IndoorDewpoint);
   Serial.print("°C");

if (IndoorDewpoint > OutdoorDewpoint) { // If Indoor Dewpoint is higher than Outdoor Dewpoint, then Fan should run
      digitalWrite(13, HIGH);
    }
    else {
      digitalWrite(13, LOW);
}

delay(2500);

}

Thanks a lot for guiding me.

Best Regards,

Flemmniglassen

could be written without the goto

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

   auto statusO = Outdoor.read();
   Serial.print("\n\nOutdoor sensor Status(): ");
   Serial.println(statusO);
   
   if ((statusO) != 0) { // If Sensor Status not OK, then read Sensor again
      delay(2500);
      return;
   }

Hi robtillaart,

Thanks for pointing this out.

I know that the goto command isn’t part of good programming practice.

However, I couldn’t find out how to solve the task in another way.

How do I know, to which point the return command returns?

Best Regards,

Flemminglassen.

A call to return leaves the function it is in.

somewhere hidden in the Arduino core is this (approx) code

int main()
{
  setup();
  while(1)
  {
    do_something_with_serial_events();
    //  maybe more hidden stuff I do not know about
    loop();
  }
}

When you call return in loop() it returns to the while(1) which is an endless loop
This while loop prepares Serial events and maybe more.