Arduino: wait for serial input - arduino

I am writing a simple arduino code. I have two leds and corresponding two switches. When one switch is pressed one led is on and other is off. Then there is a Serial.read function, which reads reset from the computer. Then both switch are off. After that other switch is pressed and other led is on. My problem is when one switch is on other shouldn't be working till the Serial.read happens.But in my case, when led1 is on if I press switch2 led2 is on and led1 is off. But that is not my desired operation. I want to make the logic that when led1 is on if I press switch2 led2 shouldn't be on and wait for the Serial.read to happen. Here is my code. I need to know what should be the correction in the logic:
int switch1 = 2;
int motorled1 = 3;
int switch2 = 4;
int motorled2 = 5;
int d1=2;
int d2=3;
int reset1 = 0;
int reset2= 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
d1=digitalRead(2);
d2=digitalRead(4);
if (d1==1)
{
digitalWrite(3, HIGH);
digitalWrite(5, LOW);
if (Serial.available() > 0)
{
Serial.write(1);
}
if (Serial.available() > 0)
{
reset1 = (Serial.read());
digitalWrite(motorled1, LOW);
digitalWrite(motorled2, LOW);
}
}
else if (d2==1)
{
digitalWrite(3, LOW);
digitalWrite(5, HIGH);
if (Serial.available() > 0)
{
Serial.write(2);
}
if (Serial.available() > 0)
{
reset2 = (Serial.read());
digitalWrite(motorled1, LOW);
digitalWrite(motorled2, LOW);
}
}
}

You seem to be using some asynchronous code structure. This is a good thing, but I am not really sure if this is what you intended to do.
In its current state, the code will continue looping over and over, checking if one of the buttons is pressed.
Now, there is two ways of achieving this:
Either make a proper state machine design, which would be the preferred way
Or just wait for the serial to be available at some point.
For the second solution, you could replace
if (Serial.available() > 0)
{
reset1 = (Serial.read());
digitalWrite(motorled1, LOW);
digitalWrite(motorled2, LOW);
}
by
while (Serial.available() <= 0)
{}
reset1 = (Serial.read());
digitalWrite(motorled1, LOW);
digitalWrite(motorled2, LOW);
essentially doing nothing while there is nothing on the serial port. Of course, this will completely freeze the rest of the program, and isn't very flexible.
For the first way, there is once again multiple ways of doing it. Since you seem not to be familiar with C programming (no offense), one of the easiest ways of doing it would be to change your if (d1==1) and else if (d2==1) statements by if (d1==1 && serial_read == false) and else if (d2==1 && serial_read == true). Then, at the top of the program, add:
int serial_read = false;
if(Serial.available() > 0)
{
reset1 = (Serial.read());
serial_read = true;
}
This is the basic idea. I will let you sort out the various bugs and improvements (such as setting serial_read to false again) as an exercise.
I also strongly encourage you to read a bit about programming in general, and C programming in particular. I also advise you to try to stick to some convention for indenting your code. There is nothing worse than code with mixed indentation.

This is the answer.
int switch1 = 2;
int motorled1 = 3;
int switch2 = 4;
int motorled2 = 5;
int d1 = 0;
int d2 = 0;
int buzzer;
char reset1;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(2, INPUT);
pinMode(4, INPUT);
pinMode(3, OUTPUT);
pinMode(5, OUTPUT);
}
void loop() {
// put your main code here, to run repeatedly:
d1 = digitalRead(2);
d2 = digitalRead(4);
if (d1 == 1 && buzzer == 0) {
digitalWrite(motorled1, HIGH);
buzzer = 1;
} else if (d2 == 1 && buzzer == 0) {
digitalWrite(motorled2, HIGH);
buzzer = 2;
}
if (Serial.available() > 0) {
Serial.write(buzzer);
reset1 = Serial.read();
buzzer = 0;
if (reset1 == 'R') {
Serial.println("LED is off");
digitalWrite(motorled1, LOW);
digitalWrite(motorled2, LOW);
}
}
}

Related

running two LEDs with two buttons

