Timer Delay in Interrupt Service Routine

This is actually a question about Arduino ISR compatibility with a NodeMCU ESP8266, so I apologize if this isn't an appropriate forum to ask about it. I have an interrupt driven routine to read a DHT11 sensor where I use both delay() and delayMicroseconds() within the ISR itself. It works like a charm. This same code, when ported to a UNO, freezes at the delay() statement in the ISR (as it should). Moving the delays out of the ISR and into the main code fixes it.

I guess my question is whether it's okay to use a delay in the ISR in an ESP8266? I think it can greatly simplify the timing code, in some cases, but most discussions on the subject echo the Arduino caveats.

Unless you positively need real-time behavior, I wouldn't do a lot more than set a boolean flag in an ISR and let the mainline process that. ISRs really should be kept short and sweet.

IMHO.

I don't have any DHT sensors but, from reading Forum posts, I think that a read can be broken down into two non-blocking processes. Send a message to the sensor to start a reading. Come back a little bit later and get the data when it is ready. That may mean avoiding the use of a library.

...R

I use both delay() and delayMicroseconds() within the ISR itself.

Why ?

If you find yourself wanting to use a delay of any sort in an ISR, that is a red flag - you're confused and going down the wrong path. Stop, reevaluate what you're trying to do, and rethink how you were planning to do it.

DrAzzy:
you're confused and going down the wrong path.

That sounds like my life in general :confused:

Whether or not to use a delay() in an ISR is a moot point on Arduinos, since it won't work. I was surprised to discover (by accident) that it appears to function on the ESP8266. The DHT11 (along with a plethora of other sensor goodies) was holiday gift and I thought I would give it a run. After trying several (at least four) DHT libraries with varying success, I thought I would write my own routine, just for fun.

// Connect DHT11 Vcc pin to UNO 5V pin
// Connect DHT11 GND pin to UNO GND pin
// Connect DHT11 Signal pin to UNO pins 2 and 4
#define DHT_PIN 4
#define INT_PIN 2

volatile int state = 0;
volatile unsigned long bTime;
volatile byte Data[5];
volatile int bytePtr;
volatile int bitPtr;

float temp;
float humidity;

void setup()
{
// Prepare pins
  digitalWrite(DHT_PIN, HIGH);
  pinMode(DHT_PIN, OUTPUT);
  attachInterrupt(digitalPinToInterrupt(INT_PIN), interrupt, CHANGE);
  Serial.begin(115200);
  Serial.println("Starting ...");
// Wait at least one second for DHT to internally initialize
  delay(1000);
}

void loop()
{
  getData(temp,humidity);
  Serial.println("Temperature: " + String(temp) + " | Humidity: " + String(humidity));
  delay(2000);
}

void getData(float &t, float &h)
{
  bitPtr = 2;
  digitalWrite(DHT_PIN, LOW); // begin sampling
  delay(18);
  state = 1;
  digitalWrite(DHT_PIN, HIGH);
  while(state) // wait until done
  {
  }
  delayMicroseconds(50); // allow DHT11 to stabilize
  digitalWrite(DHT_PIN, HIGH); // set first to avoid glitches
  pinMode(DHT_PIN, OUTPUT); // disable DHT11
  h = (Data[0] * 10.0 + Data[1]) / 10.0; // humidity first
  t = ((Data[2] * 10.0 + Data[3]) / 10.0) * 9.0 / 5.0 + 32.0;
//  t = ((Data[2] * 10.0 + Data[3]) / 10.0); // centigrade
}

void interrupt()
{
  switch (state)
  {
    case 1:
      pinMode(DHT_PIN, INPUT); // allow DHT11 to drive ISRs
      state = 2;
    break;
    case 2:
      if(!bitPtr--)
      {
        bytePtr = 0;
        bitPtr = 7;
        state = 3;
      }
    break;
    case 3:
      if(bytePtr != 5)
      {
        state = 4;
        bTime = micros(); // start timing
      }
      else
      {
        state = 0;
      }
    break;
    case 4:
      if((micros() - bTime) > 45) // bit is a 1
      {
        bitSet(Data[bytePtr],bitPtr);
      }
      else
      {
        bitClear(Data[bytePtr],bitPtr);
      }
      if(bitPtr == 0) // reset pointers
      {
        bytePtr++;
        bitPtr = 7;
      }
      else // next bit
      {
        bitPtr--;
      }
      state = 3;
    break;
  }
}

The docs for the DHT11 specify that the resolution is 1, but I included the decimal information anyway. This should allow it to work correctly with a DHT12 as well.