Hello,
I am working on a bigger project and have runout of Input/Output ports so tried your library, which in the beginning worked very well except for using the Interrupt.
There occur several problems when using D0, D3, D4 for this feature, depending on which one I use (probably because of the 10k PullUp of the Pcf INT line) as there are :
- Not being able to program the device (timeout)
- Not booting up the application after a Powerdown
- Not starting the application after a reset.
I would like to use D0, D3 or D4 as an interrupt input, is this possible in any way ?
The connections of D5, D6, D7 and D8 are not possible to use because they are already in use for SPI for my CardReader (in the original application).
Also another strange thing happens which I was not able to explain :
The blinking of the leds got out of sync with each other after a couple of minutes ??
I made a Test application for it with comments to clarify my problems,
How can I solve these problems ?
Thanks in advance..
<Arduino IDE Source code>
`
/*
- PCF8574 GPIO Port Expand for ESP8266_PCF8574_with_EC11_RotaryEncoder_Led_Beeper
- PCF8574 ----- WeMos-D1 Mini/Pro (LOLIN)
- A0 ----- GND
- A1 ----- GND
- A2 ----- GND
- VSS ----- GND
- VDD ----- 3.3V
- SDA ----- GPIO_4 (D2)
- SCL ----- GPIO_5 (D1)
- INT ----- GPIO_14 (D5) (DO NOT USE D0, D3, D4 or D8 because of pull-Up !!, they will NOT WORK, or device is not possible to program, or does NOT start on PowerUp)
-
(ONLY USE D5, D6 or D7 !!!!)
-
----------------- LET OP is Negative logic !!!
- P0 ----------------- RE_Kanaal-A (Input with Pull_Down 10k to GND, common connection to +3V3) (or 5v)
- P1 ----------------- RE_Kanaal-B (Input with Pull_Down 10k to GND, common connection to +3V3) (or 5v)
- P2 ----------------- RE_Switch (Input with Pull_Down 10k to GND, common connection to +3V3) (or 5v)
- P3 ----------------- LED (Led1) (Output) LED via 1k to 3V3 (or 5V)
- P4 ----------------- LED (Led2) (Output) LED via 1k to 3V3 (or 5V)
- P5 ----------------- BEEPER (Output) Beeper to 3V3 (or 5V)
- P6 ----------------- (NC)BUTTON OR OUTPUT
- P7 ----------------- (NC)BUTTON OR OUTPUT
*/
#include "Arduino.h"
#include "PCF8574.h" // https://github.com/xreef/PCF8574_library
#define ESP8266_INTERRUPTED_PIN D5 // used Interrupt Pin on ESP8266
// Set PCF8574 i2c address
PCF8574 pcf8574(0x38);
// Function interrupt Flag from PCF8574
bool pcfInt = false;
// Output LED(s) on PCF8574
struct LED {
int ledPin; // Used PinOnPCF
unsigned long ledOnOffTime; // Time Led is ON and after that Time Led is OFF (2x value entered)
bool ledIsON = false; // Default at Create
unsigned long ledLastChanged = 0; // Default at Create
} ;
LED Led1; // Led #1
LED Led2; // Led #2
// Output LED(s) on PCF8574
struct BEEPER {
int beepPin; // Used PinOnPCF
int beepType; // NumBeeps (0 = Stop Beeping, 1..254 = NumBeeps, 255 = Continuous Beeps)
unsigned long highDuration; // Time the Beeper is OFF
unsigned long lowDuration; // Time the Beeper is ON
bool beeperIsON = false; // Default at Create
bool beepStatus = false; // Default at Create (Start/Stop Flag)
int beepCountDown = 0; // Default at Create (Value starts the same as NumBeeps (beepType), counts down to 0)
unsigned long beepLastChanged = 0; // Default at Create (Time of last change)
} ;
BEEPER Beep1; // Beeper #1
// Encoder EC11 on PCF
String EncoderSeq = ""; //LeftTurn=BABA, RightTurn=AABB, SwitchPress=SW
static unsigned long LastTimeSeqChanged = 0;
// Use here to prohibit when Blinking of the Leds is a problem to get out of Sync !!!
unsigned long currentTime;
void pcfInterruptOnPCF8574(){
pcfInt = true;
}
void setup()
{
// Setup of the Led(s)
Led1.ledPin = 3;
Led1.ledOnOffTime = 1000;
Led2.ledPin = 4;
Led2.ledOnOffTime = 500;
// Setup of the Beeper(s)
Beep1.beepPin = 5;
Serial.begin(115200);
while (!Serial) {
delay(500);
}
Serial.println();
Serial.println("Serial Port Ready");
// Instellen Interrupt for PCF8574
pinMode(ESP8266_INTERRUPTED_PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ESP8266_INTERRUPTED_PIN), pcfInterruptOnPCF8574, FALLING);
// Instellen ALL ports as Input on PCF8574
for(int i=0;i<8;i++) {
pcf8574.pinMode(i, INPUT);
}
// Instellen used "LED" as Output on PCF8574
pcf8574.pinMode(Led1.ledPin, OUTPUT);
pcf8574.pinMode(Led2.ledPin, OUTPUT);
// Instellen used "BEEPER" as Output on PCF8574
pcf8574.pinMode(Beep1.beepPin, OUTPUT);
pcf8574.begin();
Serial.println("Application has been started");
// Switch "LED" OFF on PCF8574
pcf8574.digitalWrite(Led1.ledPin,HIGH);
pcf8574.digitalWrite(Led2.ledPin,HIGH);
// Switch "Beeper" OFF on PCF8574
pcf8574.digitalWrite(Beep1.beepPin,HIGH);
// Delay before Start...
//delay(2000);
}
void LedBlink(LED &whichLed) {
// Check if the LED needs to be Switched (once every ledOnOffTime msec.)
if (currentTime - whichLed.ledLastChanged > whichLed.ledOnOffTime) { // Instead of Delay()
if (whichLed.ledIsON) {
pcf8574.digitalWrite(whichLed.ledPin,HIGH);
whichLed.ledIsON = false;
} else {
pcf8574.digitalWrite(whichLed.ledPin,LOW);
whichLed.ledIsON = true;
}
// Keep track of when we were here last (no more than every ledOnOffTime msec.)
whichLed.ledLastChanged = currentTime;
}
}
void Beep(BEEPER &whichBeep) {
if(whichBeep.beeperIsON == true) {
if (whichBeep.beepCountDown >= 0) {
if ((currentTime - whichBeep.beepLastChanged) >= whichBeep.lowDuration) {
whichBeep.beepLastChanged = currentTime;
pcf8574.digitalWrite(whichBeep.beepPin,HIGH);
whichBeep.beeperIsON = false;
// For keeping track of counting beeps (1 full beep cycle finished)
if ((whichBeep.beepType > 0) & (whichBeep.beepType < 255)) whichBeep.beepCountDown--;
}
}
} else {
// First loop goes allway through here !!!
if ((currentTime - whichBeep.beepLastChanged) >= whichBeep.highDuration) {
whichBeep.beepLastChanged = currentTime;
pcf8574.digitalWrite(whichBeep.beepPin,LOW);
whichBeep.beeperIsON = true;
}
}
// Control the status of the beep loop
if (whichBeep.beepCountDown > 0) {
whichBeep.beepStatus = true;
} else {
if (whichBeep.beeperIsON == false) {
whichBeep.beepStatus = false;
}
}
}
void CheckRecvPcfSeq() {
unsigned long CheckTime = millis();
// Check if the Sequence needs to be handled (once every 50..100 ms, for debounce)
if (CheckTime - LastTimeSeqChanged > 50) { // Instead of Delay() after last Input char is received
// Handle the Sequence LeftTurn=BABA, RightTurn=AABB, SwitchPress=SW
if (EncoderSeq[0] == 'B') {
Serial.println("LeftTurn"); // OR DO ActionX
} else if (EncoderSeq[0] == 'A') {
Serial.println("RightTurn"); // OR DO ActionY
} else if (EncoderSeq[0] == 'S') {
Serial.println("SwitchPress"); // OR DO ActionZ
doBeeps();
} // else for adding more inputs
EncoderSeq = "";
LastTimeSeqChanged = 0;
}
}
void CheckPcfInputs() {
if (pcfInt){
//Serial.println("PCF Interrupt received !!");
PCF8574::DigitalInput val = pcf8574.digitalReadAll();
// Process read Encoder Inputs
if (val.p0==HIGH) {
// Kan-A = High
EncoderSeq += "A";
}
if (val.p1==HIGH) {
// Kan-B = High
EncoderSeq += "B";
}
if (val.p2==HIGH) {
// Switch is Pressed
EncoderSeq += "SW";
}
// // Display Encoder Inputs
// Serial.print(val.p0);
// Serial.print(" - ");
// Serial.print(val.p1);
// Serial.print(" - ");
// Serial.println(val.p2);
//
// Serial.println(EncoderSeq);
// if (val.p3==HIGH) Serial.println("KEY3 PRESSED"); // In use as an Output LED #1
// if (val.p4==HIGH) Serial.println("KEY4 PRESSED"); // In use as an Output LED #2
// if (val.p5==HIGH) Serial.println("KEY5 PRESSED"); // In use as an Output BEEPER #1
// // Still FREE to USE
// if (val.p6==HIGH) Serial.println("KEY6 PRESSED"); // NOT USED YET
// if (val.p7==HIGH) Serial.println("KEY7 PRESSED"); // NOT USED YET
// Timer for processing every 50..100 msec.
LastTimeSeqChanged = millis();
pcfInt = false;
}
}
void doBeeps()
{
// Check (and SOUND) the BEEPER
if (Beep1.beepStatus == false) {
//Serial.println("Prepare new Start of the Beeper Loop");
// Setup of the Beeper(s)
Beep1.beepPin = 5; // Pin used
Beep1.beepType = 4; // 0 = Stop Beeping, 1..254 = NumBeeps, 255 = Continuous Beeps
Beep1.beepCountDown = 4; // Starts the same as Num Beeps, counts down to 0 (if > 0 and < 255)
Beep1.highDuration = 75; // Time the Beeper is OFF
Beep1.lowDuration = 75; // Time the Beeper is ON
Beep1.beepLastChanged = 0; // Time of last change
Beep1.beepStatus = true; // Start running the above Set functionality of Beeps
}
}
void loop()
{
// use here to prohibit when Blinking of the Leds is a problem to get out of Sync !!!
currentTime = millis();
// Check (and CHANGE) the LED
LedBlink(Led1);
LedBlink(Led2);
// Only do Beep1 if told to run (in doBeeps(), for now triggered by pressing the EncoderSwitch)
if (Beep1.beepStatus == true) Beep(Beep1);
// Check the PCF Inputs
CheckPcfInputs();
CheckRecvPcfSeq();
}
`