I am new to Arduino programing. I am trying to get two buttons to light two LEDs like so. press button1 turn on light 1 turn off light 2, button2 turn on light 1 and 2. like indicators for speed selection.
this is the code I have so far.
const int BUTTON1 = 2;
const int BUTTON2 = 3;
const int LED1 = 9;
const int LED2 = 10;
int BUTTONstate1 = 0;
int BUTTONstate2 = 0;
void setup()
{
pinMode(BUTTON1, INPUT);
pinMode(BUTTON2, INPUT);
pinMode(LED1, OUTPUT);
pinMode(LED2, OUTPUT);
}
void loop(1)
{
BUTTONstate1 = digitalRead(BUTTON1);
if (BUTTONstate1 == HIGH);
digitalWrite(LED1, HIGH);
digitalwrite(LED2, low);
}
void loop(2)
{
BUTTONstate2 = digitalRead(BUTTON2);
if (BUTTONstate2 == HIGH)
digitalWrite(LED1, HIGH);
digitalwrite(led2, HIGH);
}
when i run the code I get ERROR 19:10 error: variable or field 'loop' declared void. it is the line after void loop(1) and void loop(2).
void loop(1) and void loop(2) don't make sense.
You only implement void loop() and handle both buttons in that function.
Arduino will call loop() in an infinite loop over and over. Having two loop functions doesn't make sense and causes compiler errors.
If you want to have that functionality in two different functiosn implement them using different names and call both of them inside loop()
I've never seen someone uses two void loops at one time. You have to use only one void loop(). Here is an example:
void loop() {
BUTTONstate1 = digitalRead(BUTTON1);
BUTTONstate2 = digitalRead(BUTTON2);
if (BUTTONstate1 == HIGH) {
digitalWrite(LED1, HIGH);
digitalwrite(LED2, LOW);
}
if (BUTTONstate2 == HIGH) {
digitalWrite(LED1, HIGH);
digitalwrite(LED2, HIGH);
}
}
You also make another error here. Don't ever print ; after if()

Countdown once event is triggered

I'm just getting started with my Arduino and I want to operate a relay for a certain amount of time once I press a contact switch, but still be able to stop the it again at any time by pressing the button again. I've got the press the button to start and stop working Ok, but can't get the timer bit to work at all. Below is what I've got working so far.
TIA.
void setup()
{
Serial.begin(9600);
pinMode(7, INPUT);
pinMode(6, INPUT);
pinMode(3, OUTPUT);
pinMode(4, OUTPUT);
pinMode(5, OUTPUT);
pinMode(6, OUTPUT);
}
void loop()
{
Serial.print("Pin 7 ");
Serial.println(digitalRead(7));
if (digitalRead(6) == LOW && digitalRead(7) == HIGH) {
digitalWrite(3, HIGH);
digitalWrite(4, HIGH);
digitalWrite(5, HIGH);
digitalWrite(6, HIGH);
delay(250); // Wait for 250 millisecond(s)
}
if (digitalRead(6) == HIGH && digitalRead(7) == HIGH) {
digitalWrite(3, LOW);
digitalWrite(4, LOW);
digitalWrite(5, LOW);
digitalWrite(6, LOW);
delay(250); // Wait for 250 millisecond(s)
}
}
bool buttonState = 0, buttonStateBefore = 0;
bool toggle = 0;
unsigned long timeNow = 0;
buttonState = digitalRead(buttonPin);
if(buttonState > buttonStateBefore) {
toggle = !toogle; // negates the toogle
timeNow = millis(); // milliseconds to the time you press the button
}
buttonStateBefore = buttonState;
if(toggle && millis() < timeNow + delayTime) {
// relay on
}
else {
// relay off
}
Explanation:
When you press the button, buttonState beign now one, is bigger than the buttonStateBefore. So the if-statement is true. The variable toggle is now true and the time is set to the amount of milliseconds after starting the arduino. After the first if the buttonStateBefore is set to be the buttonState, to not toggle the toggle variable every circle. The second if-statement checks if the toggle variable is true and if the time has not exceeded. If one of the two things is not the case, the relay is turned off.
I hope this is helpful.
P.s. You can shorten your code if you use a for-loop for the digitalWrite
for(int i = 3; i < 7; i++) {
digitalWrite(i, true);
}

Implementing the function interrupt with if statements

