Switching a bulb ON and OFF using toggle switch in Arduino - c++

Kindly help me in the Arduino code as I am new in this field. I have Arduino code that turns the light in bulb ON and OFF using toggle switch. It is successfully running and giving output.
The following is the code:
int buttonPinBulb = 11;
int relay1 = 10;
void setup() {
pinMode(buttonPinBulb, INPUT_PULLUP);
pinMode(relay1, OUTPUT);
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
int buttonBulb = digitalRead(buttonPinBulb);
if(buttonBulb == HIGH){
digitalWrite(relay1, HIGH);
} else {
digitalWrite(relay1, LOW);
}
Serial.println(buttonBulb);
}
Before following suggestion in the comment, the output was:
Issue
Bulb is turning ON and OFF when I toggle switch ON and OFF, and the output is showing on serial monitor continuously. But I want only one value that is not repeated. Like if I toggle the switch ON, then the value shown on serial monitor should be 1 and not 11111111....
Please help me about that. How can I do that?
After following suggestion in the comment, the code is:
int buttonPinBulb = 11;
int relay1 = 10;
int buttonBulb;
void setup() {
pinMode(buttonPinBulb, INPUT_PULLUP);
pinMode(relay1, OUTPUT);
Serial.begin(115200);
Serial.println(buttonBulb);
}
void loop() {
// put your main code here, to run repeatedly:
buttonBulb = digitalRead(buttonPinBulb);
if(buttonBulb == HIGH){
digitalWrite(relay1, HIGH);
}else{
digitalWrite(relay1, LOW);
}
//Serial.println(buttonBulb);
}
And the output was:

You can use a global variable to store the current status of the button.
You may also want to debounce your button (using millis() in the below example, unless the debouncing is already done in hardware) - especially when you want to update a database each time the status changes.
int buttonPinBulb = 11;
int relay1 = 10;
int currentStatus = LOW;
// Debounce
unsigned long lastMillis = 0;
const unsigned long debounceTime = 100; // 100ms wait
void setup() {
pinMode(buttonPinBulb, INPUT_PULLUP);
pinMode(relay1, OUTPUT);
Serial.begin(115200);
}
void loop() {
unsigned long currentMillis = millis();
if ( (currentMillis - lastMillis > debounceTime)
|| (currentMillis < lastMillis)) { // protect against overflow
int buttonBulb = digitalRead(buttonPinBulb);
if (buttonBulb != currentStatus) {
digitalWrite(relay1, buttonBulb);
Serial.println(buttonBulb);
currentStatus = buttonBulb;
// update database here
}
lastMillis = currentMillis;
}
}

As you have been told in comments, just store the current value of the pin and issue digitalWrite () only if a change is required.
ccesfully running and giving output. The following is the code:
int buttonPinBulb = 11;
int relay1 = 10;
int curRel1;
void setup()
{
pinMode(buttonPinBulb, INPUT_PULLUP);
pinMode(relay1, OUTPUT);
curRel1 = digitalRead(relay1);
Serial.begin(115200);
}
void loop()
{
int buttonBulb = digitalRead(buttonPinBulb);
if(buttonBulb == HIGH)
{
digitalWrite(relay1, HIGH);
}
else
{
digitalWrite(relay1, LOW);
}
if (buttonBulb != curRel1)
{
Serial.println(buttonBulb);
curRel1 = buttonBulb;
}
}
You could also update curRel1 in loop() calling digitalRead().

Related

Turn relay on from Bluetooth for certain amount of seconds

