user11174: I've had a project running successfully for months on an Arduino Mega, and today I tried to swap the Mega for a Due to increase the speed. After making the change, the entire project is working successfully except for a strange problem with the pushbuttons.
I have 5 momentary pushbuttons that toggle different controls (they simply send a wireless signal to toggle different AC outlets). After moving the project to the Due, when 1 button is pressed, it ends up toggling 2 other buttons at the same time.
Originally I was using the internal pullups to detect when the buttons were low, but also I've tried connecting them to the Due's 3.3v to detect when they're high, and both times I experienced the exact same behavior.
Is there any reason why there would be this difference in pushbutton-reading behavior between the Mega and the Due? Could it be that the Due is more sensitive to noise? How could I fix this?
The wires connecting to the pushbuttons run about 8 feet. I never had a problem with this setup while running the sketch on the Mega.
Below is the relevant code that detects button presses:
#include <Wire.h>
#include <SPI.h>
#include <Ethernet.h>
#include <RCSwitch.h>
#include <Servo.h>
#include <Event.h>
#include <Timer.h>
#include <dht.h>
#include "RTClib.h"


const byte nl1ButtonPin = 40, nl2ButtonPin = 42, nl3ButtonPin = 44,  pumpButtonPin = 5, irButtonPin = 27,

unsigned long buttonPressTime1, buttonPressTime2, buttonPressTime3, buttonPressTime4, buttonPressTime5;  // when the switch last changed state

byte oldButtonState1 = HIGH, oldButtonState2 = HIGH, oldButtonState3 = HIGH, oldButtonState4 = HIGH, oldButtonState5 = HIGH;

const unsigned long debounceTime = 100;

void setup() {
  pinMode(nl1ButtonPin, INPUT_PULLUP); pinMode(nl2ButtonPin, INPUT_PULLUP); pinMode(nl3ButtonPin, INPUT_PULLUP); pinMode(pumpButtonPin, INPUT_PULLUP); pinMode(irButtonPin, INPUT_PULLUP);
}

void loop() {
 byte buttonState1 = digitalRead(nl1ButtonPin);
  if (buttonState1 != oldButtonState1)
  {
    if (millis () - buttonPressTime1 >= debounceTime)
    {
  buttonPressTime1 = millis ();  // when we closed the switch
  oldButtonState1 = buttonState1;  // remember for next time
  if (buttonState1 == LOW) {
    Serial.println("button1 LOW!");
    toggleLight1();
   }
 }
}

   byte buttonState2 = digitalRead(nl2ButtonPin);
  if (buttonState2 != oldButtonState2)
  {
    if (millis () - buttonPressTime2 >= debounceTime)
    {
      buttonPressTime2 = millis ();  // when we closed the switch
      oldButtonState2 = buttonState2;  // remember for next time
      if (buttonState2 == LOW) {
        Serial.println("button2 LOW!");
        toggleLight2();
      }
    }
  }

byte buttonState3 = digitalRead(nl3ButtonPin);
if (buttonState3 != oldButtonState3)
{
  if (millis () - buttonPressTime3 >= debounceTime)
  {
    buttonPressTime3 = millis ();  // when we closed the switch
    oldButtonState3 = buttonState3;  // remember for next time
    if (buttonState3 == LOW) {
      Serial.println("button3 LOW!");
      toggleLight3();
    }
  }
}

byte buttonState4 = digitalRead(pumpButtonPin);
if (buttonState4 != oldButtonState4)
{
  if (millis () - buttonPressTime4 >= debounceTime)
  {
    buttonPressTime4 = millis ();  // when we closed the switch
    oldButtonState4 = buttonState4;  // remember for next time
    if (buttonState4 == LOW) {
      Serial.println("button4 LOW!");
      togglePump();
    }
  }
}

byte buttonState5 = digitalRead(irButtonPin);
if (buttonState5 != oldButtonState5)
{
  if (millis () - buttonPressTime5 >= debounceTime)
  {
    buttonPressTime5 = millis ();  // when we closed the switch
    oldButtonState5 = buttonState5;  // remember for next time
    if (buttonState5 == LOW) {
      Serial.println("button5 LOW!");
      toggleHeater();
    }
   }
  }
}

On the serial output, pressing one button shows 2 other buttons as low. So, for example, pressing button2 might show: "Button2 LOW!, Button4 LOW!, Button1 LOW!". There doesn't seem to be any clear patterns with which other 2 buttons get simultaneously pressed. Remember that this exact same code and hardware setup was working perfectly for months on the Mega, which makes me believe maybe it's something related to the Due (maybe 3.3v, maybe stronger PU resistors, etc).

