Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

turning off interrupts doesn't work #832

Closed
rtwfroody opened this issue Nov 13, 2017 · 3 comments
Closed

turning off interrupts doesn't work #832

rtwfroody opened this issue Nov 13, 2017 · 3 comments

Comments

@rtwfroody
Copy link

The following code shows that disabling interrupts is not implemented for this platform:
https://github.com/espressif/arduino-esp32/blob/master/cores/esp32/Arduino.h#L83

#define sei()
#define cli()
#define interrupts() sei()
#define noInterrupts() cli()

This is causing problems for me because I'm trying to read a DHT22 temperature sensor. The library contains a critical section (https://github.com/adafruit/DHT-sensor-library/blob/master/DHT.cpp#L149) where it needs to measure the length of high and low pulses on a digital input pin. Interrupts going off throw off the measurement. I've modified the code to watch timers instead of counting cycles (adafruit/DHT-sensor-library#93), but I still see a 5-10% failure rate.

It looks like FreeRTOS has functions to use in critical sections: http://www.freertos.org/taskENTER_CRITICAL_taskEXIT_CRITICAL.html. Using those macros leads to compilation errors. Is it possible to use FreeRTOS functions from Arduino code?

This all may be related to #811

@beegee-tokyo
Copy link
Contributor

Not sure why you get compilation errors (I am on PlatformIO using the staging version of arduino-esp32), but I use
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
portENTER_CRITICAL(&mux);
portEXIT_CRITICAL(&mux);
for reading a DHT11 sensor (not the Adafruit library but markruys/arduino-DHT) and it works well.

Here is the modified readSensor() function:

void DHT::readSensor()
{
  // Make sure we don't poll the sensor too often
  // - Max sample rate DHT11 is 1 Hz   (duty cicle 1000 ms)
  // - Max sample rate DHT22 is 0.5 Hz (duty cicle 2000 ms)
  unsigned long startTime = millis();
  if ( (unsigned long)(startTime - lastReadTime) < (model == DHT11 ? 999L : 1999L) ) {
    return;
  }
  lastReadTime = startTime;

  temperature = NAN;
  humidity = NAN;

  // Request sample

  digitalWrite(pin, LOW); // Send start signal
  pinMode(pin, OUTPUT);
  if ( model == DHT11 ) {
    delay(18);
  }
  else {
    // This will fail for a DHT11 - that's how we can detect such a device
    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;
  portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
  portENTER_CRITICAL(&mux);
  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;
		portEXIT_CRITICAL(&mux);
        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;
    }
  }
	portEXIT_CRITICAL(&mux);
  // Verify checksum

  if ( (byte)(((byte)rawHumidity) + (rawHumidity >> 8) + ((byte)rawTemperature) + (rawTemperature >> 8)) != data ) {
    error = ERROR_CHECKSUM;
    return;
  }

  // Store readings

  if ( model == DHT11 ) {
    humidity = rawHumidity >> 8;
    temperature = rawTemperature >> 8;
  }
  else {
    humidity = rawHumidity * 0.1;

    if ( rawTemperature & 0x8000 ) {
      rawTemperature = -(int16_t)(rawTemperature & 0x7FFF);
    }
    temperature = ((int16_t)rawTemperature) * 0.1;
  }

  error = ERROR_NONE;
}

@rtwfroody
Copy link
Author

I got errors because the docs I saw say portENTER_CRITICAL() doesn't take an argument. If I use your format, I can make everything work nicely by using that for sei()/cli() in Arduino.h. I'll make a pull request.

@everslick
Copy link
Contributor

This issue is closed, because it looks as if it is not a bug or problem with the ESP32 Arduino core or its support libraries. For general API usage questions or help on specific coding challenges, please visit the arduino-esp32 Gitter channel. If you feel this issue was closed in error, reopen it and comment, why you think this is a bug in the Arduino-Core.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants