Arduino : can I loop in loop()? - arduino

I'm wondering if there are any reasons not to loop inside the loop() function.
To illustrate my question, let's say I want to make a LED blink a thousand times.
Here are two ways to do it with the Arduino.
In the following one, I make sure not to "lock" the loop() function :
const int PIN_LED = 2;
const int BLINKING_LIMIT = 1000;
int blinkCount = 0;
void setup() {
// initialize serial:
pinMode(PIN_LED, OUTPUT);
}
// Here, I make sure not to "lock" the loop() function
void loop() {
blinkCount++;
if (blinkCount < BLINKING_LIMIT) {
digitalWrite(PIN_LED, HIGH);
delay(200);
digitalWrite(PIN_LED, LOW);
delay(200);
}
}
In the second one, there is a long loop (which could last even longer) in the loop() function. The Arduino is "locked" inside the for loop :
// Here, I make sure not to "lock" the loop() function
void loop() {
for (int i = 0; i < BLINKING_LIMIT; i++) {
digitalWrite(PIN_LED, HIGH);
delay(200);
digitalWrite(PIN_LED, LOW);
delay(200);
}
}
What is the best practice ? Should I care not to "lock" the loop() function, or can I just don't care ? Would an infinite loop inside the loop() function be acceptable ?

loop() and setup() are just 2 functions defined for Arduino. It will be compiled with the main code for your board.
The code of the Arduino board will be something like:
void main()
{
setup();
for(;;) {
loop();
}
}
And you just have the possibility to write the code for setup and loop.
It is like #Piglet said. It is your code and you can write it how you want.
You can not "lock" the loop, since it is not an interrupt and there is no OperatingSystem behind your loop.
Once the loop is terminated, it is called automatically again. So you can also write:
void loop()
{
for(;;) {
// your code
}
}
If you like it, so the loop will never terminate and you can write it like on a 8051 processor ;)

Just don't care. Nesting loops is super common practice in programming. Many problems cannot be solved efficiently without it.
It is your program. You may stay within a loop as long as you wish. Your Arduino won't timeout or anything.

Personally, I would use the second code. It's precise and short. Who wants to make the code long and boring. Loop will stop when you want to stop just add a condition, so don't care until and unless your code works perfectly.

If you just want to make a LED blink, it's not important but if you want to add something to your code, the behavior will be different:
void loop() {
blinkCount++;
if (blinkCount < BLINKING_LIMIT) {
digitalWrite(PIN_LED, HIGH);
delay(200);
digitalWrite(PIN_LED, LOW);
delay(200);
}
//ANYTHING ELSE
}
In this part, your LED will blink and the rest of your code will be executed in each 400ms about.
void loop() {
for (int i = 0; i < BLINKING_LIMIT; i++) {
digitalWrite(PIN_LED, HIGH);
delay(200);
digitalWrite(PIN_LED, LOW);
delay(200);
}
//ANYTHING ELSE
}
In this part, your LED will blink "BLINKING_LIMIT" times and only after, the rest of your code will be executed.
Just be careful if you want to add something.

Related

Arduino for loops not working as intended

I am new to arduino and am trying to make a for loop in it which just prints "Blink" using Serial.println(); command 3 times, however it isn't working properly and it just prints "Blink" forever and doesn't stop at all. What am I doing wrong in the code below? Would be grateful to any help.
void setup() {
Serial.begin(9600);
}
void loop() {
for(int i=0; i<3; i++){
Serial.println("Blink");
delay(500);
}
}
You put the for-loop inside the loop() function which runs endlessly.
Simply move it to setup():
void setup() {
Serial.begin(9600);
for(int i=0; i<3; i++){
Serial.println("Blink");
delay(500);
}
}
void loop() {
}
The arduino code is not a regular program. you have to keep in mind that the arduino code is an operation system which has to run endlessly Otherwise the arduino will stop. therefore there are 2 functions, the setup() that runs one time and the loop() that runs infinity times.

Problems with simplest Arduino program

