0

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).

8
  • 1
    You need a pull-up or a pull-down, depending on how the button are wired. Are you grounding them or connecting them to Vcc? Without that you will definitely get erratic results. See Switches tutorial.
    – Nick Gammon
    Commented Oct 2, 2015 at 21:25
  • I forgot to mention that I'm using the internal pullups. Also I've tried using a 20k resistor instead of the internal pullups, but got the same results. The switches aren't toggling randomly. The problem is that when any button is pressed, it ends up toggling the other switches as well. I love your tutorials BTW, and I got my debounce code from that specific tutorial.
    – Jerry
    Commented Oct 2, 2015 at 21:48
  • Glad you like them. :) Can you post more (or all) of your code? I don't see 4 buttons being tested there, only one. You could also try a lower-value resistor (eg. 1k).
    – Nick Gammon
    Commented Oct 2, 2015 at 22:05
  • Try increasing debounceTime
    – Gerben
    Commented Oct 3, 2015 at 8:13
  • Gerben: I've tried debounceTime of 1000ms, and I got the same result. NG: Is it proper to paste all 1050 lines of code? :) I just updated the post and added more code. There might be simple typos due to the transfer. Today I'll probably be experimenting with the wiring, and also (like NG said) with different resistor values. Maybe the difference could be due to the Due's stronger PU resistors? The Mega uses between 20-50k for the PUs, and the Due uses between 50-150k. I've already tried 20k though (without the internal PUs) and that didn't work.
    – Jerry
    Commented Oct 3, 2015 at 14:13

2 Answers 2

1

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:

Pull-up resistors

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:

Multiple presses

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
3
  • Thanks , NG! That analysis is amazing. I'm glad you could confirm it was a complex and messy situation. Everything else worked fine with the board-change from Mega to Due, and in a few hours I had everything else working: servos, relays, RTC, sensors, wireless transmitters, etc. But this simple tact switch took me 2 days of debugging!
    – Jerry
    Commented Oct 6, 2015 at 12:55
  • Do you see any scenario where those on-board pullup resistors might be useful while using an Arduino?
    – Jerry
    Commented Oct 6, 2015 at 15:51
  • 1
    Sure, just use them as intended. After all, 100 k is pretty weak for a pull-up. Over a long cable run as you described (8 ft) they might be unreliable. Run an additional line for power and supply the pull-up through the board.
    – Nick Gammon
    Commented Oct 6, 2015 at 19:39
0

I finally got it working. The problem was with this 5-way tact switch being initially incompatible with the Due: http://www.ebay.com/itm/5-Channel-Way-Tactile-Switch-Breakout-Module-Converter-Adapter-Board-Arduino-/141745152805 . As you can see from the picture and the description on that page, the switch includes pullup resistors on the board. I measured those resistors at 10k Ohms. For some reason the switch worked perfectly fine with the Mega's pullup resistors, but didn't work with the Due's.

5-way tact switch

After much experimentation, I found that the switch will start working if I add a 14.7k resistor between the switch and ground. The Due's internal pullups still had to be activated, otherwise it seemed the switch was firing constantly. When I used a 10k resistor, the center button on the switch wasn't working. And when I used 20k and higher resistors, many of the buttons weren't working.

I posted this as an answer because the switch is finally working the way I want it to. But I'm still curious to know if anyone has a reason why there would be a necessity to have a 14.7k resistor on the ground of this switch in order to make it work with the Due. Note that I don't have anything connected to the VCC of the switch (though I have experimented with it before).

1
  • After I moved the switch from next to the board where I was experimenting with it, back to the end of an 8' long copper cable where it was supposed to be, the 14.7k ground-resistor trick stopped working. I ended up just removing all the on-board PU resistors, and then it worked perfectly, just like as if it was a collection of regular tact pusbutton switches.
    – Jerry
    Commented Oct 6, 2015 at 12:58

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.