Author Topic: Issues reading switch input - noise?  (Read 5168 times)

rob

  • Newbie
  • *
  • Posts: 5
Issues reading switch input - noise?
« on: February 10, 2013, 12:32:28 pm »
I have two micro switches, two connections to a relay board, and an led output.  Trying to control motor direction via the relay board and getting very inconsistent results.  One switch will enable a single relay, but the other enables both which of course creates a short on the H bridge.  I have about 4 feet of wire from the DigiSpark to the switches - could this be causing the issue?
 
Here is my code:
 
int led = 1;
int motorR = 4;
int motorL = 5;
int switch1 = 0;
int switch2 = 2;
// variable declarations
int switch1State = 0;
int switch2State = 0;
 
void setup() {               
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);
  pinMode(motorR, OUTPUT);
  pinMode(motorL, OUTPUT);
  pinMode(switch1, INPUT);
  pinMode(switch2, INPUT);
  digitalWrite(motorR, HIGH);  // HIGH = off
  digitalWrite(motorL, HIGH);  // HIGH = off
}
 
void loop() {
  digitalWrite(led, HIGH);
  delay(75);
  digitalWrite(led, LOW);
  delay(75);
 
  switch1State = digitalRead(switch1);
  if (switch1State == HIGH) {
  digitalWrite(led, LOW);
  digitalWrite(motorL, LOW);
  } else {
  digitalWrite(motorL, HIGH);
  }
 
  switch2State = digitalRead(switch2);
  if (switch2State == HIGH) {
  digitalWrite(led, LOW);
  digitalWrite(motorR, LOW);
  } else {
  digitalWrite(motorR, HIGH);
  }
 
}  // end void
 
 
Any help would be appreciated
 
Thanks

bboyes

  • Newbie
  • *
  • Posts: 7
Re: Issues reading switch input - noise?
« Reply #1 on: February 10, 2013, 12:54:29 pm »
Four feet of wire is more than I would want to put on a raw AVR pin. You might want to add some protection: at least a 1K resistor in series with each I/O pin to limit the amount of unintended current you can inject. More than 20 mA or so and the pin will be fried, so 1K protects you up to about 20 volts. Wait, before everyone flames me: I am not suggesting that you want to make a habit of hooking up 20 volts to I/O pins through 1 K resistors. But the last I remember reading about how to damage controller I/O pins, it was not just voltage - you have to put enough current into the pin to cause some harm. I should review the ATiny85 data sheet, or some AVR-specific app notes about this.


Anyway, that 1K will also interfere with the ability to switch external loads, so it's not a perfect solution. You can use an external buffer (driving: 2N7000 FETs are cheap and pretty rugged). For inputs some sort of buffer with hysteris is good. You can even use an RS232 receiver (built in pulldown if memory serves) which are cheap and some have 15 KV or more of static and surge resistance. You can get them with 3.3V operation now. Something like the ADM3202 family http://www.analog.com/static/imported-files/data_sheets/ADM3202_3222_1385.pdf. There are lots of others, and a receive-only chip will require fewer components. Transceivers will give you buffers going both ways.


You can also add forward-biased diode clamps from the input to the 3v3 supply line so that any spikes can't exceed 3v3. But if you do get something extreme like connecting a 9V battery to the input, then you could fry the whole 3v3 rail. I'm not a fan of adding capacitors to input pins since they can cause other problems, but a small R-C filter might be OK in some situations. In your case I would recommend and active buffer. RS232 receivers are designed to have up to 25 feet of wire hung on them. RS485 receivers even more so.


That input pin wire will also act as an antenna. The input pullups on the AVR are some 10s of kilohms, so strong AC fields or conduction from nearby wires (AC lines driving a motor, whatever) may be able to impress enough voltage on the input to read. Try it on a spare ADC input: you'll read all kinds of random values with a floating input. The ADC doesn't have exactly the same impedance as a digital input but the idea is: floating inputs with long wires attract noise.


