Arduino loop does not stop - only with smaller counters. Arduino Nano Every - c++

I cannot explain to myself why this code works properly in some cases and in some not. Here is the situation:
I am trying to switch a relay with the Arduino Nano. Therefore I took the "Blink" example as a guide. It should switch on for like 5 minutes and switch off for like 25 minutes. Here is the code:
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, OUTPUT); // sets PIN 2 as switcher for the relay
}
// the loop function runs over and over again forever
void loop() {
int count = 0;
int run_pump = 300; // 5 Min run
int stop_pump = 1500; // 25 Min stop
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (HIGH is the voltage level)
digitalWrite(2, HIGH); // turn the pump on
while(count < run_pump) {
count++;
delay(1000); // wait for a second
}
count = 0;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage LOW
digitalWrite(2, LOW); // turn the pump off
while(count < stop_pump) {
count++;
delay(1000); // wait for a second
}
}
if I run this code on the Arduino it will just switch on the relay forever. BUT: If I set run_pump and stop_pump for like 10 sec. it will work properly! Is there an explanation why this does not work with the bigger counters? It's so confusing....
so this code here works absolutely fine, but why does the code above not?
// the setup function runs once when you press reset or power the board
void setup() {
// initialize digital pin LED_BUILTIN as an output.
pinMode(LED_BUILTIN, OUTPUT);
pinMode(2, OUTPUT); // sets PIN 2 as switcher for the relay
}
// the loop function runs over and over again forever
void loop() {
int count = 0;
int run_pump = 5; // 5 sec run
int stop_pump = 10; // 10 sec stop
digitalWrite(LED_BUILTIN, LOW); // turn the LED off (HIGH is the voltage level)
digitalWrite(2, HIGH); // turn the pump on
while(count < run_pump) {
count++;
delay(1000); // wait for a second
}
count = 0;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on by making the voltage LOW
digitalWrite(2, LOW); // turn the pump off
while(count < stop_pump) {
count++;
delay(1000); // wait for a second
}
}
Hope someone has a clue.... Thanks!
Tom

OK guys, I solved it. The problem was a cheap relay that was trying to communicate with the Arduino... Replacing it with a better one solved the whole problem. Thanks for the idea with the LED, this brought some stones to roll... :)

Related

Read a Flashing Led in Arduino

