Arduino buttonstate not staying low - button

I am trying to wire up a simple switch to an Arduino, as per the code below, for use in a model trainset.
When the buttonState is high, Serial.print(buttonState) shows 111111111, however, the problem I have is when buttonState should be low: Serial.print(buttonState) "flickers" between 0 and 1 like so: 000111100000101000111001.
Why is it doing this and how do I stop it? I assumed it was connections but when I simply use a wire between the 2 ports, plugging it in for on and unplugging for off I still get this issue.
int RED=6;
int YELLOW=5;
int GREEN=3;
int relaytrig = 10; // trigger on pin 10
int powertoswitch = 9; // powertoswitch
int buttonPin = 12; // switch the button comms with
int buttonState = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
// inputs
// switch input
pinMode(buttonPin,INPUT);
// outputs
// powerforswitch
pinMode(powertoswitch,OUTPUT);
// track power
pinMode(relaytrig, OUTPUT);
//signal outputs
pinMode(RED,OUTPUT);
pinMode(YELLOW,OUTPUT);
pinMode(GREEN,OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
digitalWrite(powertoswitch,HIGH);
buttonState = digitalRead(buttonPin);
if (buttonState == HIGH) {
digitalWrite(relaytrig,LOW);
digitalWrite(GREEN,LOW);
digitalWrite(RED,HIGH);
digitalWrite(YELLOW,LOW);
Serial.print(buttonState);
} else if (buttonState == LOW) {
digitalWrite(relaytrig,HIGH);
digitalWrite(GREEN,HIGH);
digitalWrite(RED,LOW);
digitalWrite(YELLOW,LOW);
Serial.print(buttonState);
}
}

Unplugging it leaves the input pin floating, and noise etc. can make a floating input pin take any value.
Depending on your connection, you need a pull-down or a pull-up resistor on the pin to make it a 1 or a 0 when nothing is connected to it.
From the code, I assume the switching wire is between 5 V (or 3.3 V for some Arduinos) and an input pin. If I'm right, you need to put a, say, 10 kΩ resistor from that input pin to ground. This will keep it 0 when there is no wire connected.
BTW you are using an IO pin (9 aka powertoswitch) to provide the plus for the switch; there's no need and you shouldn't.
Connect one end of the switch to 5 V (or 3.3 V for some Arduinos), and the other end to the input pin. Connect the input pin with the resistor to ground (GND).
There's a picture here, but they use pin 2 as the input pin, and you use pin 12.
Also, your button or wire may need debouncing, but that is another matter.

Related

How to read switches via serial port C++?

I have an arduino nano. I want to connect MX Cherry switches and detect pressing throught the serial port. What pins should i use on arduino and what code should be uploaded to the plate?
I understand that i have to power the switches so there has to be 5v pin and input pin. But i'm new to electronics so i didn't manage to figure it out.
//that's just basic code for sending a number every second via 13 pin
int i=0;
void setup() {
Serial.begin(57600);
pinMode(13, OUTPUT);
}
void loop() {
i = i + 1;
Serial.println(i);
delay(1000);
}
Basically, i need a way of sending '1' if button is pressed and '0' if it's not.
Perhaps I've misunderstood your question. Why not just read the button and send a '1' if pressed and '0' if not?
void loop(){
int buttonState = digitalRead(buttonPin);
// Assumes active low button
if (buttonState == LOW){
Serial.print('1');
}
else {
Serial.print('0');
}
delay(500);
}
Of course you probably want to add some sort of timing to that so it doesn't send thousands of 0's and 1's per second. I added a delay, but that might not be the best answer for the application you have (and chose not to share). I've also assumed that your button is wired active-LOW with a pull-up since you didn't share that either.

Arduino push button debounce