There are also some surge suppressor chips commonly used on Ethernet and other data lines. I can't grab a part number at the moment.


In your code try reading the pin multiple times and counting whether it reads high or low... then how to display that data from the spark... send it out an I2C port to some display? Run the same code on another Arduino which has the serial monitor window.

Mark

  • Full Member
  • ***
  • Posts: 196
Re: Issues reading switch input - noise?
« Reply #2 on: February 10, 2013, 03:26:48 pm »
rob
You don't say if you are using pullups or pulldowns on the switch inputs.
I'm sure like Arduino, if you use the internal pullups, you need to digitalWrite(switch1, HIGH) and digitalWrite(switch2, HIGH) to enable them.

I prefer using pulldown and connecting the switch between ground and the pin.
It stops the 5v getting shorted out accidently, and means the pin is protected by not having 5v (or something else) stuck up it.

You also have no debounce.
Switches are 'noisy' in that they don't just stay on the one state, (think of a tennis ball dropped onto the pavement, it bounces) and your sketch is running so fast it is very likely to pick up the bouncing, and then get delayed by 150mS while you turn the led on and off.

Consider adding a 100mS delay.
Basically read the switch, and if its high, then wait 100mS and read again, and act on the second reading.

Code: [Select]
  if (digitalRead(switch1) == HIGH)
 {
    delay(100);      //check to see the button is pressed by waiting 100mS (We can accept a delay here)
    if (digitalRead(switch1) == HIGH)
   {
      switch1State = HIGH;  //you may not need this
      digitalWrite(led, LOW);
      digitalWrite(motorL, LOW);
   }
   else
   {
      digitalWrite(motorL, HIGH);
      switch1State = LOW;  //you may not need this
    }
 }

I don't think noise is your issue, but using something like a 1k ohm resistor as the pull-up (or pull-down) should stop it.

If you do have a motor attached ensure there is a 0.1uF capacitor across the brush connections, to reduce the motor noise.
Let us know if any of this helps.


Mark

rob

  • Newbie
  • *
  • Posts: 5
Re: Issues reading switch input - noise?
« Reply #3 on: February 10, 2013, 04:17:20 pm »
Thanks for the quick responses!
 
What I did was use 3 terminal micro switches and tie the input to ground at the microswitch.  When the motor rotates to the stop and trips a switch, the imput goes from ground to +5v.   This seems to be working with no relay chatter and no unexpected motor starts.
 
I'll have to learn more about pull up / down resistors.
 
Thanks Again!
 
Rob
 

bjh

  • Newbie
  • *
  • Posts: 31
Re: Issues reading switch input - noise?
« Reply #4 on: February 10, 2013, 04:35:32 pm »

Quote
You also have no debounce.
Switches are 'noisy' in that they don't just stay on the one state, (think of a tennis ball dropped onto the pavement, it bounces) and your sketch is running so fast it is very likely to pick up the bouncing, and then get delayed by 150mS while you turn the led on and off.


Consider adding a 100mS delay.
Basically read the switch, and if its high, then wait 100mS and read again, and act on the second reading.


I usually debounce in hardware by putting a .1uF cap across the switch; it's nice to make up a few button & cap on a header modules for breadboarding and just not have to worry about it.

semicolo

  • Full Member
  • ***
  • Posts: 137
Re: Issues reading switch input - noise?
« Reply #5 on: February 10, 2013, 07:43:45 pm »
Even with a capacitor, the input may be in an unknown state if it hasn't a schmitt trigger (for example between 1.5V and 3.5V the state is unknown so it may switch beween high and low until the capacitor is sufficiently charged/discharge)

RussNelson

  • Newbie
  • *
  • Posts: 23
Re: Issues reading switch input - noise?
« Reply #6 on: February 20, 2013, 08:48:09 am »
Yeah, I agree with semicolo -- debounce in software -- it's the only reliable way.