Empty while loop without which the code doesn't work - c++

I ran into some code for a sumo robot. I don't understand why while(BTN) is used in the code. What is the use of the while loop?
Without the first while(BTN) the code doesn't work, without the second one the robot doesn't stop. All relevant code is listed below.
#include <Wire.h>
void setup() {
//Button
pinMode(A2, INPUT);
digitalWrite(A2, HIGH);
#define BTN !digitalRead(A2)
void loop() {
Forward(0, 0); //Stop motors
delay(100);
if (BTN) { //Turn on program with button
while (BTN) {}
while (!BTN) { //stop robot if button is pushed again
//code to move the robot was included here
}
while(BTN){}
}
}

Consider the code after BTN has been expanded:
if (!digitalRead(A2)) {
while (!digitalRead(A2)) {}
while (digitalRead(A2)) {
// move code
}
while (!digitalRead(A2)) {}
}
So it’s saying:
if the button is down;
wait until it is no longer down;
then do movement code until the button is down again
and wait until it’s no longer down.
(Note This code doesn’t consider switch bounce at all, it’s likely to behave somewhat erratically.)

Related

Arduino, code hangs in weird way when a function is invoked

I have the following code behaving in a weird way, when I make a method call
#include <TimerOne.h>
#include <cppQueue.h>
#include <Arduino.h>
typedef struct Diagnostic {
String entityName;
uint16_t pin;
} Diag;
// Global setup
cppQueue q(sizeof(Diag *), 10, FIFO, false);
int ctr = 0;
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
Serial.begin(9600);
}
// Add to queue
// the loop function runs over and over again forever
void loop() {
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on (HIGH is the voltage level)
delay(2000); // wait for a second
Serial.println("After high");
digitalWrite(LED_BUILTIN, LOW); // turn the LED off by making the voltage LOW
delay(1000); // wait for a second
// Critical Section
Diag d;
Serial.println("String assignment");
d.entityName = "Front Door";
d.pin = LED_BUILTIN;
d_ptr = &d;
Serial.println("Enqueuing one");
q.push(&d);
Serial.println("Enqueued one");
Serial.println(freeMemory());
//q.pop(&d);
//Serial.println("Dequeued one" + d.entityName);
DequeueIsr();
//Serial.println("Atomic block");
//Serial.println(q.getCount());
//Serial.println("Loop end");
}
void DequeueIsr() {
Diag di;
if (!q.isEmpty())
{
Serial.println("Queue not empty");
q.pop(&di);
Serial.println("Dequeued one" + di.entityName);
Serial.println(freeMemory());
}
}
Whenever I try to pop my object in the DequeueIsr function, the code hangs after 2 or 3 iterations, there is no output on the serial monitor after that. If I just copy the code in the Dequeue method and run it in the main loop it works, it doesn't get stuck. Also this happens when I work with strings, if I remove the entityName field from Diag, it works inside the method.
Am I missing something crucial ?
What I really wanted to do was, dequeue the queue using an interrupt method using the TimerOne library. I have removed all timer related code and even a simple method call isn't working.
It looks like cppQueue copies objects using memcpy so it only works with trivially copyable objects, String is not trivially copyable so your code has undefined behaviour

Arduino, Run Time Code Error in Debouncing Voltage Time Delay Code

I am Ansh Goel, I was learning Arduino from Udemy. I am beginner to this field. I was creating a code for Debouncing the button to solve the issues of bouncing voltage. But there is error in the code. There is no Compile time error but it is run time error.
I also tried to check the code using the Serial.print() to find the where the error is, then I found that the error is in the second nested if condition. I have also mention where there is the error in the code for ease. There I am not able to get the Serial.print("A") function too to the Serial Monitor.
My main motive is to run the code so that I am able to stop bouncing voltages when a button is pressed using some delay.
It is from line 41
This is the code I used to debounce the button
const int btn_pin = 2;
const int debounce_delay = 50; //ms
// We need to remember the previous button state between loops
int btn_prev = HIGH;
int btn_state = HIGH;
unsigned long last_debounce_time = 0;
// Counter
int counter = 0;
void setup() {
Serial.begin(9600);
// Set up pins
pinMode(btn_pin, INPUT_PULLUP);
pinMode(13, OUTPUT);
}
void loop() {
int btn_read;
// Read current button state
btn_read = digitalRead(btn_pin);
//Remember when the button change state
// If the button was previously HIGH and now LOW, it's been pressed
if ( (btn_prev == HIGH) && (btn_read == LOW )) {
//Store the time it took to take the action for button press
last_debounce_time = millis();
}
//Wait before changing the state of the button
// IN THIS CONDITION THERE IS ERROR SOMEWHERE I AM NOT GETTING IT
if(millis() > (last_debounce_time + debounce_delay)){
if(btn_read != btn_state) {
Serial.println("A");
// Then store the button change value to the global variable
btn_state = btn_read;
if(btn_state == LOW) {
// Increment and print counter
counter++;
Serial.println(counter);
digitalWrite(13,HIGH);
delay(500);
digitalWrite(13,LOW);
delay(500);
}
}
}
// Remember the previous button state for the next loop iteration
btn_prev = btn_state;
}
For testing purposes, this is the circuit design on TinkerCad, that you can check online.
TinkerCad Circuit Design
Please Help me solve the issue, it will be a great help from your side for me.
There are several locations where your code could malfunction:
you're not looping properly for loop
your logic doesn't work
digitalRead doesn't work
print doesn't work
first, remove the debounce check and see if this works:
//if(millis() > (last_debounce_time + debounce_delay)){
to check all other issues, add the following right before the remaining if:
delay so you don't get endless data
print millis, last_debounce_time, debounce_delay and btn_read
end line
then run and press the button. The output will let you know what's the issue