Today I started what is supposed to become a great Arduino career, but I'm already stumped. I may be going crazy, but shouldn't this code blink the LED on the Mega 2560?
void setup() {
pinMode(LED_BUILTIN, OUTPUT);
}
unsigned int count = 0;
void loop() {
if(count%2) digitalWrite(LED_BUILTIN, LOW);
else digitalWrite(LED_BUILTIN, HIGH);
delay(1);
count++;
}
I know this is not elegant for a blinking LED, but this is a stripped down example for something else, where I need a counter and modulo operations on it. The 'Blink' program works, but this here doesn't.
delay()'s argument is measured in milliseconds (not seconds), so you probably want 1000 rather than 1 to observe the blinking!
delay(1000);
Official Documentation

Having both manual and automatic functions for an led

So I have come to a problem where I can not get out of a loop after I'm in it. My project is to have two functions, one for manual and another for automatic which will run forever, but I want that when I am in automatic, I will be able to get out by clicking the manual button on my phone. I don't know if that makes sense, but I really need help.
//Program to control LED (ON/OFF) from ESP32 using Serial Bluetooth
#include <Arduino.h>
#include <BluetoothSerial.h> //Header File for Serial Bluetooth, will be added by default into Arduino
BluetoothSerial ESP_BT; //Object for Bluetooth
int incoming;
int yellow_led = 13;
void setup() {
Serial.begin(9600); //Start Serial monitor in 9600
ESP_BT.begin("ESP32_LED_Control"); //Name of your Bluetooth Signal
Serial.println("Bluetooth Device is Ready to Pair");
pinMode (yellow_led, OUTPUT);//Specify that LED pin is output
}
void automatic()
{
while (incoming != 51)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
delay(1000);
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
delay(1000);
}
}
void manual()
{
if (incoming == 49)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
}
else if(incoming == 48)
{
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
}
}
void loop() {
if (ESP_BT.available()) //Check if we receive anything from Bluetooth
{
incoming = ESP_BT.read(); //Read what we recevive
Serial.print("Received:"); Serial.println(incoming);
if (incoming == 51) //#3
{
ESP_BT.println("In Manual Mode");
manual();
}
else if (incoming == 52) //#4
{
ESP_BT.println("In Automatic Mode");
automatic();
}
}
delay(20);
}
The while loop in the automatic function is unnecessary. You're already looping infinitely within loop() so that should be enough. Adding another loop, even though at first may seem like it will break, turns out to be an infinite loop. I'll get to that in a second.
So all you need to do is get rid of the while loop and it should work. However, this works only if you are guaranteed to have an incoming value for each time in the loop, which is what seems like from your code.
Another problem I see here is that if you enter say manual(), there is nothing really that changes the value of incoming, you're bound to have 51 as you're reusing the previous value and nothing no desired code path will be triggered.
Same also applies to automatic(), I hope you can see how that loop becomes infinite because of this.
So you also need something on the following lines.
void manual()
{
if (!ESP_BT.available())
return;
incoming = ESP_BT.read();
if (incoming == 49)
{
digitalWrite(yellow_led, HIGH);
ESP_BT.println("LED turned ON");
}
else if(incoming == 48)
{
digitalWrite(yellow_led, LOW);
ESP_BT.println("LED turned OFF");
}
}
Lastly, need help lol, please and thank you may not be descriptive enough for anybody to help with your problem, please go through, how to ask a good question for the next time you're posting.

Arduino infiniti tone

