Arduino Nano: 1kHz Square Wave on D2 when set as Input with pull-up for button

1st post, and I am just a tinkerer so please bear with me :slight_smile:

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;
}

I chose D2 also because I am thinking about using interrupts to make the button responsive also during blocking parts of the code.

That is NEVER going to work. You are far better off writing ALL the code so that is non-blocking.

First iteration used 2 switches and works fine, but for this one I wanted to use a single momentary power button.

This strongly suggests that you leave the buttons for keeping shirts from flapping in the breeze, and stick to switches.

How IS the button sewn on?

Why are you not using the internal pullup resistor?

PaulS:
That is NEVER going to work. You are far better off writing ALL the code so that is non-blocking.

I wish I knew how to do that... As I learn more, I will.

PaulS:
This strongly suggests that you leave the buttons for keeping shirts from flapping in the breeze, and stick to switches.

How IS the button sewn on?

Why are you not using the internal pullup resistor?

My kids keep pressing the power button on Arcade 1.0, so on this one, if they do, it will put it into standby and not cause it to shutdown. A shutdown will only happen if the button is pressed for 2s or more.

As for the pull up resistor, I am using the internal one.

pinMode(pwrButton,            INPUT);
digitalWrite(pwrButton,       HIGH);

The momentary button system actually works, even with the incessant "Button Pressed!" message, however, I would like it to work properly. I was suspecting that something else in my code, such as the PWM stuff I added later, caused this issue as at first it was not repeating that message incessantly. And, as mentioned before, if I use D3, the issue goes away, and there is no square wave on the D3 pin either.

One other thing I noticed was that I had used several more Serial.println commands in the while loop and that caused massive havoc. Removing all but one, got it working again. It leads me to believe that either using Serial.println or PWM, or ??? is causing the side effect of a square wave on D2.

I tested this on 2 different Nano boards so I don't think it is broken hardware.

Any thoughts?

I found the issue.

My sketch was trying to play a beep using standard Arduino libraries on a piezo buzzer hooked up to the MCP23017 expansion board pin 2. Since the tone code was written for Arduino hardware, it was unaware that the pin 2 was actually on the IO expansion board... so it was causing the square wave on Arduino's pin 2 that I was using as an input. Problem solved.