I am working on two way communication between arduino and android phone. Currently everything is working, however I have couple of issues I have been trying to solve recently.
How I can ignite ignition for 5 seconds? I mean if IgnitionPin is on HIGH, run it for 5 seconds then automatically turn off? There is an easy way with delay, but it will not work in my case as don't want any other delays to slow up my script.
I am using Arduino Uno. I want to start my Arduino with pin in OFF position. Why pin 10 always turns ON then shuts down, even with digitalWrite(IgnitionPin, HIGH); I have tried other pins and they work fine -> turned OFF on start.
SoftwareSerial BTserial(12,13);
char choice;
const int loopDelay = 50;
int IgnitionPin = 10;
const long ignitionInterval = 5000;
int ignitionState = HIGH;
unsigned long previousMillis = 0;
void setup()
{
BTserial.begin(115200);
digitalWrite(IgnitionPin, HIGH);
pinMode(IgnitionPin, OUTPUT);
}
void loop()
{
if (BTserial.available())
{
choice = BTserial.read();
}
if( choice == 'm' )
{
ignitionState = HIGH;
digitalWrite(IgnitionPin, ignitionState);
ignitionCountTime = millis();
}
if (ignitionCountTime - previousMillis >= ignitionInterval) {
previousMillis = ignitionCountTime;
if (ignitionState == HIGH)
{
ignitionState = LOW;
}
digitalWrite(IgnitionPin, ignitionState);
}
delay(loopDelay);
}
EDIT:
SoftwareSerial BTserial(12,13);
char choice;
const int loopDelay = 50;
int IgnitionPin = 10;
unsigned long startTime;
unsigned long ignitionInterval = 30000;
unsigned long ignitionCountTime = 0;
void setup()
{
BTserial.begin(115200);
digitalWrite(IgnitionPin, HIGH);
pinMode(IgnitionPin, OUTPUT);
}
void loop()
{
if (BTserial.available())
{
choice = BTserial.read();
}
if( choice == 'm' )
{
digitalWrite(IgnitionPin, HIGH);
ignitionCountTime = millis();
}
if (ignitionCountTime - startTime >= ignitionInterval)
{
digitalWrite(IgnitionPin, LOW);
}
delay(loopDelay);
}
#1
Use the TimerOne library or setup an ISR.
Run the ISR at, 5 times per second.
uint32_t timeout = 5 * 60;
uint8_t flag = 1;
digitalWrite (myPin, HIGH);
if (timeout && flag) {
timeout--;
} else {
digitalWrite (myPin, LOW);
flag = 0;
}
OR
by checking time elapsed since some specific point in time.
unsigned long startTime;
unsigned long interval = 60000;
const byte aPin = 13;
void setup()
{
pinMode(aPin, OUTPUT);
digitalWrite(aPin, HIGH);
}
void loop()
{
if (millis() - startTime >= interval)
{
digitalWrite(aPin, LOW);
}
}
EDIT
Arduino is a microcontroller, it can do only one thing at once.
SoftwareSerial BTserial(12,13);
char choice;
const int loopDelay = 50;
int IgnitionPin = 10;
uint32_t timeout = 5 * 60;
uint8_t flag = 0;
void setup()
{
BTserial.begin(115200);
pinMode(IgnitionPin, OUTPUT);
digitalWrite(IgnitionPin, LOW);
}
void loop()
{
if (BTserial.available())
{
choice = BTserial.read();
}
if (choice == "m")
{
timeout = 5 * 60; //modify this timeout.
flag = 1;
digitalWrite(IgnitionPin, HIGH);
}
else if ((timeout > 0) && (flag == 1))
{
timeout--;
}
else
{
digitalWrite(IgnitionPin, LOW);
flag = 0;
}
delay(loopDelay);
}
#2 - In setup you are running 'digitalWrite(IgnitionPin, HIGH);' this will make it high
just use pinMode(IgnitionPin, OUTPUT); for setting pin as output pin
void setup()
{
Serial.begin(115200);
Serial.println("Enter AT commands:");
BTserial.begin(115200);
sensors.begin();
// Set Pin as an output pin
pinMode(IgnitionPin, OUTPUT);
digitalWrite(IgnitionPin, LOW);
}
If you want IgnitionPin as LOW at each restart - use 'digitalWrite(IgnitionPin, LOW);' in setup() after pinMode call.

How to call a void function within if statement (Arduino)

I wrote a code supposed to do the following: if I press one button while in loop void btnpress(), the program is sent to another function void blink2(), and then one led goes on and after 3 secs the led should go off, and it should also return to void btnpress() again via btnpress();.
The issue is that if i press the button and release, the led goes on and stay still infinitely on, program seems not to execute the following last parts digitalWrite(LED_BUILTIN, LOW); and btnpress();.
const int btnpin = 9;
int btnstate = 0;
unsigned long currentTime;
unsigned long previousTime;
const long period = 3000;
// the setup
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(btnpin, INPUT);
Serial.begin(9600);
}
// the loop
void loop()
{
btnpress();
}
void btnpress()
{
Serial.println("Press button");
delay(500);
btnstate = digitalRead(btnpin);
if (btnstate == HIGH) {
previousTime = millis();
blink2();
}
}
void blink2()
{
if (currentTime - previousTime >= period) {
Serial.println("Led on");
previousTime = currentTime;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
}
else {
Serial.println("Led off");
digitalWrite(LED_BUILTIN, LOW);
btnpress();
}
}
if I press one button while in loop void btnpress(), the program is
sent to another function void blink2(), and then one led goes on and
after 3 secs the led should go off, and it should also return to void
btnpress() again via btnpress();
According to this statement, I can suggest you to use the following code just to be sure if your functions are working according to your reqirement.
const int btnpin = 9;
int btnstate = 0;
//unsigned long currentTime;
//unsigned long previousTime;
const long period = 3000;
// the setup
void setup()
{
pinMode(LED_BUILTIN, OUTPUT);
pinMode(btnpin, INPUT);
Serial.begin(9600);
}
// the loop
void loop()
{
btnpress();
}
void btnpress()
{
Serial.println("Press button");
delay(500);
btnstate = digitalRead(btnpin);
if (btnstate == HIGH) {
// previousTime = millis();
blink2();
}
}
void blink2()
{
Serial.println("Led on");
digitalWrite(LED_BUILTIN, HIGH);
delay(3000);
Serial.println("Led off");
digitalWrite(LED_BUILTIN, LOW);
//btnpress(); It's already inside the Void loop
}
If it's working well then function call is okay.
And there has no issue with "How to call a void function within if statement (Arduino)"
The problem may be inside your if statement,
if (currentTime - previousTime >= period) {
Serial.println("Led on");
previousTime = currentTime;
digitalWrite(LED_BUILTIN, HIGH); // turn the LED on
}
here, the currentTime is not Defined.

