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

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

Related

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

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... :)

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) { ...

I need help getting a button to activate an active buzzer using an arduino

I am trying to execute the following:
Button A is pressed, the buzzer is silent.
Button B is pressed, the buzzer is on at a predetermined frequency.
What has worked:
int buttonApin = 9;
int buttonBpin = 8;
int buzzer = 12;
void setup() {
///put everything to output
}
void loop() {
if (digitalRead(buttonApin) == LOW)
{
digitalWrite(buzzer, LOW);
}
if (digitalRead(buttonBpin == LOW)
{
digitalWrite(buzzer, HIGH);
}
This works fine. I push button A, there is no sound, then I push button B the buzzer is on and stays on until I push A again.
My issue is when I replace "digitalWrite(buzzer, High); with the following:
{
digitalWrite(buzzer, HIGH);
delay(1000);
digitalWrite(buzzer, LOW);
delay(1000);
}
When I do this and I push button B, the buzzer only does the buzzer sound for 1 second. However, when I hold the buzzer down, it preforms as desired. How can I make it so that the buzzer will continue oscillating between high and low without having to hold the button B down, and until I again push button A signaling it to stop?
One options is to use a state variable and time which switches from on to off until button is pressed. You just keep looping and record the time. When the button A is pressed light is turned off and the code waits for a button B press. It does that forever.
#define OFF 0
#define ON 1
#define BUTTON 2
static char state = ON;
static unsigned long prevTime = 0;
void loop() {
if (digitalRead(buttonApin) == HIGH)
{
state = BUTTON;
digitalWrite(buzzer, LOW);
}
if (digitalRead(buttonBpin) == HIGH)
{
state = ON;
}
if (state != BUTTON && (millis() - prevTime >= 2000)) {
digitalWrite(buzzer, HIGH);
prevTime = millis();
state = ON - state;
}
}
good day sir. may i check your schematic? i think you're connecting the buzzer and the button at the same ground. the buzzer's button should be separated from the buzzer so that the flow of electricity will not be cut if the buzzer was not pressed.

Stuck before delay in sub program

I have the task to program two timers, where I display something on my LCD-Display. I have a matrix keyboard where I can type in some basic things like numbers and some letters with this code:
void keyboard_read()
{
digitalWrite(s1, LOW);
digitalWrite(s2, HIGH);
digitalWrite(s3, HIGH);
digitalWrite(s4, HIGH);
if(digitalRead(r1) == LOW){lcd.print("1"); delay(200);k++;feld[k]=1;}
if(digitalRead(r2) == LOW){lcd.print("4"); delay(200);k++;feld[k]=4;}
if(digitalRead(r3) == LOW){lcd.print("7"); delay(200);k++;feld[k]=7;}
if(digitalRead(r4) == LOW){lcd.print("A"); delay(200);k++;feld[k]='A';}
digitalWrite(s1, HIGH);
digitalWrite(s2, LOW);
digitalWrite(s3, HIGH);
digitalWrite(s4, HIGH);
if(digitalRead(r1) == LOW){lcd.print("2"); delay(200);k++;feld[k]=2;}
if(digitalRead(r2) == LOW){lcd.print("5"); delay(200);k++;feld[k]=5;}
if(digitalRead(r3) == LOW){lcd.print("8"); delay(200);k++;feld[k]=8;}
if(digitalRead(r4) == LOW){lcd.print("0"); delay(200);k++;feld[k]=0;}
digitalWrite(s1, HIGH);
digitalWrite(s2, HIGH);
digitalWrite(s3, LOW);
digitalWrite(s4, HIGH);
if(digitalRead(r1) == LOW){lcd.print("3"); delay(200);k++;feld[k]=3;}
if(digitalRead(r2) == LOW){lcd.print("6"); delay(200);k++;feld[k]=6;}
if(digitalRead(r3) == LOW){lcd.print("9"); delay(200);k++;feld[k]=9;}
if(digitalRead(r4) == LOW){lcd.print("B"); delay(200);k++;feld[k]='B';}
digitalWrite(s1, HIGH);
digitalWrite(s2, HIGH);
digitalWrite(s3, HIGH);
digitalWrite(s4, LOW);
if(digitalRead(r1) == LOW){lcd.print("F"); delay(200);k++;feld[k]='F';}
if(digitalRead(r2) == LOW){lcd.print("E"); delay(200);k++;feld[k]='E';}
if(digitalRead(r3) == LOW){lcd.print("D"); delay(200);k++;feld[k]='D';}
if(digitalRead(r4) == LOW){lcd.print("C"); delay(200);k++;feld[k]='C';}
}
When I type in the first Timer (Timer0) keyboard_read() works just fine, but when I go into the second Timer (Timer2) keyboard_read() stops at the delay command. When I tried to put keyboard_read() in the loop() it still stops at the delay command (There isn't this command in the loop at the moment).
Code for Timer0:
ISR(TIMER0_COMPA_vect) //Durchlaufendes MenĂ¼
{
cnt0++;
//Tastatureingabe_______________________________________________________________
keyboard_read();
if(feld[k]=='A') //Abfrage nach AutoStart
{
lcd.clear(); lcd.setCursor(0,0); lcd.print("AutoStart");
TCCR0B = 0x00; //Timer0 ausschalten
TCCR2B = 0x07; //Timer2 einschalten
}
else if(feld[k]=='E') //Abfrage nach Einstellungen
{
lcd.clear(); lcd.setCursor(0,0); lcd.print("Einstellungen");
TCCR0B = 0x00; //Timer0 ausschalten
//TCCR1B = 0x00; //Timer1 einschalten (not declared yet)
k=0;
}
else if((feld[k]!=NULL)) //Falsche Eingabe Abfrage
{
lcd.clear(); lcd.setCursor(0,0); lcd.print("Falsche Eingabe");
} //other things are not necessary
Code for Timer2:
ISR(TIMER2_COMPA_vect) //Ausgabe der Parameter
{
cnt2++;
loop();
//Tastatureingabe_________________________________________________________
keyboard_read();
if(feld[k]=='B') //Abfrage nach AutoStart
{
lcd.clear(); lcd.setCursor(0,0); lcd.print("Zuruek");
TCCR0B = 0x0D; //Timer0 einschalten
TCCR2B = 0x00; //Timer2 ausschalten
}
else if((feld[k]!=NULL))
{
lcd.clear(); lcd.setCursor(0,0); lcd.print("Falsche Eingabe");
}
Do I have to change something in the keyboard_read() sub program or the Timers to make it work?
Thanks in advance for any help.
You can read long article about interrupts: How do interrupts work on the Arduino Uno and similar boards? on Arduino SE by Nick Gammon
And in short:
Interrupt must be as short as possible. If you need delay, you are doing it wrong and you can handle it in loop later. Just set some flag (or you can use COMPA overflow flag directly without its interrupt, you just have to check this flag and clear it by writing logic 1 into it)
You can't use Arduinos delay as it needs Timer/Counter 0 overflow interrupt running. And all interrupts are blocked in the ISR handler automatically. So you are waiting for changing millis that never happen.
Also you can't use anything else that could relly on another interrupt. For example Serial.write/print works until the send buffer gets filled and then deadlock will appear.
Why are you calling loop()? It'll return back to the interrupted code right after the handler finishes the job.

The arduino is skipping the if statement and just running the whole cod continuously i could not figure out how to fix it

My problem is that I am making an alarm that goes off when the temperature is greater than a preset amount. however the Arduino is going past the if statement and not stopping at the gate.
I have tried looking up different syntax however it keeps going through the if statement like it is not there while it still serial prints.
//naming the led's left to right defining the pin and the constant int
//coded by luke
// the breadboard has 6 leds lined up by order 1,2,3,4,5,6 on the corresponding pins
//6.28.2014
// second program written from scratch
// !buzzer pin 8!
// integers
const int led1=(1);
const int led2=(2);
const int led3=(3);
const int led4=(4);
const int led5=(5);
const int led6=(6);
const int buzzer=(8);
const int temp=(0);
int maxtemp=(80);
// place the buzzer at pin 8 for sound
void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);
pinMode(led6, OUTPUT);
pinMode(temp, INPUT);
Serial.begin(9600);
}
void loop()
{
delay (1000);
analogRead(temp);
delay (100);
Serial.print(analogRead(temp)/2.05);
delay (10);
if(analogRead(temp/2.05) > maxtemp)
{
tone (buzzer, 440);
delay (100); // wait to turn on the second
digitalWrite(led2, HIGH);
delay (100);
digitalWrite(led1, LOW);
delay (100);
digitalWrite (led3, HIGH);
delay (100);
digitalWrite (led2, LOW);
delay (100);
tone (buzzer, 450);
digitalWrite (led4, HIGH);
delay (100);
digitalWrite (led3, LOW);
delay (100);
digitalWrite (led5, HIGH);
delay (100);
digitalWrite (led4, LOW);
delay (100);
digitalWrite (led6, HIGH);
delay (100);
digitalWrite (led5, LOW);
delay (100);
digitalWrite (led6, LOW);
}
}
// put your main code here, to run repeatedly:
What you're printing to serial is not the same as what you're comparing to maxtemp in the if statement:
Serial.print(analogRead(temp)/2.05);
if(analogRead(temp/2.05) > maxtemp)
The former has /2.05 outside the analogRead call, the latter has it inside. Assuming the former is reporting what you expect to see, changing the if statement to:
if((analogRead(temp) / 2.05) > maxtemp)
Should fix the problem.