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.
Related
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.
I want to make a device like Knocki(https://knocki.com), which essentially is a relay control using a vibration sensor. i can detect vibrations rn but the problem is, once i knock the relay blinks on and then turns off. i understand this is a lack of programming that is causing this. could someone help me write code which makes it so that when i knock the relay is turned on indefinitely; until I knock again to turn relay off.
And yes u can probably tell that this code is copied from somewhere(https://wiki.keyestudio.com/Ks0068_keyestudio_37_in_1_Sensor_Kit_for_Arduino_Starters#Project_21:_Vibration_Sensor).I took it from the home page of the vibration sensor. the code was initially so that every time i knocked, the onboard Arduino led lit up. Also, right now the relay is blinking faintly every time i knock(Although correctly,in sync with my knocks)
#define SensorLED 13
#define SensorINPUT 3 //Connect the sensor to digital Pin 3 which is Interrupts 1.
unsigned char state = 0;
int Relay = 5;
void setup()
{
pinMode(SensorLED, OUTPUT);
pinMode(SensorINPUT, INPUT);
attachInterrupt(1, blink, FALLING);// Trigger the blink function when the falling edge is detected
}
void loop()
{ if(state!=0)
{
state = 0;
digitalWrite(SensorLED,HIGH);
delay(500);
digitalWrite(Relay,HIGH);
}
else
digitalWrite(SensorLED,LOW);
digitalWrite(Relay,lOW);
}
void blink()//Interrupts function
{ state++;
Yes its in your code: The (bad) example works only because there is a
digitalWrite(SensorLED,HIGH);
->>> delay(500);
a delay for 1/2 sec to keep the led on.So as a check put an other delay after the relay line and it should go on for 1/2 sec too (so the led is lit 1 sec in total)
digitalWrite(SensorLED,HIGH);
delay(500);
digitalWrite(Relay,HIGH);
delay(500);
Thats just for checking -> NEXT STEP:
Get rid of the delays (see blinkwithoutdelay example in
Arduino->File->Examples->2.Digital -> blinkwithoutdelay
and introduce a second state variable e.g.
bool relayStateOn = false;
to get an independent on/off of the relay and the led.(If thats - what I understand -what you want to do)
If you feed your relay from the board, that is not the problem. Please, check the voltage in your relay when you try to set it on, if your voltage falls down, it means that this output to your relay does not supply the necessary current.
I am trying to create a working physical simulation of a traffic light intersection. I want to listen for button readings (pedestrian buttons to turn pedestrian lights green) continuously throughout the program and want to run a different function that will handle pedestrian lights if the buttons are ever pressed during the program.
I have tried it with while loops and if conditions but it just won't work because then it would read the button input at a specific point in time when I want it to read the readings constantly throughout the program and break the loop if the condition is ever untrue (while and do-while loops only check the condition at the end of the loop when I want it to check the condition throughout the loop). I also need to get which button was pressed if that possible. Then depending on which button was pressed, I want to run a function called pedes() or pedes2().
Feel free to ask if you need any clarifications.
I have posted my original code below that I want to run constantly until a button will be pressed.
Thanks!
// If at any point in time during this code, a button is pushed, I want to run a function called
pedes() or pedes2() depending on which button is pressed.
// First set of Trafiic Lights
int redT = 13 ;
int yellowT = 12;
int greenT = 11;
// First set of Pedestrian Lights
int redP = 10;
int greenP = 9;
// Second set of Traffic Lights
int redT2 = 8;
int yellowT2 = 7;
int greenT2 = 6;
// Second set of Pedestrian Lights
int redP2 = 5;
int greenP2 = 4;
// Pedestrian Buttons
int buttonT = 3;
int buttonT2 = 2;
int buttonT3 = 1;
int buttonT4 = 0;
int buttonStateT = 0;
int buttonStateT2 = 0;
int buttonStateT3 = 0;
int buttonStateT4 = 0;
// Booleans which will handle which button was pressed
void setup() {
// First set of Trafiic Lights
pinMode(redT, OUTPUT);
pinMode(yellowT, OUTPUT);
pinMode(greenT, OUTPUT);
// First set of Pedestrian Lights
pinMode(redP, OUTPUT);
pinMode(greenP, OUTPUT);
// Second set of Traffic Lights
pinMode(redT2, OUTPUT);
pinMode(yellowT2, OUTPUT);
pinMode(greenT2, OUTPUT);
// Second set of Pedestrian Lights
pinMode(redP2, OUTPUT);
pinMode(greenP2, OUTPUT);
// Pedestrian Buttons
pinMode(buttonT, INPUT);
pinMode(buttonT2, INPUT);
pinMode(buttonT3, INPUT);
pinMode(buttonP4, INPUT);
}
void loop() {
// Resetting all the traffic lights
digitalWrite(redP, HIGH); // Turns on red pedestrian LED from 1st bunch
digitalWrite(redP2, HIGH); // Turns on red pedestrian LED from 2nd bunch
digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
delay(2000);
digitalWrite(redT, LOW); // Turns off red traffic LED from 1st bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
digitalWrite(greenT, HIGH); // Turns on green traffic LED from 1st bunch
digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch
delay(10000); // Pauses program for 8 seconds
digitalWrite(greenT, LOW); // Turns off green traffic LED from 1st bunch
digitalWrite(yellowT, HIGH); // Turns on yellow traffic LED from 1st bunch
delay(3000); // Pauses program for 3 seconds
digitalWrite(yellowT, LOW); // Turns off yellow traffic LED from 1st bunch
digitalWrite(redT, HIGH); // Turns on red traffic LED from 1st bunch
delay(2000); // Pauses program for 3 seconds
digitalWrite(redT2, LOW); // Turns off red traffic LED from 2nd bunch
digitalWrite(greenT2, HIGH); // Turns on green traffic LED from 2nd bunch
delay(6000); // Pauses program for 8 seconds
digitalWrite(greenT2, LOW); // Turns off green traffic LED from 2nd bunch
digitalWrite(yellowT2, HIGH); // Turns on yellow traffic LED from 2nd bunch
delay(3000); // Pauses program for 3 seconds
digitalWrite(yellowT2, LOW); // Turns off yellow traffic LED from 2nd bunch
digitalWrite(redT2, HIGH); // Turns on red traffic LED from 2nd bunch
delay(2000); // Pauses program for 3 seconds
}
Instead of constantly polling you could use an interrupt on the button pin and set a flag or call a function from within the interrupt routine.
Also make sure to debounce the button in hardware or software.
Since you seem to be learning, here are some extra improvements you could add as an exercise:
To switch the lights you could use timer interrupts instead of delays (you could even put the mcu in sleep mode in between).
Another improvement would be to create a TrafficLight class which contains all the logic. Here is an interesting tutorial. This way you could easily create multiple objects: TrafficLight tl1(..), tl2(..); or even arrays of traffic lights (for example with the same timings).
You could then even create a class Intersection which contains all the traffic lights and the logic for that intersection.
Well if you delay for 10 seconds you cannot react to something in the meantime.
You can use millis() to implement a non-blocking delay.
https://www.arduino.cc/en/tutorial/BlinkWithoutDelay
Instead of being idle and unable to respond you spend your time with checking and responding to your button states and/or time conditions.
Avoid using delays. Delays will pause everything until the time is up, which makes everything less responsive. Delays are useful when learning how to code, but they can hinder usability if you need to react to an external sensor or button.
A better habit to get into is using timers instead of delays. This lets your code keep looping without pausing, and you can add code to check for user input more frequently.
Here is an example of what you should NOT do:
void loop() {
digitalWrite(MY_LED,HIGH);
delay(1000);
digitalWrite(MY_LED,LOW);
delay(1000);
//This code only gets reached every 2 seconds
//This means you may need to hold the button for up to
//2 seconds before it will print a message
if (digitalRead(MY_BUTTON) == LOW) {
Serial.println("You pressed the button");
}
}
You can use millis() to return the number of milliseconds since the arduino started running. Here is a basic example of a timer:
bool ledState = false;
unsigned long toggledTime = 0; //The last time we toggled the led
void loop() {
//Calculate how much time has passed since the last time
//we turned the LED on or off
unsigned long timeElapsedSinceLastToggle = millis() - toggledTime;
//If 1000ms (1s) has passed, we'll toggle the LED
if (timeElapsedSinceLastToggle > 1000) {
ledState = !ledState; //Invert the state
digitalWrite(MY_LED,ledState); //Perform the action
toggledTime = millis(); //Reset our timer to the current time
}
//This code now checks very frequently since the code above
//never uses delay()
if (digitalRead(MY_BUTTON) == LOW) {
Serial.println("You pressed the button");
}
}
I would recommend using a different timer for each LED that you want to toggle. This will make your code much more responsive, and your buttons will respond (nearly) instantly.
There is one thing you will want to be careful with regarding timers. millis() is how many milliseconds since boot, but what happens when your code runs for a very long time? millis() resets (starts over at 0) after about 50 days. For lots of people, this doesn't matter much, but it is worth keeping in mind if your code will be running indefinitely for long periods of time.
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.
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.