using arduino tone function on two pin at the same time

I'm trying to make an smart car with Arduino Mega, and I need to turn both of the back wheels on for an specific time sometimes. I've been told that I can set a "digital HIGH" time using tone, But as I need them to work in a same time, Is there a way to set tone for two pins in one line or something to do instead?
Thanks for your help.
#include <Servo.h>
/////////////////////
Servo servo;
/////////////////////
int trig = 12;
int echo = 13;
long duration;
int distance;
int dist_right;
int dist_left;
int ang = 90;
unsigned int value = 255;
unsigned long tone_time = 3000;
float forward_time;
/////////////////////
int ena = 35;
int in1 = 7;
int in2 = 6;
int in3 = 5;
int in4 = 4;
int enb = 47;
/////////////////////
void setup()
{
Serial.begin(9600);
servo.attach(22);
pinMode(trig, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
pinMode(ena, OUTPUT);
pinMode(enb, OUTPUT);
pinMode(echo, INPUT);
digitalWrite(ena, HIGH);
digitalWrite(enb, HIGH);
}
void loop() {
servo.write(90);
distance = dist();
if(distance<=15)
{
for(ang;ang>=0;ang-=2)
{
servo.write(ang);
delay(30);
}
dist_right = dist();
Serial.println(dist_right);
for(ang;ang<=180;ang+=2)
{
servo.write(ang);
delay(30);
}
dist_left = dist();
Serial.println(dist_left);
for(ang;ang>=90;ang-=2)
{
servo.write(ang);
delay(30);
}
if(dist_right>=dist_left)
{
tone(in3, value, tone_time);
}
else if(dist_right<dist_left)
{
tone(in1, value, tone_time);
}
servo.write(90);
ang=90;
}
else{
forward_time=distance/25;
tone((in1,in3), value, forward_time);
}
}
int dist(){
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
duration = pulseIn(echo, HIGH);
distance= duration*0.034/2;
return distance;
}
I'm 99.99% sure, that your motors will not feel the time differencce if you turn them one by one. Try simplest case and you will see.
// Define your wheel control pins (use same as in your mega)
const int motor1Pin = 5;
const int motor1Pin = 6;
// somewhere in setup method
outputMode(motor1Pin, OUTPUT);
outputMode(motor2Pin, OUTPUT);
// Create function to turn motors and remember the time
unsigned long turnMotorsOn(int seconds) {
// turn motors ant return time when they should be stopped
return millis() + seconds * 1000;
}
// In you code check if it is time to turn off
if (millis() > timeWhenTurnMotorsOff) {
// turn them off
}

Coding arduino traffic ligth with timer and button

I need make a traffic light that works on countdown:
when number on timer == 0 or if button pressed green led should turn on
otherwise red led
There is my loop,
I tried without for loop and button worked but if I add for loop (for timer) button not responding
thank you
crosswalk_button = digitalRead(2); //That will read the state of the button, if it's pressed or not
for (int i = numberfor7digit; i >= 0; i--) { //numberfor7digit is = 9
numbers(i); //numbers is a function i wrote which shows int it takes currently i
delay(1000);
if (crosswalk_button == 0) { //If you press the button for the crosswalk on with the green one for the crosswalk
numbers(0);
greenhigh(); // green high is a function too, which turns on green light
}
// when number in 7 segment is 0 it will turn on green
else if (i == 0) {
numbers(0);
greenhigh();
}
// for any other number it turns on red
else {
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW);
}
}
}
Few things which will help you to design this system effectively are:
Use Interrupts to read the value of the button
This will make the turning on Green Light irrespective of what's been executed by the Arduino when the button is pressed.
Example: Illustration to show how to configure a button for interrupt
int interruptPin = 2; //button attached to this pin
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(interruptPin), greenhigh, LOW);
}
void loop() {
//Your code inside this loop
}
void greenhigh() {
//Your code for turning green light high
numbers(0);
digitalWrite(GREEN_LED, HIGH);
digitalWrite(RED_LED, LOW);
}
Seven Segment Display
Now, since the button is fixed writing code for seven segment display will be simpler.
Example: Illustration to show SSD working
digitalWrite(RED_LED, HIGH);
for (int i = numberfor7digit; i >= 0; i--) {
numbers(i);
delay(1000);
}
greenhigh();
delay(5000);
Conclusion
Complete code can be written as:
int interruptPin = 2; //button attached to this pin
int numberfor7digit = 9;
int GREEN_LED = 10; //TODO: Input here your actual green led
int RED_LED = 11; //TODO: Input here your actual red led
void setup() {
pinMode(interruptPin, INPUT_PULLUP);
pinMode(GREEN_LED, OUTPUT);
pinMode(RED_LED, OUTPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), greenhigh, LOW);
}
void greenhigh() {
//TODO: Your code for turning green light high
numbers(0);
digitalWrite(GREEN_LED, HIGH);
digitalWrite(RED_LED, LOW);
}
void numbers(int n) {
//Your implementaion of numbers()
}
void loop() {
digitalWrite(RED_LED, HIGH);
for (int i = numberfor7digit; i >= 0; i--) {
numbers(i);
delay(1000);
}
greenhigh();
delay(5000);
}
You have to read the status of your button every time the loop runs i.e. the for loop that you are using.
And I have also removed the delay and replaced it with an if statement similar to blink without delay example.
One more thing, there is no need to create a crosswalk_button variable
You can directly replace it with digitalRead(2)
Use this code, it should work.
void loop() {
for(int i = numberfor7digit; ; i >= 0; i--) {
static long previousMillis = 0;
if(millis() - previousMillis >= 1000) {
numbers(i);
previousMillis = millis();
}
crosswalk_button = digitalRead(2);
if(crosswalk_button == false || i == 0) {
i = 0;
numbers(i);
greenhigh();
} else {
digitalWrite(RED_LED, HIGH);
digitalWrite(GREEN_LED, LOW):
}
}
}

