ESP8266 GPIO扩展器丢失中断

时间:2017-10-28 01:37:28

标签: arduino interrupt gpio nodemcu arduino-esp8266

我有一个允许LED脉冲的程序。我还用一个按钮连接PC8574 GPIO扩展器。我想评估按键。但是,我只能读取INT(中断)的状态,同时程序处于使LED更亮并再次变暗(两个for循环之间)之间的部分

我知道问题是for循环的延迟,但我不知道如何避免这种情况。

是否可以更频繁地评估中断相关代码或者像实际中断一样 - 总是在按下实际键时?如果是这样,怎么样?

我使用此库:This project on GitHub

/*LED_Breathing.ino Arduining.com  20 AUG 2015
Using NodeMCU Development Kit V1.0
Going beyond Blink sketch to see the blue LED breathing.
A PWM modulation is made in software because GPIO16 can't
be used with analogWrite().
*/

#include <pcf8574_esp.h>
#include <Wire.h>
TwoWire testWire;
// Initialize a PCF8574 at I2C-address 0x20, using GPIO5, GPIO4 and testWire for the I2C-bus
PCF857x pcf8574(0x20, &testWire);

#define LED     D1        // Led in NodeMCU at pin GPIO16 (D0).

#define BRIGHT    300     //max led intensity (1-500)
#define INHALE    1250    //Inhalation time in milliseconds.
#define PULSE     INHALE*1000/BRIGHT
#define REST      1000    //Rest Between Inhalations.

#define PIN_INT D5
#define PIN_SDA D7
#define PIN_SCL D8

//----- Setup function. ------------------------
void setup() {                
  Serial.begin(115200);
  Wire.pins(PIN_SDA, PIN_SCL);//SDA - D1, SCL - D2
  Wire.begin();

  pinMode(PIN_INT, INPUT_PULLUP);

  pcf8574.begin( 0xFF); 
  pcf8574.resetInterruptPin();
  pinMode(LED, OUTPUT);   // LED pin as output.    
}


bool CheckKey(byte key, byte num){ //0, 1, 2, 3
  return key & (1 << num);
}

//----- Loop routine. --------------------------
void loop() {
  //ramp increasing intensity, Inhalation: 
  for (int i=1;i<BRIGHT;i++){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);         // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);   // wait
    delay(0);                        //to prevent watchdog firing.
  }


  if( digitalRead(PIN_INT)==LOW ){
    delay(50);
    byte b = pcf8574.read8();
    Serial.println( "INT: " + String(b));

    byte keys = ((~b)) & 0x0F;

    if( CheckKey(keys, 8) ){
      Serial.println( "KEY 7");
      delay(2000);
    }
  }

  //ramp decreasing intensity, Exhalation (half time):
  for (int i=BRIGHT-1;i>0;i--){
    digitalWrite(LED, LOW);          // turn the LED on.
    delayMicroseconds(i*10);          // wait
    digitalWrite(LED, HIGH);         // turn the LED off.
    delayMicroseconds(PULSE-i*10);  // wait
    i--;
    delay(0);                        //to prevent watchdog firing.
  }
  delay(REST);                       //take a rest...
}

1 个答案:

答案 0 :(得分:1)

您可以通过Arduino的attachInterrupt()函数将PCF8574 INT引脚用作对ESP8266的中断,但是您从中学到的收益并不多,因为要检测按下了哪个键,您需要调用{{ 1}},并且您无法从中断处理程序中执行此操作。 ESP8266 Arduino核心基于Espressif NONOS SDK,因此您无法使用单独的线程来监视按键。我建议定义一个辅助函数,检查当前是否按下了一个键,然后在主循环中尽可能多地调用该函数,例如在两个for循环的每个循环中。按下按键时,LED的亮度梯度会略微受到干扰,但我认为肉眼不会注意到。

因此,辅助函数可以定义为:

pcf8574.read8()

然后,在byte GetKeyPress(void) { if (digitalRead(PIN_INT) == LOW) { return ~pcf8574.read8(); } else { return 0; } } 函数的开头声明一个静态变量loop(),并在两个for循环的每一个中调用上述函数:

static byte keyPress;

要处理按键时(例如,在代码中的两个for循环之间),您可以这样做:

if (keyPress == 0) {
  keyPress = GetKeyPress();
}