So it's a simple problem, I have several LEDs on a board where depending on their states it will trigger a command to fire a relay. Where I am stuck is figuring out how to get the Arduino to see a blinking LED, I have tried to bypass it all together but the code got larger than we wanted so it was scrapped and I am starting all over. Any ideas would be most helpful. Here is the basic code:
int Relay = 2;
int Led = 7;
int Ball = 8;
void setup()
{
Serial.begin(115200);
pinMode(Relay, OUTPUT);
pinMode(Led, INPUT);
pinMode(Ball, OUTPUT);
}
void loop()
{
digitalWrite (Relay, HIGH);
delay (500);
digitalWrite (Relay, LOW);
delay(300);
digitalRead(Led);
if(Led == HIGH)
{
digitalWrite(Ball, HIGH);
}
if(Led == LOW)
{
digitalWrite(Ball, LOW);
}
}
digitalRead(Led) throws away the value you are reading, and if (Led == LOW) is comparing a pin number with a voltage level, which is meaningless. You mean:
level = digitalRead(Led);
if (level == HIGH) { ...

Arduino - Running an if condition for a certain amount of time

Currently working on a project where I need to turn on the motor for just 1 second if my rain sensor detects any rain. if no rain I will again rote backward for 1 second.
sensor and device that I'm using
Arduino MEGA
Rain Sensor
L298N Motor driver
but the problem is I'm unable to run the condition for 1 second.
Here is my current Arduino sketch
const int IN1 = 7;
const int IN2 = 6;
const int ENA = 9;
const int capteur_A = A0;
int val_analogique;
void setup() {
Serial.begin(9600);
pinMode(capteur_A, INPUT);
pinMode (IN1, OUTPUT);
pinMode (IN2, OUTPUT);
pinMode (ENA, OUTPUT);
}
void forward(){
analogWrite(ENA, 60);
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
}
void loop() {
val_analogique=analogRead(capteur_A);
Serial.println(val_analogique);
if(val_analogique<=300){
forward();
Serial.println("Going Forward");
}
else{
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
}
To let the Motor rotate for 1 second, you just have to wait and then stop it. You can use the delay() function to wait a specific number of milliseconds. The forward function would be:
void forward() {
analogWrite(ENA, 60); // Set power and direction for the motor
digitalWrite(IN1, LOW);
digitalWrite(IN2, HIGH);
delay(1000); // Wait for 1000 milliseconds
digitalWrite(ENA, 0); // Stop the motor
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
And for the other direction it would be exactly the same, just with the two direction ports swapped:
void backward() {
analogWrite(ENA, 60); // Set power and direction for the motor
digitalWrite(IN1, HIGH);
digitalWrite(IN2, LOW);
delay(1000); // Wait for 1000 milliseconds
digitalWrite(ENA, 0); // Stop the motor
digitalWrite(IN1, LOW);
digitalWrite(IN2, LOW);
}
Oh, and by the way, it would also be nice to call the ports OUT and not IN, as they're outputs and not inputs :)
You have to implement a simple state machine pseudo code as a starter:
long timer = 0;
bool conditionRain = false;
bool conditionNoRain = true;
setup() {}
loop() {
...
if(val_analogique<=300 && conditionRain == false) { // Condition rain detected
timer = millis(); // we start the timer
conditionRain = true; // set the state
conditionNoRain = false; // set the state
}
if (conditionRain == true && millis()-timer < 1000) { // Here is the timer check
... do motor for rain ...
}
// Assumption Since the motor should run for one second when the rain stops
if(val_analogique>=850 && conditionNoRain == false){ // Condition rain detected
timer = millis();
conditionRain = false; // set the state
conditionNoRain = true; // set the state
}
if (conditionNoRain == true && millis()-timer<1000){ // Here is the timer check
... do motor for no rain ...
}
Simple switching between states with timer function -there is no else because we always check the states if these are not fulfilled nothing should happen

Arduino shows odd behaviour with LED output in loop

Hi I am having a little trouble understanding the behaviour of what would seem a very simple issue.
I have 4 LED's and resistors linked up, with a push button. The idea is that I press the button and the LEDS light up sequentially, turning the previous one off.
This works fine, until it is time to restart the loop from the beginning where everything is ok in serial monitor, but the LEDS barely light up except number 4 which lights up normally.
Here is my code:
const int buttonPin = 6;
const int ledPin1 = 2;
const int ledPin2 = 3;
const int ledPin3 = 4;
const int ledPin4 = 5;
int buttonState = 0;
int pressed = 0;
void setup() {
{
Serial.begin (115200);
Serial.println ();
Serial.println ("Starting up");
}
pinMode(ledPin1, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);
pinMode(ledPin4, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
void loop()
{
if(digitalRead(buttonPin)==HIGH)
{
if(pressed==0)
{
pressed=1;
switch(buttonState)
{
case 0:
digitalWrite(ledPin1, LOW);
buttonState++;
break;
case 1:
digitalWrite(ledPin1, HIGH);
Serial.println ("1");
buttonState++;
break;
case 2:
digitalWrite(ledPin2, HIGH);
pinMode(ledPin1, LOW);
Serial.println ("2");
buttonState++;
break;
case 3:
digitalWrite(ledPin3, HIGH);
pinMode(ledPin2, LOW);
Serial.println ("3");
buttonState++;
break;
case 4:
digitalWrite(ledPin4, HIGH);
pinMode(ledPin3, LOW);
Serial.println ("4");
buttonState++;
break;
case 5:
digitalWrite(ledPin4, LOW);
Serial.println ("off");
buttonState=0;
return;
}
}
}
else
{
pressed=0;
}
}
Hope some of you more intelligent folks can shed some light on this unusual behaviour.
BTW I am VERY new to arduino programming so please take it easy.
You want to understand the difference between pinMode() and digitalWrite() functions.
pinMode(pin, mode) configures the specified pin to behave either as an input or an output. (doc)
digitalWrite(pin, value) writes a HIGH or a LOW value to a digital pin. (doc)
In your switch statement, you are changing pinMode from OUTPUT to INPUT.
pinMode(ledPin1, LOW)
is the same as
pinMode(ledPin1, INPUT)
because LOW and INPUT are both defined as 0x00.
When you change the pin mode to INPUT, you can no longer turn on your LED by calling digitalWrite(ledPin1, HIGH).
LED 4 works because you don't call pinMode(ledPin4, LOW) anywhere.
I think you wanted to call digitalWrite(ledPin1, LOW) instead of pinMode(ledPin1, LOW) in the switch statement.

C++ (Particle Photon) Threading with changing variable

Note: The code is designed to run on a Particle Photon. Please keep this in mind while reading my question.
I want to make a led blink based on a variable called blink_type this variable will be changed dynamically in a later stage when I implement the API call to fetch the status of something else. I'm currently simulating this behaviour in the loop() function (also tried a thread but that also didn't work).
The blinking works fine until the variable changes from 0 to 1, after that it never blinks again until I do a reset.
Below you will find my code:
// This #include statement was automatically added by the Particle IDE.
#include <httpsclient-particle.h>
// Base variables.
int led = D0;
int buzzer = D1;
// Defining blink types. 0 is normal, 1 is breathe.
int blink_type = 0;
// Set the threads
Thread *normalBlinkThread;
Thread *ledBreatherThread;
void setup() {
// Setup the outputs.
pinMode(led, OUTPUT);
pinMode(buzzer, OUTPUT);
// Create the required threads.
normalBlinkThread = new Thread("rest_status_light", normalBlink);
ledBreatherThread = new Thread("rest_status_light", hearthBeatBlink);
}
os_thread_return_t normalBlink(void*) {
// Start never ending loop
for(;;) {
if(blink_type == 0) {
// Blink led
digitalWrite(led, HIGH);
delay(3000);
digitalWrite(led, LOW);
delay(3000);
}
}
}
os_thread_return_t hearthBeatBlink(void*) {
// Start never ending loop
for(;;) {
if(blink_type == 1) {
// Blink led
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW);
delay(500);
digitalWrite(buzzer, HIGH);
delay(500);
digitalWrite(buzzer, LOW);
delay(3000);
}
}
}
void loop() {
delay(10000);
switch (blink_type) {
case 0:
blink_type = 1;
break;
case 1:
blink_type = 0;
break;
}
}
To not get confused, the "buzzer" output (D1) is currently also wired to an LED.
If there would be a better approach to blink a led in two different ways based on a dynamic variable I'm happy to adopt to this sollution!
normalBlink() and hearthBeatBlink() have delays only when (blink_type == 1). When blink_type becomes 0 there are no delays in the for loops and one of them, the first which evaluates the variable change, happily spins for eternity. Try to add a small delay in the case blink_type is 0. Hope this helps!

Arduino Loop Error: Waits several seconds to respond to input change

I am trying to write a simple control program for an Arduino Uno for an experiment I'm running at work. Quite simply it just needs to read if an input pin is high, if it is wait 10 milliseconds to turn an output pin high, hold for 10 milliseconds then go low, else the output pin is low.
My problem is that when I run this it ignores the initial delay altogether, and the output pin stays high for several seconds before going low. (using delayMicroseconds)
void setup()
{
pinMode(8, INPUT);
pinMode(13, OUTPUT);
}
void loop()
{
if (digitalRead(8) == HIGH)
{
delayMicroseconds(10000); //wait 10 milliseconds
digitalWrite(13, HIGH); // Pump on
delayMicroseconds(10000); // holds for pulse width of 10 millisecond
digitalWrite(13, LOW); // Pump off
}
else
{
}
}
I've tried setting up something simpler for debugging using the delay function to wait for a second, then turn output pin high, wait for a seconds, then turn output pin low. I did this so I could visually debug using the arduino's built in LED. the result is that it actually continues to run the loop 3 times after the input pin goes low. (using delay)
void setup()
{
pinMode(8, INPUT);
pinMode(13, OUTPUT);
}
void loop()
{
if (digitalRead(8) == HIGH)
{
delay(1000); //wait 1 second
digitalWrite(13, HIGH); // Pump on
delay(1000); // hold for 1 second
digitalWrite(13, LOW); // Pump off
}
else
{
}
}
I can't seem to figure out why it's doing this. I've looked all over and can't seem to find information about why this would happen. I might be missing something really simple, I am not an experienced coder, I just write what I need to run experiments. I've tried reading and writing to the pin register directly using c code, and switching from an if statement to a while loop, none of them fixed the problem. Any insight is greatly appreciated.
You should look at the internal pull-up resistors on the Arduino. You can debounce the signal from your button entirely with software:
void setup() {
pinMode(2, INPUT_PULLUP);
}
void loop() {
if (digitalRead(2) == LOW) // NOTE THAT PULLUPS REVERSE YOUR LOGIC
{
delay(1000); //wait 1 second
digitalWrite(13, HIGH);
delay(1000);
digitalWrite(13, LOW);
}
}