[Solved] DHT reading half working for no reason

Hello,

I am currently experiencing a weird problem.

I have a mega2560 with Ethernet shield and am trying to get a JSON reading of the values.

The weird thing is, it works but only for humidity. Temperature won’t display in JSON. Only in Serial.println().

(My code may not be negative temps proof, not tested yet)

Interesting parts are readDHT22Sensor function and end of loop().

#include <DHT.h>
#include <Ethernet.h>
#include <SPI.h>

DHT dht(7, DHT22);

byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED }; //ethernet shield mac address
byte ip[] = { 192, 168, 10, 102 }; // arduino IP in lan
byte gateway[] = { 192, 168, 1, 1 }; // internet access via router
byte subnet[] = { 255, 255, 255, 0 }; //subnet mask
EthernetServer server(84); //server port

String readString;

char *readDHT22Sensor(int pin){
  DHT dht(pin, DHT22);
  dht.begin();
  char returnString[64];
  char temperature[6];
  char humidity[6];

  dtostrf(dht.readTemperature(), 10, 2, temperature);
  dtostrf(dht.readHumidity(), 10, 2, humidity);
  
  sprintf(returnString, "{temperature : %s , humidity : %s}", temperature, humidity);
  return returnString;
}

void setup() {
  Ethernet.begin(mac, ip, gateway, gateway, subnet);
  server.begin();
  pinMode(7, INPUT);
  dht.begin();
  Serial.begin(9600);
  Serial.println("go");
}

void loop() {
  // Create a client connection
    EthernetClient client = server.available();
    if (client) {
        while (client.connected()) {
            if (client.available()) {
                char c = client.read();

                //read char by char HTTP request
                if (readString.length() < 100) {

                    //store characters to string
                    readString += c;
                    //Serial.print(c);
                }

                //if HTTP request has ended
                if (c == '\n') {

                    client.println("HTTP/1.1 200 OK");
                    client.println("Content-Type: text/json");
                    client.println();
                    client.println(readDHT22Sensor(7));
                    //Serial.println(readDHT22Sensor(7));

                    delay(1);
                    //stopping client
                    client.stop();
                    
                    if(readString.indexOf("pin52on") >0)
                    {
                      Serial.println("52 high");
                      pinMode(53, OUTPUT);
                      digitalWrite(53, HIGH);
                    }
                    if(readString.indexOf("pin52off") >0)
                    {
                      Serial.println("52 low");
                      pinMode(53, OUTPUT);
                      digitalWrite(53, LOW);
                    }
                    

                    //clearing string for next read
                    readString="";
                }
            }
        }
    }
}

The result :

TBH I don’t really understand why…

Thanks for your help

char *readDHT22Sensor(int pin){
  DHT dht(pin, DHT22);
  dht.begin();
  char returnString[64];
  char temperature[6];
  char humidity[6];

  dtostrf(dht.readTemperature(), 10, 2, temperature);
  dtostrf(dht.readHumidity(), 10, 2, humidity);
  
  sprintf(returnString, "{temperature : %s , humidity : %s}", temperature, humidity);
  return returnString;
}

Classic newbie trap. You're returning a pointer to a local array. Once the function exits the array no longer exists. So you have a pointer pointing to some location in memory and you don't know what the program is ding with that memory location outside of this function.

Don't do this.

How whould I proceed then ?

Thanks

JeanneD4RK:
How whould I proceed then ?

Thanks

BY not returning a pointer to local storage. Make returnSting global and make the function return void is the obvious answer. There are others.

Ok I did that it did not change anything, but I have other news, I changed

  char temperature[10];
  char humidity[10];
  dtostrf(dht.readTemperature(), 10, 2, temperature);
  dtostrf(dht.readHumidity(), 10, 2, humidity);

To this

  char temperature[10];
  char humidity[10];
  dtostrf(dht.readHumidity(), 10, 2, humidity);
  dtostrf(dht.readTemperature(), 10, 2, temperature);

And here is the result :


(Yes it's hot AF here)

Who the hell invented C ?

If that made it "appear" to work then you're chasing some undefined behavior somewhere. This can't be counted on. You've got something messed up only now that you've made this change it isn't corrupting the same location in memory so it looks like it works. But you still have a bug somewhere.

That's the kind of thing where you add a single unrelated line to some other unrelated part of the code and suddenly it breaks again.

Yes I never meant it was solved, the humidity fields has temp in it too…

I really don’t know why he’s mixing up this. 2 local variables put in a sprintf should not do that…

JeanneD4RK:
I really don't know why he's mixing up this. 2 local variables put in a sprintf should not do that...

Post the most recent code. You've got something funny going on. Once you introduce undefined behavior it is pointless to try to explain why. You just gotta fix the buffer overrun or whatever is causing it.

...

Obviously a 10 char long string has only 9 chars

Did not know how dtostrf was working, I tought I had to put the length of the string in the 2nd arg, nope it's minimal length. 10 for a 10 char long is too much. Good value would have been 9 if I wanted to keep the behaviour of putting spaces before. I put 1 because I didn't want blank space.

  char temperature[10];
  dtostrf(dht.readTemperature(), 10, 1, temperature);  
  char humidity[10];
  dtostrf(dht.readHumidity(), 10, 1, humidity);

Became

  char temperature[10];
  dtostrf(dht.readTemperature(), 1, 1, temperature);  
  char humidity[10];
  dtostrf(dht.readHumidity(), 1, 1, humidity);

Or could have been maximum 9 char long :

  char temperature[10];
  dtostrf(dht.readTemperature(), 9, 1, temperature);  
  char humidity[10];
  dtostrf(dht.readHumidity(), 9, 1, humidity);

Oh, I see it. Look at dtostrf. You've got a minimum width of 10. But your array is only 10 wide. You gotta leave room for a terminating null. Your dtostrf is writing 11 characters to a 10 character array.

EDIT: Looks like we spotted that at same time.

Thanks for your help !