C++ Assignment - Why isn't the push button working? - c++

I am trying to do the following on an Arduino:
Task: Create a toggle switch that controls when 3 LEDs switch on (at the same time). In a toggle switch, when the button is pressed, the LEDs switch on. When it is pressed again, the LEDs switch off.
My pushbutton isn't turning on to turn on the LEDs
The code is:
// C++ code
//Declare
int ledPin13 = 13;
int ledPin12 = 12;
int ledPin11 = 11;
int buttonPin = 1;
int buttonState;
//State if input or output
void setup() {
pinMode(buttonPin , INPUT);
pinMode(ledPin13 , OUTPUT);
pinMode(ledPin12 , OUTPUT);
pinMode(ledPin11 , OUTPUT);
}
//Stage 3 - Code what you want to do (according to psuedocode)
void loop() {
buttonState = digitalRead(buttonPin);
if(buttonState == HIGH) {
digitalWrite(ledPin13 , HIGH);
digitalWrite(ledPin12 , HIGH);
digitalWrite(ledPin11 , HIGH);
}
else {
digitalWrite(ledPin13 , LOW);
digitalWrite(ledPin12 , LOW);
digitalWrite(ledPin11 , LOW);
}
}

It is because your program continuously reads a state. It means the time of pressing the button in compare with the checking of the state by MCU is too mush . for fixing this problem you have two options:
Checking the button. You have to check the state but It is better
to use debouncing which means adding delay between two reads.
bool LEDstate = false;
void loop()
{
if (digitalRead(buttonPin) == HIGH)
{
delay(500); // to be stable
if (digitalRead(buttonPin) == HIGH)
{
if (LEDstate == false)
{
digitalWrite(ledPin13, HIGH);
digitalWrite(ledPin12, HIGH);
digitalWrite(ledPin11, HIGH);
LEDstate = true;
}
else
{
digitalWrite(ledPin13, LOW);
digitalWrite(ledPin12, LOW);
digitalWrite(ledPin11, LOW);
LEDstate = false;
}
while (digitalRead(buttonPin) == HIGH); // wait to release
}
}
}
Inverse reading, which means you have to read the pressing and then wait to release to change the state of LEDs
bool LEDstate = false;
void loop()
{
if (digitalRead(buttonPin) == HIGH)
{
delay(100); // to be stable
while (digitalRead(buttonPin) == HIGH); // wait to release
if (LEDstate == false)
{
digitalWrite(ledPin13, HIGH);
digitalWrite(ledPin12, HIGH);
digitalWrite(ledPin11, HIGH);
LEDstate = true;
}
else
{
digitalWrite(ledPin13, LOW);
digitalWrite(ledPin12, LOW);
digitalWrite(ledPin11, LOW);
LEDstate = false;
}
}
}

bool toggleState = 0;
buttonState = digitalRead(buttonPin);
delay(100);
if( buttonState == 1)
{
if(toggleState)
toggleState = 0;
else
toggleState = 1;
}
if(toggleState)
{
digitalWrite(ledPin13 , HIGH);
digitalWrite(ledPin12 , HIGH);
digitalWrite(ledPin11 , HIGH);
}
else
{
digitalWrite(ledPin13 , LOW);
digitalWrite(ledPin12 , LOW);
digitalWrite(ledPin11 , LOW);
}

Related

Trying to make pushbutton to a toggle switch, when pressed it's going to run sensors and pressed again nothing is going to happen

