1st post, and I am just a tinkerer so please bear with me
Project Goal: Power Up/Down and put on standby (all off except RPI) a RetroPie arcade I built. First iteration used 2 switches and works fine, but for this one I wanted to use a single momentary power button. The code pasted below is not complete and I cut it down more to get below 9k chrs.
Issue: I was seeing an endless sequence of "Button Pressed!" on the Serial Monitor, instead of one after each button press. In troubleshooting I found that the issue is caused by the presence of a 1kHz square wave on D2. If I make my input D3, the square wave is not there. However, I need to use PWM on D3 for the pulsing Power Led when on standby. I chose D2 also because I am thinking about using interrupts to make the button responsive also during blocking parts of the code.
#include <DFRobot_MCP23017.h>
DFRobot_MCP23017 mcp(Wire, 0x27);
#define ON HIGH
#define OFF LOW
#define BTN_PRESSED LOW
#define BTN_DEPRESSED HIGH
// MCP20317 IO Expander
#define monitorPwr mcp.eGPA0 // SSR
#define unused mcp.eGPA1 // Unusued output
#define beeper2 mcp.eGPA2 // Active Beeper (no tone)
#define coolerFanPwr mcp.eGPA3 // PWM / MOSFET
#define controlButtonsLedPwr mcp.eGPA4 // Relay 1
#define sbcPwr mcp.eGPA5 // Relay 2
#define amplifierPwr mcp.eGPA6 // Relay 3
#define marqueeLedPwr mcp.eGPA7 // Relay 4
// Arduino
const int pwrButton = 2;
const int pwrButtonLed = 3;
const int GPIO17_Shutdown = 8;
const int GPIO18_Shutdown = 9;
const int beeper = 10;
const int marqueeLedPWM = 11;
// Variables below declared as volatile only to allow tinkering with interrupts
volatile boolean pwrButtonState = false;
volatile long debounceDelay = 100;
volatile long longPressDelay = 1500;
volatile long pwrButtonPressTime = 0;
volatile long pwrButtonDePressTime = 0;
volatile long pwrButtonPressLength = 0;
volatile boolean pwrState = false;
volatile boolean pwrButtonChange = false;
volatile boolean standbyState = false;
volatile boolean standbyStateChange = false;
volatile boolean pwrButtonPressActive = false;
volatile boolean executeButtonPress = false;
const int marqueeLedBrightness = 127; // Range 0 - 255
void setup() {
Serial.begin(9600);
mcp.pinMode(mcp.eGPA, OUTPUT);
mcp.pinMode(mcp.eGPB, INPUT);
pinMode(GPIO17_Shutdown, OUTPUT);
pinMode(GPIO18_Shutdown, OUTPUT);
pinMode(pwrButtonLed, OUTPUT);
pinMode(marqueeLedPWM, OUTPUT);
pinMode(pwrButton, INPUT);
digitalWrite(pwrButton, HIGH); //Enable pull up resistor
attachInterrupt(digitalPinToInterrupt(pwrButton), pwrButtonPressed, FALLING);
}
void loop() {
/*
STATUS - Duration - Result
--------------------------------------------
Pwr OFF - Short press - PWR ON
Pwr ON - Short press - STDBY ON
Pwr ON - Short press - STDBY OFF
Pwr ON - Long press - PWR OFF
*/
while(digitalRead(pwrButton) == BTN_PRESSED) {
if(pwrButtonPressActive == false) {
pwrButtonPressActive = true;
executeButtonPress = true;
pwrButtonPressTime = millis();
Serial.println("Button Pressed!");
}
pwrButtonDePressTime = millis();
}
pwrButtonPressLength = pwrButtonDePressTime - pwrButtonPressTime;
pwrButtonPressActive = false;
// Long press, Power On, Turn Power Off
if((pwrButtonPressLength >= longPressDelay) && pwrState == true && executeButtonPress == true) {
Serial.println("Turning POWER OFF");
pwrState = false;
standbyState = false; // Turn off so at next power up, it will be off
executeButtonPress = false;
Serial.print("pwrState: ");
Serial.println(pwrState);
Serial.print("standbyState: ");
Serial.println(standbyState);
pwrButtonChange = false;
powerDown();
} else {
// Short press, Power Off, Turn Power On
if((pwrButtonPressLength >= debounceDelay) && pwrState == false && executeButtonPress == true) {
Serial.println("Turning POWER ON");
pwrState = true;
executeButtonPress = false;
Serial.print("pwrState: ");
Serial.println(pwrState);
Serial.print("standbyState: ");
Serial.println(standbyState);
pwrButtonChange = false;
powerUp();
}
// Short press, Power On, Standyby Off, Turn standby On
if((pwrButtonPressLength >= debounceDelay) && pwrState == true && standbyState == false && executeButtonPress == true) {
Serial.println("Turning STANDBY ON");
standbyState = true;
executeButtonPress = false;
Serial.print("pwrState: ");
Serial.println(pwrState);
Serial.print("standbyState: ");
Serial.println(standbyState);
pwrButtonChange = false;
standbyOn();
}
// Short press, Standyby On, Turn standby OFF
if((pwrButtonPressLength >= debounceDelay) && pwrState == true && standbyState == true && executeButtonPress == true) {
Serial.println("Turning STANDBY OFF");
standbyState = false;
executeButtonPress = false;
Serial.print("pwrState: ");
Serial.println(pwrState);
Serial.print("standbyState: ");
Serial.println(standbyState);
pwrButtonChange = false;
standbyOff();
}
}
}
void pwrButtonPressed() {
pwrButtonChange = true;
}
void powerUp() {
#ifdef DEBUG
Serial.println(F("powerUp() executing..."));
#endif
turnDevice(pwrButtonLed, ON, 0, 0);
turnMCPDevice(monitorPwr, ON, 0, 0);
turnMCPDevice(sbcPwr, ON, 0, 0);
turnMCPDevice(coolerFanPwr, ON, 0, 0);
turnMCPDevice(controlButtonsLedPwr, ON, 0, 0);
turnMCPDevice(marqueeLedPwr, ON, 500, 0);
analogWrite(marqueeLedPWM, marqueeLedBrightness);
turnMCPDevice(amplifierPwr, ON, 30000, 0);
//pwrState=true;
}
void powerDown() {
#ifdef DEBUG
Serial.println(F("powerDown() executing..."));
#endif
boolean OK2exit = false;
boolean timeout = false;
unsigned long previousMillis = 0;
unsigned long currentMillis = millis();
unsigned long period = 10000; // 10 seconds timeout
analogWrite(marqueeLedPWM, 0);
turnMCPDevice(marqueeLedPwr, OFF, 250, 0);
turnMCPDevice(controlButtonsLedPwr, OFF, 250, 0);
turnMCPDevice(amplifierPwr, OFF, 250, 0);
// Initiate SBC shutdown
#ifdef DEBUG
Serial.println(F("Signaling to SBC to shutdown..."));
#endif
digitalWrite(GPIO17_Shutdown, HIGH);
delay(1000);
digitalWrite(GPIO17_Shutdown, LOW);
digitalWrite(GPIO18_Shutdown, HIGH);
delay(2000);
digitalWrite(GPIO18_Shutdown, LOW);
previousMillis = currentMillis;
while (!OK2exit) {
currentMillis = millis();
if (currentMillis - previousMillis >= period) { timeout = true; }
if (timeout) {
turnMCPDevice(monitorPwr, OFF, 0, 0);
turnMCPDevice(sbcPwr, OFF, 0, 0);
turnMCPDevice(coolerFanPwr, OFF, 0, 0);
turnDevice(pwrButtonLed, OFF, 0, 0);
OK2exit = true;
}
}
//pwrState = false;
#ifdef DEBUG
Serial.println(F("Arcade has shutdown..."));
#endif
}
void standbyOn() {
#ifdef DEBUG
Serial.println(F("standbyOn() executing..."));
#endif
analogWrite(marqueeLedPWM, 0);
turnMCPDevice(monitorPwr, OFF, 0, 0);
turnMCPDevice(marqueeLedPwr, OFF, 250, 0);
turnMCPDevice(controlButtonsLedPwr, OFF, 250, 0);
turnMCPDevice(amplifierPwr, OFF, 250, 0);
turnDevice(coolerFanPwr, OFF, 0, 0);
//standbyState = true;
//blinkPwrButtonLed(); // Put this last as it is blocking
}
void standbyOff() {
#ifdef DEBUG
Serial.println(F("standbyOff() executing..."));
#endif
turnDevice(coolerFanPwr, ON, 0, 0);
turnMCPDevice(monitorPwr, ON, 0, 0);
turnMCPDevice(marqueeLedPwr, ON, 250, 0);
analogWrite(marqueeLedPWM, marqueeLedBrightness);
turnMCPDevice(controlButtonsLedPwr, ON, 250, 0);
turnMCPDevice(amplifierPwr, ON, 250, 0);
turnDevice(pwrButtonLed, ON, 0, 0);
//standbyState = false;
}