user10794: I think I can explain this. You have set up a rather complex (and incorrectly wired) network of resistors. Your switch has pull-up resistors, clearly connected together, and then to the "+" pin. The other side of the switches would go to ground. 

Note that I don't have anything connected to the VCC of the switch ...

Right, so your setup looks like this:

Now with no switch pressed they will all read high due to the Due's pull-up (which by the way is around 100 k compared to the Mega's 50 k.)
Now you press a switch. The naturally grounds that switch so it reads LOW. However it also pulls down neighbouring switches through the 10 k resistor network. So each switch now is in the middle of a voltage divider. There is 20 k going to ground and a couple of 100 k going to Vcc, like this:

This voltage divider would be enough for that pin to register as LOW, and indeed that would be repeated for each pin.
Adding your carefully calculated resistor between the "-" pin and ground is just changing the voltages a bit.
The correct solution is to connect the "+" pin to Vcc so that it acts as a proper pull-up. And get rid of that resistor in series with ground.

It probably worked on the Mega because of the different pull-up resistance when you activated the internal pull-up which would have changed the calculations for the voltage divider.
I've worked out what I think the voltages will be. Note that the supposedly open switches will actually have 1.1 V on them, which as far as I can tell from the datasheet is in the "undefined" territory between LOW (max 0.99 V) and HIGH (minimum 2.31 V).
Reasoning: You can effectively consider that the 4 open switches have 4 x 110 k between them and 3.3 V in parallel. In other words, 27.5 k. With a voltage divider now between that and the 10 k to ground, you have:
10 / (10 + 27.5) * 3.3 = 880 mV

So, there will be 880 mV on the common point (which is "+" on the board).
Now for each switch you have a voltage divider of:
10 / 110 * (3.3 - 0.880) = 220 mV

Add to that the 880 mV at the common point and we have:
0.88 + 0.22 = 1.10 V


11174: <p>I've had a project running successfully for months on an Arduino Mega, and today I tried to swap the Mega for a Due to increase the speed. After making the change, the entire project is working successfully except for a strange problem with the pushbuttons.</p>

<p>I have 5 momentary pushbuttons that toggle different controls (they simply send a wireless signal to toggle different AC outlets). After moving the project to the Due, when 1 button is pressed, it ends up toggling 2 other buttons at the same time.</p>

<p>Originally I was using the internal pullups to detect when the buttons were low, but also I've tried connecting them to the Due's 3.3v to detect when they're high, and both times I experienced the exact same behavior.</p>

<p>Is there any reason why there would be this difference in pushbutton-reading behavior between the Mega and the Due? Could it be that the Due is more sensitive to noise? How could I fix this?</p>

<p>The wires connecting to the pushbuttons run about 8 feet. I never had a problem with this setup while running the sketch on the Mega.</p>

<p>Below is the relevant code that detects button presses:</p>

<pre><code>#include &lt;Wire.h&gt;
#include &lt;SPI.h&gt;
#include &lt;Ethernet.h&gt;
#include &lt;RCSwitch.h&gt;
#include &lt;Servo.h&gt;
#include &lt;Event.h&gt;
#include &lt;Timer.h&gt;
#include &lt;dht.h&gt;
#include "RTClib.h"


const byte nl1ButtonPin = 40, nl2ButtonPin = 42, nl3ButtonPin = 44,  pumpButtonPin = 5, irButtonPin = 27,

unsigned long buttonPressTime1, buttonPressTime2, buttonPressTime3, buttonPressTime4, buttonPressTime5;  // when the switch last changed state

byte oldButtonState1 = HIGH, oldButtonState2 = HIGH, oldButtonState3 = HIGH, oldButtonState4 = HIGH, oldButtonState5 = HIGH;

const unsigned long debounceTime = 100;

void setup() {
  pinMode(nl1ButtonPin, INPUT_PULLUP); pinMode(nl2ButtonPin, INPUT_PULLUP); pinMode(nl3ButtonPin, INPUT_PULLUP); pinMode(pumpButtonPin, INPUT_PULLUP); pinMode(irButtonPin, INPUT_PULLUP);
}

void loop() {
 byte buttonState1 = digitalRead(nl1ButtonPin);
  if (buttonState1 != oldButtonState1)
  {
    if (millis () - buttonPressTime1 &gt;= debounceTime)
    {
  buttonPressTime1 = millis ();  // when we closed the switch
  oldButtonState1 = buttonState1;  // remember for next time
  if (buttonState1 == LOW) {
    Serial.println("button1 LOW!");
    toggleLight1();
   }
 }
}

   byte buttonState2 = digitalRead(nl2ButtonPin);
  if (buttonState2 != oldButtonState2)
  {
    if (millis () - buttonPressTime2 &gt;= debounceTime)
    {
      buttonPressTime2 = millis ();  // when we closed the switch
      oldButtonState2 = buttonState2;  // remember for next time
      if (buttonState2 == LOW) {
        Serial.println("button2 LOW!");
        toggleLight2();
      }
    }
  }

byte buttonState3 = digitalRead(nl3ButtonPin);
if (buttonState3 != oldButtonState3)
{
  if (millis () - buttonPressTime3 &gt;= debounceTime)
  {
    buttonPressTime3 = millis ();  // when we closed the switch
    oldButtonState3 = buttonState3;  // remember for next time
    if (buttonState3 == LOW) {
      Serial.println("button3 LOW!");
      toggleLight3();
    }
  }
}

byte buttonState4 = digitalRead(pumpButtonPin);
if (buttonState4 != oldButtonState4)
{
  if (millis () - buttonPressTime4 &gt;= debounceTime)
  {
    buttonPressTime4 = millis ();  // when we closed the switch
    oldButtonState4 = buttonState4;  // remember for next time
    if (buttonState4 == LOW) {
      Serial.println("button4 LOW!");
      togglePump();
    }
  }
}

byte buttonState5 = digitalRead(irButtonPin);
if (buttonState5 != oldButtonState5)
{
  if (millis () - buttonPressTime5 &gt;= debounceTime)
  {
    buttonPressTime5 = millis ();  // when we closed the switch
    oldButtonState5 = buttonState5;  // remember for next time
    if (buttonState5 == LOW) {
      Serial.println("button5 LOW!");
      toggleHeater();
    }
   }
  }
}
</code></pre>

<p>On the serial output, pressing one button shows 2 other buttons as low. So, for example, pressing button2 might show: "Button2 LOW!, Button4 LOW!, Button1 LOW!". There doesn't seem to be any clear patterns with which other 2 buttons get simultaneously pressed. Remember that this exact same code and hardware setup was working perfectly for months on the Mega, which makes me believe maybe it's something related to the Due (maybe 3.3v, maybe stronger PU resistors, etc).</p>
 10794: <p>I think I can explain this. You have set up a rather complex (and incorrectly wired) network of resistors. Your switch has pull-up resistors, clearly connected together, and then to the "+" pin. The other side of the switches would go to ground. </p>

<blockquote>
  <p>Note that I don't have anything connected to the VCC of the switch ...</p>
</blockquote>

<p>Right, so your setup looks like this:</p>

<p><a href="https://i.stack.imgur.com/ZDmo9.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/ZDmo9.png" alt="Pull-up resistors"></a></p>

<p>Now with no switch pressed they will all read high due to the Due's pull-up (which by the way is around 100 k compared to the Mega's 50 k.)</p>

<p>Now you press a switch. The naturally grounds that switch so it reads LOW. However it also pulls down neighbouring switches through the 10 k resistor network. So each switch now is in the middle of a voltage divider. There is 20 k going to ground and a couple of 100 k going to Vcc, like this:</p>

<p><a href="https://i.stack.imgur.com/nZNKC.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/nZNKC.png" alt="Multiple presses"></a></p>

<p>This voltage divider would be enough for that pin to register as LOW, and indeed that would be repeated for each pin.</p>

<p>Adding your carefully calculated resistor between the "-" pin and ground is just changing the voltages a bit.</p>

<p>The correct solution is to connect the "+" pin to Vcc so that it acts as a proper pull-up. And get rid of that resistor in series with ground.</p>

<hr>

<p>It probably worked on the Mega because of the different pull-up resistance when you activated the internal pull-up which would have changed the calculations for the voltage divider.</p>

<p>I've worked out what I think the voltages will be. Note that the supposedly open switches will actually have 1.1 V on them, which as far as I can tell from the datasheet is in the "undefined" territory between LOW (max 0.99 V) and HIGH (minimum 2.31 V).</p>

<p>Reasoning: You can effectively consider that the 4 open switches have 4 x 110 k between them and 3.3 V in parallel. In other words, 27.5 k. With a voltage divider now between that and the 10 k to ground, you have:</p>

<pre><code>10 / (10 + 27.5) * 3.3 = 880 mV
</code></pre>

<p>So, there will be 880 mV on the common point (which is "+" on the board).</p>

<p>Now for each switch you have a voltage divider of:</p>

<pre><code>10 / 110 * (3.3 - 0.880) = 220 mV
</code></pre>

<p>Add to that the 880 mV at the common point and we have:</p>

<pre><code>0.88 + 0.22 = 1.10 V
</code></pre>