I want to implement the function interrupt () but I don't know exactly how..In this case there is 2 for loops which can be seen in the code:I want whenever one of the 2 buttons is pressed the process inside the loop to be interrupted immediately:
void loop() {
int brightButton = digitalRead(K1);
int ldrStatus = analogRead(ldrPin);
if (brightButton == LOW && ldrStatus >= 200)
{
for (int i = 0; i < 10; i++)
{
digitalWrite(greenLed, HIGH);
tone(buzzer,400);
delay(500);
noTone(buzzer);
delay(500);
}
}
else {
digitalWrite(greenLed, LOW);
}
int tempButton = digitalRead(K2);
int valNTC = analogRead(NTC);
if (tempButton == LOW && valNTC > 512)
{
for (int i = 0; i <10; i++)
{
digitalWrite(redLed, HIGH);
tone(buzzer,450);
delay(300);
noTone(buzzer);
delay(1000);
}
}
else {
digitalWrite(redLed, LOW);
}
}
Example code from the Arduino manual:
https://www.arduino.cc/reference/en/language/functions/external-interrupts/attachinterrupt/
const byte ledPin = 13;
const byte interruptPin = 2;
volatile byte state = LOW;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, CHANGE);
}
void loop() {
digitalWrite(ledPin, state);
}
void blink() {
state = !state;
}
Note that this will interrupt the for loop and return to it once the interrupt service routine is finished.
If you want to abort the for loop check the pin state in every loop cycle and break if you want to leave the for loop or return if you want to leave loop().
Of course this is not "immediately".

Trying to make a password using an array with arduino

I am a beginner to using the arduino and I'm stuck at a certain problem. What I have is a programm that prints numbers to the console with the press of a button. What I'm trying to get is to the point that I enter 4 numbers after which it checks if it is the same as an array of numbers that I set before.
Now the problem is that I dont know how to make the programm check if the array I entered with the buttons is the same as the one I wrote before.
int b1 = 4;
int bs1 = 0;
int b2 = 2;
int bs2 = 0;
int b3 = 3;
int bs3 = 0;
int count = 0;
int correctcode[] = {2,3,3,1};
int code[4];
void setup() {
// put your setup code here, to run once:
pinMode(greenPin, OUTPUT);
pinMode(redPin, OUTPUT);
pinMode (b1, INPUT);
pinMode (b2, INPUT);
pinMode (b3, INPUT);
Serial.begin(9600);
}
void loop() {
// put your main code here, to run repeatedly:
bs1 = digitalRead(b1);
bs2 = digitalRead(b2);
bs3 = digitalRead(b3);
if (bs1 == HIGH) {
count++;
Serial.print ("1");
delay(500);
if (count == 4){
Serial.println ("pincode ingevoerd, checking....");
}
}
if (bs2 == HIGH) {
count++;
Serial.print ("2");
delay(500);
if (count == 4){
Serial.println ("pincode ingevoerd, checking....");
}
}
if (bs3 == HIGH) {
count++;
Serial.print ("3");
delay(500);
if (count == 4){
Serial.println ("pincode ingevoerd, checking....");
}
}
}
// Button pins ( with external pulldown resistors )
const byte b1 = 4;
const byte b2 = 2;
const byte b3 = 3;
// Signal pins
const byte greenPin = 12;
const byte redPin = 13;
byte count = 0; // 0 ... 4 counted button presses
byte correctcode[4] = {2,3,3,1};
byte code[4];
void setup() {
pinMode(greenPin, OUTPUT);
pinMode(redPin, OUTPUT);
pinMode (b1, INPUT);
pinMode (b2, INPUT);
pinMode (b3, INPUT);
Serial.begin(9600);
}
void loop() {
bool bs1 = digitalRead(b1);
bool bs2 = digitalRead(b2);
bool bs3 = digitalRead(b3);
if (bs1) add(1);
else if (bs2) add(2);
else if (bs3) add(3);
}
void add( byte value ) {
Serial.print (value);
code[count++] = value;
if (count == 4) {
count=0;
if (check()) correct();
else wrong();
}
else
delay(500);
}
bool check() {
for (byte i=0; i < 4; i++) {
if (code[i] != correctcode[i]) {
return false;
}
}
return true;
}
void wrong() {
Serial.println(" -> wrong !");
digitalWrite(redPin, HIGH);
delay(1000);
digitalWrite(redPin, LOW);
}
void correct() {
Serial.println(" -> correct !");
digitalWrite(greenPin, HIGH);
delay(300);
digitalWrite(greenPin, LOW);
}
Compiled, but Untested
Don't duplicate code, but create functions. This can make code easier to read.
If you do not want an autorepeat ( after 500 ms ) for your buttons, better check for state changes (Pressed -> Released)
If multiple buttons are pressed, I added a priority. You might want to discard that state instead.
For more than 3 buttons, read about arrays :)