So i have a dht11 sensor connected to show the temperature and a HC-SR04 sensor to make a LED light up when the distance is under 15cm. I also have photoresistor to light up when it's dark and not ligh up when it's day.
I can do this on my own but the thing is i am trying to make the pushbutton as a toggle switch. When pressed once the sensors should stop printing data to the seriall monitor and the lights to turn off. When pressed again it shoul go back to printing the temperature, HC sensor and photoresistor should also work. When pressed again it should go back to stopping everything and so on.
The # is in norwegian don't mind that just explains the code
// #Include tar med en biblotek
// #define betyr at du gir navn til en constant integer
#include "DHT.h"
#define DHTTYPE DHT11
const int DHTPIN = 7; // fyll inn: digital pin sensoren er koblet til
DHT dht(DHTPIN, DHTTYPE);
const int trig = 10;
const int echo = 11;
int bstate = 1;
int led = 2; //En variabel for led pin.
float tid, avstand, t; // "t" en variabel for temperaturen
int led1 = 8;
int bpin = 5;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
dht.begin();
pinMode(led1, OUTPUT);
pinMode(led, OUTPUT);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
pinMode(bpin, INPUT);
}
void loop() {
if(digitalRead(bpin) == LOW){
Serial.println("System on!");
bpin = 1;
while(bstate == 1){
//Temperatur Sensor kode:
t = dht.readTemperature(); //leser av temp verdier fra sensor og legger verdi inn i "t" variabelen.
Serial.print("Temperature: ");
Serial.println(t);
delay(2000);
return;
//Photoresistor LED
int verdi = analogRead(A1);
Serial.print("Verdi: ");
Serial.println(verdi);
if (verdi > 400){
digitalWrite(led1, HIGH);
}
else {
digitalWrite(led1, LOW);
}
if(digitalRead(bpin) == LOW)
{
bstate = 0;
Serial.println("System off!");
delay(1000);
}
//Ultralyd sensor kode:
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
tid = pulseIn(echo, HIGH);
avstand = (tid*0.034)/2;
if (avstand < 15){
digitalWrite(led, HIGH);
delay(10000);
}
else {
digitalWrite(led, LOW);
}
delay(500);
if(digitalRead(bpin) == LOW)
{
bstate = 0;
Serial.println("System off!");
delay(1000);
}
}
}
}
Another code with toggle switch:
#include "DHT.h"
#define DHTTYPE DHT11
const int DHTPIN = 7; // fyll inn: digital pin sensoren er koblet til
DHT dht(DHTPIN, DHTTYPE);
const int trig = 10;
const int echo = 11;
int ledstate = 0;
int bstate = 0;
int led = 2;
int led1 = 8;
int bpin = 5;
int bnew;
int bold = 1;
float tid, avstand, t;
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
pinMode(led, OUTPUT);
pinMode(bpin, INPUT);
}
void loop() {
// put your main code here, to run repeatedly:
Serial.println(bnew);
bnew = digitalRead(bpin);
if(bold == 0 && bnew == 1){
if(bstate == 0){
Serial.println("System on");
//Temperatur Sensor kode:
t = dht.readTemperature(); //leser av temp verdier fra sensor og legger verdi inn i "t" variabelen.
Serial.print("Temperature: ");
Serial.println(t);
delay(2000);
return;
//Photoresistor LED
int verdi = analogRead(A1);
Serial.print("Verdi: ");
Serial.println(verdi);
if (verdi > 400){
digitalWrite(led1, HIGH);
}
else {
digitalWrite(led1, LOW);
}
//Ultralyd sensor kode:
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
tid = pulseIn(echo, HIGH);
avstand = (tid*0.034)/2;
if (avstand < 15){
digitalWrite(led, HIGH);
delay(10000);
}
else {
digitalWrite(led, LOW);
}
delay(500);
bstate = 1;
}
else if(bstate == 1 && bnew == 1){
Serial.println("System off");
bstate = 0;
}
delay(1000);
}
bold = bnew;
delay(1000);
}
Code without if (Not toggle switch):
// C++ code
//
#include "DHT.h"
#define DHTTYPE DHT11
const int DHTPIN = 7; // fyll inn: digital pin sensoren er koblet til
DHT dht(DHTPIN, DHTTYPE);
const int trig = 10;
const int echo = 11;
int led = 2;
int led1 = 8;
float tid, avstand, t;
void setup()
{
pinMode(led, OUTPUT);
pinMode(trig, OUTPUT);
pinMode(echo, INPUT);
Serial.begin(9600);
}
void loop()
{
//Ultralyd sensor kode:
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
tid = pulseIn(echo, HIGH);
avstand = (tid*0.034)/2;
if (avstand < 15){
digitalWrite(led, HIGH);
delay(10000);
}
else {
digitalWrite(led, LOW);
}
delay(1500);
//Temperatur Sensor kode:
t = dht.readTemperature(); //leser av temp verdier fra sensor og legger verdi inn i "t" variabelen.
Serial.print("Temperature: ");
Serial.println(t);
delay(2000);
return;
//Photoresistor LED
int verdi = analogRead(A1);
Serial.print("Verdi: ");
Serial.println(verdi);
if (verdi > 400){
digitalWrite(led1, HIGH);
}
else {
digitalWrite(led1, LOW);
}
}
The connections are correct but when ii run these codes almost nothing happens. the first code i can turn system on but not off and just dht11 sensor is working, syste turned off automatic. The second code the temperature printed nan or - all the time and system on to other sensors did not work. The third code temperature kinda worked and HC-SR04 sensor worked but not the photoresistor.
Circuit drawing of curcuit
Scematic view of circuit
Anything would help thanks