How to break the loop in an Arduino?

I'm trying to write a simple program in Arduino, blinking of a LED.
Program is as shown below.
#define red1 13
#define amber1 12
#define green1 11
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(red1, OUTPUT);
pinMode(amber1, OUTPUT);
pinMode(green1, OUTPUT);
}
void Delay(int sec) {
for(int i=0;i<sec;i++){
if (Serial.available())
{
Button();
break;
}
delay(1);
}
}
void Light()
{
digitalWrite(red1,HIGH);
Delay(5000);
digitalWrite(red1,LOW);
digitalWrite(amber1,HIGH);
Delay(5000);
digitalWrite(amber1,LOW);
}
void Button()
{
digitalWrite(red1,LOW);
digitalWrite(amber1,LOW);
digitalWrite(green1,HIGH);
delay(1000);
digitalWrite(green1,LOW);
}
void loop()
{
Light();
}
When ever I enter a value in serial monitor Button() function is executed, it should end as soon as function completes due to a break, but this function keeps repeating continuously? How can I fix this such that whenever a serial monitor is interrupted, Button() is executed onetime and then continues with Light().
Try to replace
break;
with
return;
This will terminate the function instantly since you won't be executing other statements after the loop.
You can look at https://www.arduino.cc/reference/en/language/structure/control-structure/return/ for more info about return
As some others have briefly alluded to, you call Button many times due to the fact that you don't clear the serial interface.
Right now what happens is Delay is called, and let's say there's information available on the interface, then you call Button and break as expected, but since you don't clear the interface by reading the available information, you call Button again on the next call to Delay.
To fix this, you need to read the information from the serial interface either in the Button function or in the if statement before calling Button.

How to clear the bytes of Serial interface in an Arduino?

I'm trying to interrupt the serial monitor to execute a certain function and continue with the previous function after completion of the interrupted function, my code is as bellow
#define red1 13
#define amber1 12
#define green1 11
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(red1, OUTPUT);
pinMode(amber1, OUTPUT);
pinMode(green1, OUTPUT);
}
void Delay(int sec) {
for(int i=0;i<sec;i++){
if (Serial.available())
{
Button();
break;
}
delay(1);
}
}
void Light()
{
digitalWrite(red1,HIGH);
Delay(5000);
digitalWrite(red1,LOW);
digitalWrite(amber1,HIGH);
Delay(5000);
digitalWrite(amber1,LOW);
}
void Button()
{
digitalWrite(red1,LOW);
digitalWrite(amber1,LOW);
digitalWrite(green1,HIGH);
delay(1000);
digitalWrite(green1,LOW);
}
void loop()
{
Light();
}
Whenever I enter a value in serial monitor Button() function is executed, it should end as soon as function completes due to a break, but this function keeps repeating continuously? How can I fix this such that whenever a serial monitor is interrupted, Button() is executed onetime and then continues with Light().
I tried using a break but the serial interface buffer is not cleared so its keep continuing this function also it exits if loop, so I tried using return
void Delay(int sec) {
for(int i=0;i<sec;i++){
if (Serial.available())
{
Button();
return;
}
delay(1);
}
}
the same thing happens
the function doesn't exit it keeps repeating the same since the serial interface is not cleared from an earlier encounter, I could've used serial.available in void loop() but whenever Arduino is at delay function its sleeping so it doesn't read a serial interrupter, so I created separate Delay()
so how can I change the code to end this function and go back to Light()
but the serial interface buffer is not cleared
Then you have to clear it:
while (Serial.available())
Serial.read(); // remove 1 character

Arduino project:automatic room light controller

I am Working on an Arduino mini project. its to design an automatic room light controller using IR modules and arduino UNO R3. Before coming to my question i'd explain it a bit .Its like an arduino is connected to an IR module and a counter keeps count of people entering the room, when the room is empty light turns off automatically.But my Code isnt working the way im expecting it to work. . given below is the code for my mini project.
#define x 14 // x sensor 1
#define y 19 // y sensor 2
#define relay 2 // relay for output
int count = 0; // initialisation
// void IN() //{ count ++;} // void OUT() // { cout--; // }
void setup()
{
// put your setup code here, to run once:
pinMode(x, INPUT);
pinMode(y, INPUT);
pinMode(relay, OUTPUT);
}
void loop()
{
// put your main code here, to run repeatedly:
if(digitalRead(x)) //IN();
{
count++;
}
if (digitalRead(y)) // OUT();
{
count--;
}
if (count <= 0) {
digitalWrite(relay, LOW);
delay(20);
}
else
digitalWrite(relay, HIGH);
}
The problem with my code is that the transmitter and receiver sense interference both at the same time resulting in turning of the light while the person is still inside the room.As im new to arduino need your inputs.