I need help with debounce of push button. Sometimes it send twice same string to serial link, and I don't know why. Could someone help me, where is a problem?
int reading;
int exbutton= LOW;
unsigned long ddelay= 200;
unsigned long last= 0;
void loop(){
reading= digitalRead(prkgbrake);
if (reading== HIGH && exbutton == LOW && millis() - last> ddelay){
if (brake == 0){
Serial.write("brake:1\n");
while( digitalRead(prkgbrake) == HIGH){
}
}
else{
Serial.write("brake:0\n");
while( digitalRead(prkgbrake) == HIGH){
}
}
last = millis();
}
Thank you in advance.
I hope you didn't copy this code from somewhere, some of the code doesn't make sense.
For instance, what is 'prkgbrake'? What is 'brake'? They are not declared. Why don't you have a 'setup()' function?
Nevertheless, debouncing can be achieved in many ways. I will just fix your code. That way you will understand what you did wrong.
int exbutton = LOW;
unsigned int _delay = 200;
int pushButton = 2;
void setup()
{
// initialize serial communication at 9600 bits per second:
Serial.begin(9600);
pinMode(pushButton, INPUT_PULLUP);
}
void loop()
{
while (digitalRead(pushButton) == LOW && exbutton == LOW)
{
if((millis() - last) > _delay)
{
Serial.println("Button Pressed");
while(digitalRead(pushButton) == LOW);
}
}
last = millis();
}
Explanantion: Assuming your pushbutton is connected with digital pin 2. When you use a digital pin with a button it is better to use pullup/pulldown. You can use external resistor or the internal resistor for that. The internal resistor only supports Pull-up.
To know more about pull-up/-down checkout this Arduino page. The bottom line is when you use a pin as input it acts like an antenna and can capture signals from surroundings, known as floating state. So it is better to keep the pin in a known state. If you use internal pull-up, the pin will be always HIGH. So the button configuration has to be in a way so that when it is pressed the pin should go LOW.
Pull Up Configuration
The code pinMode(pushButton, INPUT_PULLUP); enables the digital pin 2 as input with pull-up enabled.
the loop() should work like this:
1) Check if the button is pressed (i.e. if it is LOW).
2) If not update the last variable.
3) If yes then DONT update last, and enter the while loop.
4) Now keep checking if millis()-last is greater than _delay. If not it will go back to while loop and check if the button is still pressed or not. If yes then it will come back and check if millis()-last is more than _delay or not. It will continue to do so until it passed the mentioned amount of debounce delay.
5) If button get depressed (i.e. goes to HIGH) before the '_delay' time then it will update the last and will check if button is pressed or not and will start counting the delay time.
N.B. Play with the _delay variable. It will define the responsiveness of your button.

Arduino debounce button with delay

I'm having a bit of trouble with my Arduino when I try and use long wires to a switch.
If I use a shorter wire I have no problems, but as soon as they are extended, things start playing up.
What I'm trying to do is, when I press a button I would like it to output to a pin, stay on for 2 seconds, then turn off regardless whether the button is still pressed or not.
The code I use at the moment that does work with short wires is:
// constants won't change. They're used here
// to set pin numbers:
const int buttonPin = 2; // the number of the pushbutton pin
const int ledPin = 10; // the number of the LED pin
// variables will change:
int buttonState = 0; // variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop() {
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
// check if the pushbutton is pressed.
// if it is, the buttonState is HIGH:
if (buttonState == HIGH) {
// turn LED on:
digitalWrite(ledPin, HIGH);
delay(2000); // wait for a second
digitalWrite(ledPin, LOW);
}
}
I've been reading on forums that using debounce may solve this problem. However I'm new to Arduino and not sure how to implement this.
I used the Arduino button tutorial and used a 10k pull down resistor as stated. Is there any way I can allow, either with code or with a resistor / cap, to trigger via a switch that has a wire length of <2m?
Any help appreciated.
Wire length is not going to be an issue here. You either have a wiring fault or your code doesn't match your expected behaviour. (You didn't mention what the actual behaviour is right now.)
Additional debouncing of the switch won't be necessary since after you detect a button press, you are ignoring its state for some time. That is what software debouncing typically is.
stay on for 2 seconds, then turn off regardless whether the button is still pressed or not.
Right now the output will not turn off until you release the button. The reason for this is that after you write it low, you immediately check the button again and write the output high if it's still pressed. You either need to put a delay below
digitalWrite(ledPin, LOW);
or be a little fancier and make sure the button is released before you allow another press.

Arduino RFID (Wiegand) Continuous reading