Trying to use millis instead of delay for a switch state loop

I am trying to write a code for an Arduino, which is a model of a redlight.
The idea is that pressing the button will switch to the first state (turning LEDs on and off).
Then the second and finally the third state will revert it back to the first state waiting for the button to be pressed again
There is the need for a time gap between the 2 states....it works perfectly well using the delay() function
But I am not allowed to use it, so instead, I am trying to use millis(), the idea is that the time should start once the button is pressed and stop once it's reverts back to the first state and restart over once the button is pressed again.
And it's sadly not working, whenever I press the button nothing happens.
Does anybody know how I can fix it?
here is the code:
const long delay2 = 4000;
int but = 2;
int leda = 3;
int ledb = 4;
int ledc = 5;
int ledd = 6;
int lede = 7;
volatile byte state=LOW;
void setup() {
Serial.begin(9600);
for(int p=3; p <= 8; p++) pinMode(p, OUTPUT);
pinMode(but, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(but), changestate, FALLING);
}
void car(){
digitalWrite(leda, HIGH);
digitalWrite(ledb, LOW);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void wait(){
digitalWrite(leda, LOW);
digitalWrite(ledb, HIGH);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void ped(){
digitalWrite(leda, LOW);
digitalWrite(ledb, LOW);
digitalWrite(ledc, HIGH);
digitalWrite(ledd, HIGH);
digitalWrite(lede, LOW);
}
void changestate() {
state=state+1;
if (state > 3){
state=0;
}
}
void loop(){
switch(state){
case 0:
car();
unsigned long start_time = millis();
break;
case 1:
wait();
while (millis() > start_time + delay1);
state=2;
break;
case 2:
ped();
while (millis() > start_time + delay2);
state=0;
break;
default:
break;
}
}
EDIT: The issue has been solved! Here's the code for further reference:
#define delay1 500
#define delay2 4000
int but = 2;
int leda = 3;
int ledb = 4;
int ledc = 5;
int ledd = 6;
int lede = 7;
volatile byte state=LOW;
void setup() {
Serial.begin(9600);
for(int p=3; p <= 8; p++) pinMode(p, OUTPUT);
pinMode(but, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(but), changestate, FALLING);
}
void car(){
digitalWrite(leda, HIGH);
digitalWrite(ledb, LOW);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void wait(){
digitalWrite(leda, LOW);
digitalWrite(ledb, HIGH);
digitalWrite(ledc, LOW);
digitalWrite(ledd, LOW);
digitalWrite(lede, HIGH);
}
void ped(){
digitalWrite(leda, LOW);
digitalWrite(ledb, LOW);
digitalWrite(ledc, HIGH);
digitalWrite(ledd, HIGH);
digitalWrite(lede, LOW);
}
void changestate() {
state=state+1;
if (state > 3){
state=0;
}
}
unsigned long start_time = millis();
void loop(){
switch(state){
case 0:
car();
break;
case 1:
start_time = millis();
while(millis() < start_time + delay1){
wait();
state=2;
}
break;
case 2:
while(millis() < start_time + delay2){
ped();
}
state=0;
break;
default:
break;
}
}
Problematic things in code:
unsigned long start_time = millis(); start_time can't be a local variable. After break command, loop function will end. Local variable on the stack will be destroed. After new calling loop will created again and content is unpredictable. Make it global.
while (millis() > start_time + delay1); if this become true it will hangup for 49 days. You probably want do while (millis() < start_time + delay1); But this is same as use delay()
millis() < start_time + delay1; don't use this form. It produce falsely result shortly before internal counter overflow (every 49.x days). Use form (millis() - start_time > delay1 This calculate valid elapsed time also if result of millis() is lower then start_time
Also, do you have debouced button? It's seem as school exercise. I will don't write code for you. Only standart hint - Use Serial.println() to log where your code is running and what is in yours variables.
Here is an untested suggestion. It only allows state changes if a sufficient amount of time has passed. You may want to have different times in an array if (millis() - start_time > mydelays[state]) {
volatile bool change_allowed = true;
volatile bool statechanged = true;
volatile unsigned long start_time = 0;
void changestate() {
if (millis() - start_time > DELAY) {
change_allowed = true;
}
if (change_allowed) {
start_time = millis();
change_allowed = false;
state=state+1;
statechanged = true;
if (state > 2) {
state=0;
}
}
}
void loop() {
if (statechanged) {
statechanged = false;
switch(state){
case 0:
...
}

Serial Communication freezes with BMP180 and Arduino Mega

I recently bought an ELEGO Mega 2560, or in other words an Arduino Mega. I bought a bmp180 sensor as well. I connected the bmp in this fashion, VCC - 3.3v, GND - GND, SCL - 21, SDA - 20. I uploaded a simple code which just displayes altitude. When I go to the Serial Monitor to view the results, nothing pops up. It is suppose to say BMP init success if it connects, and fail if it doesn't. When I go to the monitor, it just doens't say anything. When I disconnect the sensor, it says fail. It appears as if the Serial Monitor just freezes. Also a headsup, my code is very messy, I'm sorry if it's hard to keep up.
#include <Wire.h>
#include <SFE_BMP180.h>
SFE_BMP180 bmp180;
float Po = 1014.9;
#define ledPin 7
#define TransmitPin 5
//int Altitude = 5;
int sendValue;
String incomingString;
unsigned long lastTransmission;
const int interval = 1000;
void setup() {
Wire.begin();
pinMode(ledPin, OUTPUT);
pinMode(2, INPUT);
pinMode(10, OUTPUT);
pinMode(TransmitPin, OUTPUT);
bool success = bmp180.begin();
Serial.begin(115200);
if (success) {
Serial.println("BMP180 init success");
}
else
Serial.println("fail");
}
void loop() {
sendValue = digitalRead(29);
if (sendValue == HIGH) {
if (millis() > lastTransmission + interval) {
Serial.println("AT+SEND=1,8,Return");
digitalWrite(TransmitPin, HIGH);
delay(100);
digitalWrite(TransmitPin, LOW);
lastTransmission = millis();
}
}
if (Serial.available()) {
incomingString = Serial.readString();
if (incomingString.indexOf("Testing!") > 0) {
digitalWrite(10, HIGH);
delay(100);
digitalWrite(10, LOW);
}
}
char status;
double T, P, alt;
bool success = false;
status = bmp180.startTemperature();
if (status != 0) {
delay(1000);
status = bmp180.getTemperature(T);
if (status != 0) {
status = bmp180.startPressure(3);
if (status != 0) {
delay(status);
status = bmp180.getPressure(P, T);
if (status != 0) {
if (millis() > lastTransmission + interval) {
alt = bmp180.altitude(P, Po);
Serial.print("AT+SEND=1,8,");
int altAsFoot = alt * 3.281;
Serial.println(altAsFoot);
digitalWrite(TransmitPin, HIGH);
delay(100);
digitalWrite(TransmitPin, LOW);
}
for (int i = 0; i < 1800; i++) {
delay(1);
if (Serial.available()) {
incomingString = Serial.readString();
if (incomingString.indexOf("+OK") > 0) {
digitalWrite(ledPin, HIGH);
delay(100);
digitalWrite(ledPin, LOW);
}
if (incomingString.indexOf("Testing!") > 0) {
digitalWrite(10, HIGH);
delay(100);
digitalWrite(10, LOW);
}
}
}
}
}
}
}
}
Turns out it was a hardware issue. I had ground shorted to SDA. I'm assuming the same will happen if it's shorted to SCL. Make sure both SDA and SCL aren't shorted to each other or ground.

Arduino - stopping loop via button

So i have been experimenting with TinkerCad, waiting for my arduino to arrive. Currently I have a loop of ledlights and i want to start and stop the loop by pressing a button.
Currently i am able to start my loop via the button, but not able to stop the loop with the same button press. Does this have something to do with the debouncing?
const int button = 10;
const int led1 = 8;
const int led2 = 4;
const int led3 = 3;
const int timedelay = 250;
boolean buttonstate = false;
void setup()
{
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
if(digitalRead(button)==HIGH) // check if button is pushed
buttonstate = !buttonstate; //reverse buttonstate value
if(buttonstate==true)
{
digitalWrite(led1, HIGH);
delay(timedelay);
digitalWrite(led1, LOW);
delay(timedelay);
digitalWrite(led2, HIGH);
delay(timedelay);
digitalWrite(led2, LOW);
delay(timedelay);
digitalWrite(led3, HIGH);
delay(timedelay);
digitalWrite(led2, HIGH);
delay(timedelay);
digitalWrite(led1, HIGH);
delay(timedelay);
digitalWrite(led3, LOW);
delay(timedelay);
digitalWrite(led2, LOW);
delay(timedelay);
digitalWrite(led1, LOW);
delay(timedelay);
digitalWrite(led1, HIGH); }
else {
digitalWrite(led1, HIGH);
}
}
My circuit setup:
EDIT:
I have adjusted my code, replaced the delay with millis and looking for a change in button state. Still looking for a way to adjust interval_led1 at the end of the loop to make sick ledlight sequences.
const int led1 = 13;
const int led2 = 8;
const int led3 = 5;
const int button = 10;
int ledState_led1 = LOW; // ledState used to set the LED
int ledState_led2 = LOW;
int ledState_led3 = LOW;
// Generally, you should use "unsigned long" for variables that hold time
// The value will quickly become too large for an int to store
unsigned long previousMillis_led1 = 0; // will store last time LED was updated
unsigned long previousMillis_led2 = 0;
unsigned long previousMillis_led3 = 0;
long interval_led1 = 500; // interval at which to blink (milliseconds)
long interval_led2 = 600;
long interval_led3 = 700;
boolean buttonstate = false;
void setup() {
pinMode(led1, OUTPUT);
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(button, INPUT);
}
void loop() {
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long currentMillis_led1 = millis();
unsigned long currentMillis_led2 = millis();
unsigned long currentMillis_led3 = millis();
bool current_state = digitalRead(button);
bool prev_buttonstate= false;
if(current_state==HIGH && current_state != prev_buttonstate)
{
buttonstate = !buttonstate; //reverse buttonstate value
}
prev_buttonstate = current_state;
if(buttonstate==true)
if (currentMillis_led1 - previousMillis_led1 >= interval_led1) {
previousMillis_led1 = currentMillis_led1;
if (ledState_led1 == LOW) {
ledState_led1 = HIGH;
} else {
ledState_led1 = LOW;
}
digitalWrite(led1, ledState_led1);
}
if(buttonstate==true)
if (currentMillis_led2 - previousMillis_led2 >= interval_led2) {
previousMillis_led2 = currentMillis_led2;
if (ledState_led2 == LOW) {
ledState_led2 = HIGH;
} else {
ledState_led2 = LOW;
}
digitalWrite(led2, ledState_led2);
}
if(buttonstate==true)
if (currentMillis_led3 - previousMillis_led3 >= interval_led3) {
previousMillis_led3 = currentMillis_led3;
if (ledState_led3 == LOW) {
ledState_led3 = HIGH;
} else {
ledState_led3 = LOW;
}
digitalWrite(led3, ledState_led3);
}
}
Here your two cases are very different in terms of delay:
if(buttonstate==true) is very long to execute because of the multiple delay instructions in it,
else is very fast because there is no delay in it.
When buttonstate==True and you press the button (as Delta_G said, the delay() prevent the test to happen most of the time and you should use millis() for instance to do the timing, but let say you are lucky and you pass your first if statement), so buttonstate will flip to false.
As there is no delay in your else instruction, the board will come back in no time to your initial if, which, unfortunately will still be true as you are not fast enough to press this button for only a few microseconds. So buttonstate will flip again and your code will fall in your if(buttonstate==true) which is very long, allowing you to release the button in time before the if(digitalRead(button)==HIGH) is reevaluated.
The solution (apart from timing issues raised by #Delta_G, and hardware issues raised by #TomServo) is to seek for changes of the button state. You thus have to compare to the previous value it had. You can declare another boolean boolean prev_buttonstate = false; and could do something like:
bool current_state = digitalRead(button);
if(current_state==HIGH && current_state != prev_buttonstate)
{
buttonstate = !buttonstate; //reverse buttonstate value
}
prev_buttonstate = current_state;
Hope it helps!
Your circuit is correct. If you keep pressing the button little longer, the condition will continue to hold good and the state falsely resets again.
To simulate the toggling effect, use a bool variable like so:. You reset the variable when the signal goes low.
void loop() {
static bool ready = true;
if(digitalRead(button)==HIGH && ready)
{
ready = false;
buttonstate = !buttonstate; //reverse buttonstate value
if(buttonstate){
digitalWrite(led1, HIGH);
delay(timedelay);
digitalWrite(led1, LOW);
delay(timedelay);
/* Etc*/ }
else {
digitalWrite(led1, HIGH);
}
}
else
if(digitalRead(button)==LOW && !ready)
{
ready = true;
}
}

Arduino alternative for delays?

What I wanted to do is to run 2 traffic lights simultaneously(ex. North and South).Is there an alternative for delay besides millis? I tried to use Blinkwithoutdelay but as a newbie its very complicated for me to use it.
digitalWrite(greenled, HIGH); //Green on for 1 seconds
delay(greenDuration);
digitalWrite(greenled, LOW); //Green off, yellow on for 1 seconds
digitalWrite(yellowled, HIGH);
delay(1000);
digitalWrite(yellowled, LOW); //yellow off, red on for 1 seconds
digitalWrite(redled, HIGH);
delay(1000);
digitalWrite(redled, LOW); //Red off
digitalWrite(greenled2, HIGH); //Green on for 1 seconds
delay(1000);
digitalWrite(greenled2, LOW); //Green off, yellow on for 1 seconds
digitalWrite(yellowled2, HIGH);
delay(1000);
digitalWrite(yellowled2, LOW); //yellow off, red on for 1 seconds
digitalWrite(redled2, HIGH);
delay(1000);
digitalWrite(redled2, LOW); //Red off
Complete code:
int beam = 2;//Beam sensor
int greenled = 4;
int redled = 7;
int yellowled = 13;
int greenDuration =1000; //normal time
int greenShortDuration = 1000;
int greenIncrement = 5000; //5 seconds
void setup()
{
// set the digital pin as output:
pinMode(greenled, OUTPUT);
pinMode(redled, OUTPUT);
pinMode(greenled, OUTPUT);
pinMode(beam,INPUT);
Serial.begin(9600);
}
void loop()
{
Serial.println("Status:low");
digitalWrite(greenled, HIGH); //Green on for 5 seconds
delay(greenDuration);
digitalWrite(greenled, LOW); //Green off, yellow on for 2 seconds
digitalWrite(yellowled, HIGH);
delay(1000);
digitalWrite(yellowled, LOW); //yellow off, red on for 5 seconds
digitalWrite(redled, HIGH);
delay(1000);
digitalWrite(redled, LOW); //Red and Yellow off
digitalWrite(greenled2, HIGH); //Green on for 1 seconds
delay(1000);
digitalWrite(greenled2, LOW); //Green off, yellow on for 1 seconds
digitalWrite(yellowled2, HIGH);
delay(1000);
digitalWrite(yellowled2, LOW); //yellow off, red on for 1 seconds
digitalWrite(redled2, HIGH);
delay(1000);
digitalWrite(redled2, LOW); //Red off
if(digitalRead(beam)==HIGH){
for(int i=1; i<=10; i++){
Serial.println(i);
while(i>=10){
Serial.println("Motion Detected");
greenDuration +=greenIncrement; //Add 5 seconds everytime
Serial.println(greenDuration);
break;
}
}
}
if(!digitalRead(beam)==HIGH){
Serial.println("hey"); //indication of code is working
greenDuration=greenShortDuration;
return;
}
}
I tried to use Blinkwithoutdelay but as a newbie its very complicated
for me to use it.
You have to try harder :)
Imagine loop() isn't the "program" but a description of any moment.
In general it detects that neither time for a change nor a new pushbutton request has come, so loop exits immediately.
Even if something should have happened, any new reaction does not take any time, and loop exits immediately.
There is a simple solution to solve the given traffic lights sample.
Instead of calling the delay function you could call your special delay-function:
int globalFlagSomeonePressedBeam = false; // store global if someone pushed the beam button
void delay_and_check_for_beam (int msDelay) {
for (int i=0; i<msDelay; ++i) {
if(digitalRead(beam)==HIGH){ // check beam button
globalFlagSomeonePressedBeam = true; // store information
}
delay(1);
}
}
Between the calls to your delay function you set the right lights (digital outs)
After you check your globalFlagSomeonePressedBeam you need to set it back to false
Solution by OP.
unsigned long curGoStopDuration, defGoStopDuration = 5000, maxGoStopDuration = 30000;
unsigned long currentMillis;
#pragma region SensorFields
int durationIncrement = 2500;
unsigned long greenPrevMillis;
float DetectionTime = 2500;
bool triggered;
#pragma endregion
enum LightState { Green, Yellow, Red };
class Stoplight
{
private:
int greenLed, yellowLed, redLed;
unsigned long previousMillis;
float CurInterval;
LightState state;
public:
unsigned long GreenDuration = 5000;
unsigned long RedDuration = 5000;
int YellowDuration = 1000;
Stoplight(int gLed, int yLed, int rLed) :greenLed(gLed), yellowLed(yLed), redLed(rLed)
{
pinMode(greenLed, OUTPUT);
pinMode(redLed, OUTPUT);
pinMode(yellowLed, OUTPUT);
}
void Loop()
{
if (currentMillis - previousMillis >= CurInterval)
{
previousMillis = currentMillis;
//Transitions
switch (state)
{
case Green:
ToYellow();
break;
case Yellow:
ToRed();
break;
case Red:
ToGreen();
break;
}
}
}
void ToGreen()
{
digitalWrite(redLed, LOW);
digitalWrite(greenLed, HIGH);
CurInterval = GreenDuration - YellowDuration;
state = Green;
}
void ToYellow()
{
digitalWrite(greenLed, LOW);
digitalWrite(yellowLed, HIGH);
CurInterval = YellowDuration;
state = Yellow;
}
void ToRed()
{
digitalWrite(yellowLed, LOW);
digitalWrite(redLed, HIGH);
CurInterval = RedDuration;
state = Red;
}
};
Stoplight SL_01(2, 3, 4), SL_02(5, 6, 7);
int beamSensor = 8;
void setup()
{
//Set default values
curGoStopDuration = defGoStopDuration;
SL_01.ToGreen();
SL_02.ToRed();
pinMode(beamSensor, INPUT);
Serial.begin(9600);
}
void loop()
{
currentMillis = millis();
Sensor();
//Manipulate durations
SL_01.GreenDuration = curGoStopDuration;
SL_02.RedDuration = curGoStopDuration;
SL_01.Loop();
SL_02.Loop();
}
void Sensor()
{
//If sensor detects something
if (digitalRead(beamSensor) == HIGH)
{
if (!triggered)
{
greenPrevMillis = currentMillis;
triggered = true;
}
if (currentMillis - greenPrevMillis >= DetectionTime)
{
if(curGoStopDuration < maxGoStopDuration)
curGoStopDuration += durationIncrement; //Add seconds
greenPrevMillis = currentMillis;
Serial.print("Green light duration is now: ");
Serial.println(curGoStopDuration);
}
}
else //No detection
{
curGoStopDuration = defGoStopDuration;
triggered = false;
}
}
You need interrupt on your beam, fast one, just counter, but its necessary for more precise counting (traffic =) )... this works for me just fine:
#define redPin1 40
#define yellowPin1 41
#define greenPin1 42
#define beamPin1 21
#define redDuration 1000
#define yellowDuration 1000
#define greenDuration 1000
#define durationIncrement 500
byte carCounter1 = 0;
byte state1 = 1;
void setup()
{
pinMode(redPin1, OUTPUT);
pinMode(yellowPin1, OUTPUT);
pinMode(greenPin1, OUTPUT);
pinMode(beamPin1, INPUT);
attachInterrupt(digitalPinToInterrupt(beamPin1), beamCount1, RISING);
}
void beamCount1()
{
carCounter1++;
}
void wait(long duration)
{
int wait = 0;
long last = millis();
while (wait == 0)
{
long now = millis();
if (now - last >= duration) { wait = 1;}
else {}
}
}
void redLight(byte redLightPin)
{
digitalWrite(redLightPin, HIGH);
wait(redDuration);
state1 = 2;
}
void yellowLight1(byte redLightPin, byte yellowLightPin)
{
digitalWrite(yellowLightPin, HIGH);
wait(yellowDuration);
digitalWrite(redLightPin, LOW);
digitalWrite(yellowLightPin, LOW);
state1 = 3;
}
void yellowLight2(byte yellowLightPin)
{
digitalWrite(yellowLightPin, HIGH);
wait(yellowDuration);
digitalWrite(yellowLightPin, LOW);
state1 = 1;
}
void greenLight(byte greenLightPin)
{
digitalWrite(greenLightPin, HIGH);
long incremented = greenDuration + (carCounter1 * durationIncrement);
wait(incremented);
digitalWrite(greenLightPin, LOW);
carCounter1 = 0;
state1 = 4;
}
void trafficLight(byte red, byte yellow, byte green)
{
switch (state1){
case 1:
redLight(red);
break;
case 2:
yellowLight1(red, yellow);
break;
case 3:
greenLight(green);
break;
case 4:
yellowLight2(yellow);
break;
}
}
void loop()
{
trafficLight(redPin1, yellowPin1, greenPin1);
}
no delays, just wait function which makes track of millis... if you want more precision, count the time needed for each light and remove it from wait...