How can I blink a LED differently when I press a toggle button?

I'm trying to blink a LED according to press of toggle button. If I press the first toggle switch the first time, LED blinks at 5 Hz, when I press the toggle button for the second time, LED blink at 6 Hz and when I press the third time, LED turns off.
I tried using the program below, but It's not working as I wanted.
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7; // the number of the pushbutton pin
const int ledPin = 6; // the number of the LED pin
// variables will change:
int buttonState = 0;
// variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
Serial.begin(9600);
}
void loop() {
int x=0;
// read the state of the pushbutton value:
buttonState = digitalRead(buttonPin);
Serial.print(x);
// check if the pushbutton is pressed. If it is, the buttonState is HIGH:
if (buttonState == HIGH && x==0) {
// turn LED on:
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
Serial.print(x);
} else {
// turn LED off:
x = x+1;
}
if (buttonState == HIGH && x==1) {
// turn LED on:
digitalWrite(ledPin, HIGH);
delay(2000);
digitalWrite(ledPin, LOW);
delay(2000);
Serial.print(x);
} else {
// turn LED off:
digitalWrite(ledPin, LOW);
x = x+1;
}
if (buttonState == HIGH && x==2) {
// turn LED on:
digitalWrite(ledPin, HIGH);
delay(3000);
digitalWrite(ledPin, LOW);
delay(3000);
Serial.print(x);
} else {
// turn LED off:
digitalWrite(ledPin, LOW);
x = x+1;
}
if (buttonState == HIGH && x==3) {
// turn LED off:
digitalWrite(ledPin, LOW);
x = 0;
}
}
When I use this code it works for first case that is LED blinks at 1000 ms delay, but if I toggle switch it again works for first condition. How can I make it to execute second condition i.e. to blink at delay of 2000 ms?
Firstly this is your circuit. I tried this circuit and code and worked for me. I used interrupt for checking button state. And millis calculation is simple.
Frequency = 1 / Period
Period = Ton + Toff
6Hz = 1000 millis / T => T = 166 millis
166 = Ton + Toff (for %50 duty cycle Ton=Toff) => Ton = Toff = 83 millis
enter image description here
const int ledPin = 13;
const int buttonPin = 2;
int state = -1;
bool willLightOn = false;
unsigned long currentDelay = 0;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
void setup() {
pinMode(ledPin, OUTPUT);
pinMode(buttonPin, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(buttonPin), changeState, FALLING);
}
void loop() {
if(state % 3 == 0) { //6Hz
currentDelay = 83;
willLightOn = true;
} else if (state % 3 == 1) { //5Hz
currentDelay = 100;
willLightOn = true;
} else if (state % 3 == 2) { //LED off
currentDelay = 0;
willLightOn = false;
digitalWrite(ledPin, LOW);
}
currentMillis = millis();
if (currentMillis - previousMillis >= currentDelay && willLightOn) {
previousMillis = currentMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
}
}
void changeState() {
state++;
}
Right now your logic checks 3 times for the value of x in a single loop.
Below code toggles light whenever x is greater than zero. x's value is changed when button is pressed.
But there is a big problem here: If button is pressed when there's something else going on in the processor or it is sleeping (like the long delays you want to use), it may be ignored. So you better study interrupts and implement this behavior using them.
if (x > 0)
{
digitalWrite(ledPin, HIGH);
delay(1000 * x);
digitalWrite(ledPin, LOW);
}
if (buttonState == HIGH)
{
x++;
if (x > 3)
x = 0;
}
You should create a global state of the application. This state is where you remember if you are blinking at 50hz/60hz/off. Then you can use a switch to do the right thing.
Then you check if the button is pressed and change the application state.
See my example below:
// constants won't change. They're used here to set pin numbers:
const int buttonPin = 7; // the number of the pushbutton pin
const int ledPin = 6; // the number of the LED pin
// variables will change:
int applicationState = 0;
bool lightOn = true;
int currentDelay = 1000;
unsigned long currentMillis = 0;
unsigned long previousMillis = 0;
// variable for reading the pushbutton status
void setup() {
// initialize the LED pin as an output:
pinMode(ledPin, OUTPUT);
// initialize the pushbutton pin as an input:
pinMode(buttonPin, INPUT);
}
void loop() {
if (digitalRead(buttonPin) == HIGH) {
applicationState++;
if(applicationState >= 3) {
applicationState = 0;
}
delay(100);
}
switch(applicationState){
case 0:
currentDelay = 1000;
lightOn = true;
break;
case 1:
currentDelay = 2000;
lightOn = true;
break;
case 2:
digitalWrite(ledPin, LOW);
lightOn = false;
break;
}
currentMillis = millis();
if (currentMillis - previousMillis >= currentDelay && lightOn) {
previousMillis = currentMillis;
digitalWrite(ledPin, !digitalRead(ledPin));
}
}
I hope you understand what I try to say and demo with the example code.
Your code can not work:
You do need to check if the button state changes, detect when there is a edge. And make sure you detect a single edge only once.
You must repeat the blinking it in a loop till the button is pressed, then you can change the frequency.
You must check the button while you sleep, otherwise your program do not recognize when you press the button.
To make it work, you must change the complete program.
#define BLINK_SLEEP_TIME <some value> // insert value for 16.6666ms
//return 1 after a positive edge
bool button_read(void)
{
static bool lastState=1; //set this to 1, so that a pressed button at startup does not trigger a instant reaction
bool state = digitalRead(buttonPin);
if(state != lastState)
{
state=lastState;
return state;
}
return 0;
}
//Blink the LED with a given period, till button is pressed
//Times are in x*16.666ms or x/60Hz
//At least one time should be more than 0
void blink(uint8_t ontime, uint8_t offtime)
{
while(1)
{
for(uint8_t i=0;i<ontime;i++)
{
led_setOn();
delay(BLINK_SLEEP_TIME);
if(button_read())
{
return;
}
}
for(uint8_t i=0;i<offtime;i++)
{
led_setOff();
delay(BLINK_SLEEP_TIME);
if(button_read())
{
return;
}
}
}
}
const uint8_t time_table[][]=
{
{0,50},//LED is off
{6,6}, //LED blinks with 5Hz, 60Hz/2/6=5Hz
{5,5}, //LED blinks with 6Hz, 60Hz/2/5=6Hz
}
void endless(void)
{
uint8_t i=0;
for(;;)
{
i++;
if(i>2)
{
i=0;
}
blink(time_table[i][0],time_table[i][1]);
}
}
A better approach would be to use a hardware PWM-Module and change the values after a edge on the button.