I have this RFID reader "Rosslare AY-X12", and it's working with Wiegand 26bit. I have an arduino mini Pro and connected together it's working fine but it only reads the card one time and then I have nothing.
When I put on the card arduino reads that card but only one time during the card is near by the reader and it again reads that card when I put off the card and then I put on. But I want to read that card continuously, I mean when the card is near by the Reader still reading the card, every 1ms reads that card.
Do you have any idea how to do that ? Is there any RFID arduino library which can do that? I had got the Mifare and its can do that. But this 125Khz reader which can communicate over Wiegand can't do that or I don't know how to do that.
I'm using this library : https://github.com/monkeyboard/Wiegand-Protocol-Library-for-Arduino
My previous answer was deleted. I am going to make another attempt to answer the questions.
Do you have any idea how to do that ?
This cannot be done by Arduino because Arduino in your case is just reading the D0 and D1 pulses from your RFID reader. Since your RFID reader Rosslare AY-X12 does not send out continuous output of wiegand protocol, there is no way Arduino can read more than what was not sent to it.
The common RFID readers will not send continuous data of the same card because in the common use case (entry/exit/attendance), normally one tap is to check-in and another tap is to check-out. If the RFID reader sends continuous data of the same card, the main system receiving the multiple wiegand data will be confused and will not be able to determine if the user actually wish to check-in or check-out.
Is there any RFID arduino library which can do that?
No. There is no such RFID Arduino library. If the RFID reader is not sending out continuous data, there is no way the receiver (Arduino) can receive them.
Is there a way to achieve this?
Yes, there are some readers that has the option to turn on the continuous output of data, for example 714-52 Mifare® ID Reader with selectable outputs. In its specification :
Continuous output with tag in field or single transmission
With this reader configured to continuous output, you can then use Arduino and the monkeyboard wiegand library to read the data.
I wrote my own wiegand code. Its not that difficult. I attached interrupts to the data pins and when they change I log the zero or one. You then build up the binary string and once timed out because no bits coming in. Then you convert the binary to decimal.
#include <LiquidCrystal.h>
int data0 = 2; //set wiegand data 0 pin
int data1 = 3; //set wiegand data 1 pin
unsigned long bit_holder; //unsigned long (positive 32 bit number)
unsigned long oldbit = 0;
volatile int bit_count = 0;
LiquidCrystal lcd(8, 9, 10, 11, 12, 13);
unsigned long badge;
unsigned int timeout;
unsigned int t = 800;
void setup() {
Serial.begin(9600);
lcd.begin(16, 2);
lcd.print("Present Badge");
delay(2);
Serial.println("Present Badge");
pinMode(data0, INPUT);
digitalWrite(data0, HIGH);
pinMode(data1, INPUT);
digitalWrite(data1, HIGH);
attachInterrupt(0, zero, FALLING); //attach interrupts and assign functions
attachInterrupt(1, one, FALLING);
}
void zero(){
bit_count ++;
bit_holder = (bit_holder << 1) + 0; //shift left one and add a 0
timeout = t;
}
void one(){
bit_count ++;
bit_holder = (bit_holder << 1) + 1; //shift left one and add a 1
timeout = t;
}
void loop() {
timeout --;
if (timeout == 0 && bit_count > 0){
lcd.clear();
lcd.print("Dec:");
lcd.print(bit_holder);
lcd.setCursor(0,1);
lcd.print("Hex:");
lcd.print(String(bit_holder,HEX));
Serial.print("bit count= ");
Serial.println(bit_count);
Serial.print("bits= ");
Serial.println(bit_holder,BIN);
oldbit = bit_holder; //store previous this value as previous
bit_count = 0; //reset bit count
bit_holder = 0; //reset badge number
}
}
You may need to find a reader that offer a continuously reading, as I know almost of Wiegand Reader in the market can't perform a continuously reading because they have a "onboard" control that controls this...
Maybe you can try with Arduino Serial RFID Reader...
try a this timer libary Timer1 and mayby try this code it worked for me, my tags and cards now reads continuously.
Greetings from Denmark
Gregor
#include <Timer1.h>
//******************************************************************
// ATmega168, ATmega328:
// - Using Timer 1 disables PWM (analogWrite) on pins 9 and 10
// ATmega2560:
// - Using Timer 1 disables PWM (analogWrite) on pins 11 and 12
// - Using Timer 3 disables PWM (analogWrite) on pins 2, 3 and 5
// - Using Timer 4 disables PWM (analogWrite) on pins 6, 7 and 8
// - Using Timer 5 disables PWM (analogWrite) on pins 44, 45 and 46
//******************************************************************
unsigned int lastTime;
#include <SoftwareSerial.h>
SoftwareSerial RFID = SoftwareSerial(2,4);
char character;
String our_id;
void setup()
{
// Disable Arduino's default millisecond counter (from now on, millis(), micros(),
// delay() and delayMicroseconds() will not work)
disableMillis();
// Prepare Timer1 to count
// On 16 MHz Arduino boards, this function has a resolution of 4us
// On 8 MHz Arduino boards, this function has a resolution of 8us
startCountingTimer1();
lastTime = readTimer1();
Serial.begin(9600);
RFID.begin(9600);
}
void loop()
{
unsigned int now = readTimer1();
while (RFID.available()>0)
{
character = RFID.read();
our_id += character;
lastTime = now;
}
if (our_id.length() > 10) {
our_id = our_id.substring(1,13);
Serial.println(our_id);
our_id = "";
}
delay(1000);
}

How can Arduino detect the state of an LED?

I'm working on a blinking/fading lights program for Arduino. I'm trying to build in some interactivity that's based on LED state and certain switch combinations. Consider: When a button is pressed, if an LED is ON I want to turn it off and if an LED is OFF I want to turn it on.
However, I've not been able to find any information about determining LED state. The closest was this question about Android, but I'm trying to find out if I can do this from the Arduino platform. Does anyone have any practical experience or advice?
It is absolutely OK to read output ports. That is
digitalWrite(LED_PORT, !digitalRead(LED_PORT));
will toggle the pin.
You might also want to consider the toggle library: http://playground.arduino.cc/Code/DigitalToggle
You have several options:
One, you can store the LED state in a boolean, and on button press, negate that and write it to the LED port:
void loop()
{
static int ledState = 0; // off
while (digitalRead(BUTTON_PIN) == 0)
; // wait for button press
ledState = !ledState;
digitalWrite(LED_PORT, ledState);
}
Two, if you don't mind accessing the ports of the AVR directly:
void init()
{
DDRD = 0x01; // for example: LED on port B pin 0, button on port B pin 1
PORTB = 0x00;
}
void loop()
{
while (PINB & 0x02 == 0)
; // loop until the button is pressed
PORTB ^= 0x01; // flip the bit where the LED is connected
}

Resources