ESP32 больше не может вводить прерывание после появления прерывания во время функции delayMicrosecond

У меня странная проблема с моим проектом ESP32. Я использую ADPS-9960 для управления жестами, который запускает внешнее прерывание. В самом обработчике прерываний я задаю только переменную, которая вызывает выполнение функции в цикле. Когда я запускаю прерывание во время функции задержки, прерывание перестает работать. Это означает, что цикл все еще выполняется, но процедура прерывания больше не выполняется.

#include <Arduino.h> 
#include <Wire.h>
#include <SparkFun_APDS9960.h>
#include <ESP32Servo.h>
// Pins
#define APDS9960_INT    25 // Needs to be an interrupt pin

#define SERVO 4

// Constants
// Global Variables
SparkFun_APDS9960 apds = SparkFun_APDS9960();
int isr_flag = 0;
void IRAM_ATTR interruptRoutine();
int detectorPin = 19;

Servo myservo;

void setup() 
{
  // Set interrupt pin as input
  pinMode(APDS9960_INT, INPUT_PULLUP);
  // Initialize Serial port
  Serial.begin(9600);
  Serial.println();
  Serial.println(F("--------------------------------"));
  Serial.println(F("SparkFun APDS-9960 - GestureTest"));
  Serial.println(F("--------------------------------"));
  
  // Initialize interrupt service routine
  attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
  // Initialize APDS-9960 (configure I2C and initial values)
  if ( apds.init() ) 
  {
    Serial.println(F("APDS-9960 initialization complete"));
  } 
  else 
  {
    Serial.println(F("Something went wrong during APDS-9960 init!"));
  }
  apds.setGestureGain(GGAIN_1X); // ohne diese Zeile geht es nicht zuverlässig
  
  // Start running the APDS-9960 gesture sensor engine
  if ( apds.enableGestureSensor(true) ) 
  {
    Serial.println(F("Gesture sensor is now running"));
  } 
  else
  {
    Serial.println(F("Something went wrong during gesture sensor init!"));
  }


  myservo.attach(SERVO);  
  myservo.write(20);

  pinMode(detectorPin, INPUT);
}

void loop()
{
  if( isr_flag == 1 )
  {  
    detachInterrupt(digitalPinToInterrupt(APDS9960_INT));
    handleGesture();
    isr_flag = 0;
    attachInterrupt(digitalPinToInterrupt(APDS9960_INT), interruptRoutine, FALLING);
  }

  if(digitalRead(detectorPin))
    Serial.println("ON");

  else
    Serial.println("OFF");
}

void IRAM_ATTR interruptRoutine()
{
  if(isr_flag == 0)
    isr_flag = 1;
}


void  handleGesture() 
{
    if ( apds.isGestureAvailable() ) 
    {
      if( apds.readGesture() == DIR_FAR )
      {       
        Serial.println("FAR");
        myservo.write(165);
        delayMicroseconds (5000000);
        myservo.write(20); 
      }
      else
        Serial.println("FALSE");
  }
}

, 👍1

Обсуждение

isr_flag должен быть объявлен как "изменчивый". Пожалуйста, сделайте это и повторите попытку, @chrisl

Эй, @chrisl, спасибо за ваш ответ. Я изменил его на " volatile int isr_flag = 0;", но, к сожалению, проблема все еще присутствует., @FriendlyGuest

Почему вы используете " delayMicroseconds() для задержки 5 секунд. Я думаю, что тип параметра-это только " unsinged int. Согласно документации Arduino, максимальное значение составляет 16383us. Пожалуйста, используйте "задержка ()" для таких длительных задержек. В более старых версиях " delayMicroseconds()` также отключал прерывания. Так что это может быть вашей проблемой, @chrisl

Я использовал " dealyMicroseconds ()", потому что я неправильно понял документацию " attachInterrupt ()". К сожалению, использование delay() не решило проблему, если во время функции задержки появляется прерывание, я все еще не могу ввести прерывание после этого. Проблему очень трудно локализовать, так как, похоже, нет хорошего способа отладки в среде IDE Arduino., @FriendlyGuest

Не могли бы вы, пожалуйста, проверить, когда именно выполняется ISR (особенно после первого вызова " задержка ()"), подключив светодиод и переключив его в ISR (но не в операторе if, а только в ISR)?, @chrisl

@крис Еще раз спасибо за ответ. Когда я делаю жест во время задержки, ISR, похоже, не выполняется, так как индикатор не переключается. Я посмотрел в справочном примере и заметил кое-что странное. Они объявляют 2 как контакт прерывания, но затем используют 0 в attachInterrupt/detachInterrupt, это должно быть ошибкой, верно? [link](https://github.com/sparkfun/APDS-9960_RGB_and_Gesture_Sensor/blob/master/Libraries/Arduino/APDS-9960_RGB_and_Gesture_Sensor_Arduino_Library/examples/GestureTest/GestureTest.ino), @FriendlyGuest

Мхх, теперь я больше не вижу причин, по которым ISR не должен срабатывать снова после 5 секунд и движения сервопривода. Вы уверены, что проблема в задержке? Может быть, удалите его и повторите попытку. В настоящее время я немного копаюсь в темноте, @chrisl

Да, я почти уверен, что это должно что-то сделать с задержкой, потому что, когда я использую жест, который вызывает выполнение блока else в " handleGesture ()", кажется, проблем нет. Дальше я попробую использовать простую кнопку для внешнего прерывания и посмотрю, не изменится ли что-нибудь. Спасибо за вашу поддержку до сих пор!, @FriendlyGuest