Search code examples
sensorsesp32

ESP32 reading DHT22 sensor in ULP coprocessor


I´m trying to read a dht22 sensor in ulp deep sleep, and it´s not working, can perhaps someone tell me what I´m doing wrong?

I´m reimplementing the arduino-DHT library because it´s working in non ulp mode with my sensor, it looks like this:

 digitalWrite(pin, LOW); // Send start signal
 pinMode(pin, OUTPUT);
 delayMicroseconds(800);

 pinMode(pin, INPUT);
 digitalWrite(pin, HIGH); // Switch bus to receive data

  // We're going to read 83 edges:
  // - First a FALLING, RISING, and FALLING edge for the start bit
  // - Then 40 bits: RISING and then a FALLING edge per bit
  // To keep our code simple, we accept any HIGH or LOW reading if it's max 85 usecs long

  uint16_t rawHumidity = 0;
  uint16_t rawTemperature = 0;
  uint16_t data = 0;

  for ( int8_t i = -3 ; i < 2 * 40; i++ ) {
    byte age;
    startTime = micros();

    do {
      age = (unsigned long)(micros() - startTime);
      if ( age > 90 ) {
        error = ERROR_TIMEOUT;
        return;
      }
    }
    while ( digitalRead(pin) == (i & 1) ? HIGH : LOW );

    if ( i >= 0 && (i & 1) ) {
      // Now we are being fed our 40 bits
      data <<= 1;

      // A zero max 30 usecs, a one at least 68 usecs.
      if ( age > 30 ) {
        data |= 1; // we got a one
      }
    }

    switch ( i ) {
      case 31:
        rawHumidity = data;
        break;
      case 63:
        rawTemperature = data;
        data = 0;
        break;
    }
  }

Looks simple enough :D, I tried the first part with this code, but it doesn´t work:

rtc_gpio_init(15);
rtc_gpio_set_direction(15, RTC_GPIO_MODE_INPUT_OUTPUT);

And in my ulp script file:

.set temp_humidity_sensor_pin, 13 // gpio 15 (adc 13)

send_start_signal:

    /* disable hold on gpio 15 (data pin) */
    WRITE_RTC_REG(RTC_IO_TOUCH_PAD3_REG, RTC_IO_TOUCH_PAD3_HOLD_S, 1, 0)

    /* switch to output mode */
    WRITE_RTC_REG(RTC_GPIO_OUT_W1TS_REG, RTC_GPIO_OUT_DATA_W1TS_S + temp_humidity_sensor_pin, 1, 1)

    /* send start signal (LOW) */
    WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + temp_humidity_sensor_pin, 1, 0)

    /* pull low for 800 microseconds (8Mhz) */
    wait    6400

    /* switch to input mode */
    WRITE_RTC_REG(RTC_GPIO_OUT_W1TC_REG, RTC_GPIO_OUT_DATA_W1TC_S + temp_humidity_sensor_pin, 1, 1)

    /* switch bus to receive data (HIGH) */
    WRITE_RTC_REG(RTC_GPIO_OUT_REG, RTC_GPIO_OUT_DATA_S + temp_humidity_sensor_pin, 1, 1)

wait_for_sensor_preparation_low:

    READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
    and r0, r0, 1
    jump wait_for_sensor_preparation_low, eq

wait_for_sensor_preparation_high:

    READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1) 
    and r0, r0, 0
    jump wait_for_sensor_preparation_high, eq

    jump wake_up // <-- never called :(

Any ideas?


Solution

  • Your "and r0, r0, 0" instruction (near the end) always sets r0 to zero (x & 0 == 0 by definition), which means the following jump instruction will loop forever. Remember that the "eq" flag doesn't really mean "equal". It means "zero". I think you want:

    wait_for_sensor_preparation_low:
    
        READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1)
        and r0, r0, 1
        jump wait_for_sensor_preparation_high, eq
        jump wait_for_sensor_preparation_low
    
    wait_for_sensor_preparation_high:
    
        READ_RTC_REG(RTC_GPIO_IN_REG, RTC_GPIO_IN_NEXT_S + temp_humidity_sensor_pin, 1) 
        and r0, r0, 1
        jump wait_for_sensor_preparation_high, eq
    

    By the way, I wrote a C compiler for the ULP, which should make your life easier. It's on https://github.com/jasonful/lcc