How can I set a ceratin time interval for reading input in my Arduino game?

I'm making a game with my Arduino Uno.
4 leds on the breadboards are displaying a random binary number.
The player needs to press the button to put in the number that he sees
(for example, if the leds are 0011, push the button 3 times).
If he guessed right, he wins (another led blinks). If not, he loses (led turns on and stays on).
But I want the player to automatically lose if he hasn't pressed a button for two seconds.
But I'm really a beginner so bear with me. Below I'll post what I've got so far. But it's not exactly working. When I turn it on, without me pressing the button, it just goes straight to "you win" and the next round. What am I doing wrong?
int led1 = 9;
int led2 = 6;
int led3 = 5;
int led4 = 3;
int ledResult = 13; //will blink when you won, stay on when you lost
int buttonPin = 2;
int val = 0; // variable for reading the pin status
int buttonPushCounter = 0;
int buttonState = 0;
int lastButtonState = 0;
long interval = 2000;
long randomNumber;
void setup() {
Serial.begin(9600); //starts serial communication
pinMode (led1, OUTPUT);
pinMode (led2, OUTPUT);
pinMode (led3, OUTPUT);
pinMode (led4, OUTPUT);
pinMode (ledResult, OUTPUT);
pinMode (buttonPin, INPUT);
randomSeed(analogRead(A0)); //the pin is unconnected so it'll return something random (0-1023)
}
void loop() {
randomNumber = random(1, 16);
Serial.println("Random Numbers sequence"); //just for self-check
Serial.println(randomNumber);
if (randomNumber >= 8)
{
digitalWrite (led1, HIGH);
randomNumber - 8;
}
else
{
digitalWrite (led1, LOW);
}
if (randomNumber >= 4)
{
digitalWrite (led2, HIGH);
randomNumber - 4;
}
else
{
digitalWrite (led3, LOW);
}
if (randomNumber >= 2)
{
digitalWrite (led4, HIGH);
randomNumber - 2;
}
else
{
digitalWrite (led1, LOW);
}
if (randomNumber = 1)
{
digitalWrite (led2, HIGH);
}
else
{
digitalWrite (led1, LOW);
}
unsigned long currentMillis = millis();
if (currentMillis > interval) {
Serial.println("You lost.");
digitalWrite(ledResult, HIGH);
}else{
//READ BUTTON STATE
buttonState = digitalRead(buttonPin);
// compare the buttonState to its previous state
if (buttonState != lastButtonState) {
if (buttonState == HIGH)
{
buttonPushCounter++;
Serial.println("Button push counter:");
Serial.println(buttonPushCounter);
}
// Delay a little bit to avoid bouncing
delay(50);
}
// save the current state as the last state, for next time through the loop
lastButtonState = buttonState;
if (buttonPushCounter = randomNumber) {
Serial.println("You won!");
digitalWrite(ledResult, HIGH);
delay(700);
digitalWrite(ledResult, LOW);
delay(700);
}
else
{
Serial.println("You lost.");
digitalWrite(ledResult, HIGH);
}
}
}
Essentially you'll want to have a main loop that probes/polls for user input, and if there's no input from the user on probe, then check the current millis time against when you called it for start. This will give you the elapsed time since no input was detected. If the elapsed time is greater than your threshold, you break out of the loop and check a timeout flag to see if you proceed with the button validation code or branch to the "lose" code.
Without writing the whole thing, here's a C pseudo-code mock up of the idea (commented to explain):
void loop() {
while (is_running) { // main loop
unsigned long start = millis(); // get starting probe time
bool timeout = false;
while ((buttonState = probe_input()) == no_input_val) {
/* probe_input function returned no input,
so check for timeout. If the probe_input function
did return a 'value', then this loop won't iterate
and you can check the buttonState below */
if ((millis() - start) >= interval) {
/* millis is monotonic time, so calling it, then
subtracting the value from the start value will give
us elapsed time since user did not give input. */
timeout = true;
break;
}
}
if (!timeout) {
/* button state/level code */
} else {
// lose code
}
}
}
Again, this is just pseudo-code and won't compile as you'd need to implement the probe_input function to poll for input, but it's more to illustrate what you'd need to do to get you moving in the direction you're wanting.
I hope that can help.

Resources