I am making a smoke detector.
When it detects smoke iz should alert with buzzer.
Is there any way I could make it to buzz forever until external interupt such as restart pin?
Or could I just remove timing from tone() function.
Here is the code I use.
int sensorValue;
int digitalValue;
int green = 8;
int red = 7;
void setup(){
Serial.begin(9600);
pinMode( 0, INPUT);
pinMode(green, OUTPUT);
pinMode(red, OUTPUT);
}
void start(){
digitalWrite(green, HIGH);
}
void loop() {
sensorValue = analogRead(0);
digitalValue = digitalRead(0);
Serial.println(sensorValue,DEC);
Serial.println(digitalValue,DEC);
delay(2000);
if(analogRead(0) < 100){
tone(9,200,1000);
digitalWrite(red,HIGH);
}
}
Playing a sound "forever" is straightforward:
if(analogRead(A0) < 100 ) {
tone(9,2000); // once triggered, will play the sound forever
}
To switch it off, you seem to like the RESET button. So there's no need to ever call
noTone(9);
BTW: what about reading the reference ?
There is lots of ways:
Change your logic that activate the buzzer.
while (analogRead(0) < 100){
tone(9,200,1000);
}
Just use an infinite loop:
while (1) {
tone(9,200,1000);
}
Reset the Arduino to get out of the infinite loop.
An variation on this would be to replace (1) with the code that checks a pin to exit the loop or reads the sensor.
if you're really bent on using interrupts
you didn't specify what board you're working with but
for uno the 2 3 pins can be attached as interrupts and just trigger a function that turns off the tone
check out this:
attachinterrupt

Arduino click, double click and hold button

I am trying to implement three different functions for one button in an Arduino project. Click, double click and hold.
I have to use interrupts and let the system sleep as much as possible, because the final product will have to run on a coin cell for a few months.
#include <Ports.h>
#include <RF12.h>
#include <avr/sleep.h>
#include <PinChangeInt.h>
#include <VirtualWire.h>
ISR(WDT_vect) { Sleepy::watchdogEvent(); }
char *controller;
const int buttonPin = 3;
bool stateSingle = false;
bool stateDouble = false;
bool stateLong = false;
void setup() {
pinMode(13, OUTPUT);
pinMode(6, OUTPUT);
pinMode(7, OUTPUT);
pinMode(5, OUTPUT);
// vw_set_ptt_inverted(true);
// vw_set_tx_pin(12);
// vw_setup(4000);
//
Serial.begin(9600);
PCintPort::attachInterrupt(buttonPin, wakeUp, HIGH);
}
void wakeUp() {
}
void loop() {
cli();
int i = 0;
while (digitalRead(buttonPin) == HIGH) { // Wait until button is LOW, or has been high for more than 600ms
Sleepy::loseSomeTime(50);
if (i > 12)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH)
longTapAction();
else {
i = 0;
while (digitalRead(buttonPin) == LOW) { // Wait for possible double press
Sleepy::loseSomeTime(50);
if (i > 8)
break;
i++;
}
if (digitalRead(buttonPin) == HIGH) {
doubleTapAction();
while (digitalRead(buttonPin) == HIGH)
Sleepy::loseSomeTime(50);
} else
singleTapAction();
}
}
void singleTapAction() {
stateSingle = !stateSingle;
digitalWrite(5, stateSingle ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void doubleTapAction() {
stateDouble = !stateDouble;
digitalWrite(6, stateDouble ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
void longTapAction() {
stateLong = !stateLong;
digitalWrite(7, stateLong ? HIGH : LOW);
sei();
Sleepy::powerDown();
}
The problem is that this is not always correctly working.
Because I'm using interrupts, millis() inside void loop() is not reliable, for some reason.
For any double click, and for any hold action, the single click function also gets called. I suspect this is due to multiple interrupts firing, but I have no way to test this. Also, sometimes, the double click seems to need only one click. Is my thinking wrong, did I forget something?
If you are seeing singleTapAction and doubleTapAction triggering too often, the problem could be that your method doesn't really debounce the button inputs, meaning you may read spurious noise on any click as a single press or double press. E.G your first while loop will exit almost immediately if there is a noisy input, which makes the following behavior difficult to predict.
https://www.arduino.cc/en/Tutorial/Debounce
If you have a look at the linked example on the arduino site - a possible solution is to record the period of time an input has been present and ignore any inputs of less than a certain period. Modifying your code to do this could stop the spurious calls.

Resources