0
\$\begingroup\$

This is my wiring here:
+ is connected to 3v3, - to GND and OUT to pin28.

I'm using this example found on raspberry-pico official examples.

#include <stdio.h>
#include <math.h>
#include "pico/stdlib.h"
#include "hardware/gpio.h"

#ifdef PICO_DEFAULT_LED_PIN
#define LED_PIN PICO_DEFAULT_LED_PIN
#endif

const uint DHT_PIN = 28;
const uint MAX_TIMINGS = 85;

typedef struct {
    float humidity;
    float temp_celsius;
} dht_reading;

void read_from_dht(dht_reading *result);

int main() {
    stdio_init_all();
    gpio_init(DHT_PIN);
#ifdef LED_PIN
    gpio_init(LED_PIN);
    gpio_set_dir(LED_PIN, GPIO_OUT);
#endif
    while (1) {
        dht_reading reading;
        read_from_dht(&reading);
        float fahrenheit = (reading.temp_celsius * 9 / 5) + 32;
        printf("Humidity = %.1f%%, Temperature = %.1fC (%.1fF)\n",
               reading.humidity, reading.temp_celsius, fahrenheit);

        sleep_ms(2000);
    }
}

void read_from_dht(dht_reading *result) {
    int data[5] = {0, 0, 0, 0, 0};
    uint last = 1;
    uint j = 0;

    gpio_set_dir(DHT_PIN, GPIO_OUT);
    gpio_put(DHT_PIN, 0);
    sleep_ms(20);
    gpio_set_dir(DHT_PIN, GPIO_IN);

#ifdef LED_PIN
    gpio_put(LED_PIN, 1);
#endif
    for (uint i = 0; i < MAX_TIMINGS; i++) {
        uint count = 0;
        while (gpio_get(DHT_PIN) == last) {
            count++;
            sleep_us(1);
            if (count == 255) break;
        }
        last = gpio_get(DHT_PIN);
        if (count == 255) break;

        if ((i >= 4) && (i % 2 == 0)) {
            data[j / 8] <<= 1;
            if (count > 16) data[j / 8] |= 1;
            j++;
        }
    }
#ifdef LED_PIN
    gpio_put(LED_PIN, 0);
#endif

    if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF))) {
        result->humidity = (float) ((data[0] << 8) + data[1]) / 10;
        if (result->humidity > 100) {
            result->humidity = data[0];
        }
        result->temp_celsius = (float) (((data[2] & 0x7F) << 8) + data[3]) / 10;
        if (result->temp_celsius > 125) {
            result->temp_celsius = data[2];
        }
        if (data[2] & 0x80) {
            result->temp_celsius = -result->temp_celsius;
        }
    } else {
        printf("Bad data\n");
    }
}

When I use serial debug I should get something like Humidity = 50%, Temperature = 10C but the only thing I'm getting is Bad data and Humidity = 0%, Temperature = 0C.

What am I doing wrong here?

EDIT
The sensor is working on my Arduino UNO.

I've now tried UART connection since someone told me that the USB Serial could be interrupting.
This is my wiring: 1, 2, 3

I've activated Serial Port and Serial Console on my Raspberry Pi Pico and did minicom -b 115200 -o -D /dev/ttyS0 but no output is set.

\$\endgroup\$
10
  • \$\begingroup\$ You should expect: Humidity = 50.0%, Temperature = 10.0C (50.0F). What is the exact string you get? \$\endgroup\$ Commented Mar 13, 2021 at 16:33
  • \$\begingroup\$ what is your question? \$\endgroup\$
    – jsotola
    Commented Mar 13, 2021 at 16:34
  • \$\begingroup\$ @HenningLarsen what I'm getting is the Bad Data String \$\endgroup\$ Commented Mar 13, 2021 at 17:10
  • \$\begingroup\$ @jsotola the question is what I'm doing wrong since the wiring is correct and the example is from the official github \$\endgroup\$ Commented Mar 13, 2021 at 17:10
  • 1
    \$\begingroup\$ @AndréClérigo - Welcome :-) However I see that you have posted the same question on Stack Overflow. Such multi-posting isn't allowed, as it wastes time duplicating the effort of people on the two sites. There is hardware debugging you can do (if you have the tools), and limited software debugging (since there is just one if() statement that leads to the "Bad data" message). Where do you want the question to "live" - here (if you have an oscilloscope or logic analyser)? Or on Stack Overflow for s/w (if you don't)? \$\endgroup\$
    – SamGibson
    Commented Mar 13, 2021 at 17:39

2 Answers 2

3
\$\begingroup\$

I found a fix! I used this line of code instead

if (count >46) data[j / 8] |= 1;

Instead of

if (count > 16) data[j / 8] |= 1;

There is a whole github issue that talks about it here

I also find out that the for this to work the sensor should be using a 4.7k Ohm resitance so since my board had an embedded resistance of 5.1k I had to had a 55k Ohm resistance in parallel to pull it down to 4.7k and now the code works!

Many thanks for those that tried to help me!

\$\endgroup\$
0
0
\$\begingroup\$

The only way you can get "Bad Data" if from this if statement to evaluate to false:

if ((j >= 40) && (data[4] == ((data[0] + data[1] + data[2] + data[3]) & 0xFF)))

Either

j < 40  or (data[4] != ((data[0] + data[1] + data[2] + data[3]) & 0xFF))

Try print out (if you cannot step through with a debugger) what the value of these variables are, and work back from there.

Can you link to the sensor datasheet?

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.