How can I stop a loop with serial input - c++

How can I stop or exit from this loop using a serial input?
This is the simple code I've been using
#define stimulation 4
#define led 13
void setup() {
Serial.begin(57600);
pinMode(stimulation,OUTPUT);
pinMode(led, OUTPUT);
digitalWrite(stimulation, LOW);
digitalWrite(led, LOW);
Serial.println("Press any Key");
while (!Serial.available()){}
}
void loop() {
digitalWrite(stimulation, HIGH);
digitalWrite(led, HIGH);
delay(20);
digitalWrite(stimulation, LOW);
digitalWrite(led, LOW);
delay(30);
}
I was looking for a serial input string to exit the loop
void loop() {
digitalWrite(stimulation, HIGH);
digitalWrite(led, HIGH);
delay(20);
digitalWrite(stimulation, LOW);
digitalWrite(led, LOW);
delay(30);
}
Thank you!

As your code will work without the serial monitor, you can try this snippet:
void setup() {
/* other codes */
Serial.begin(57600);
int numTries = 0;
while (!Serial.available()){
if( ++numTries >= 10) break;
delay(100);
}
}
Edited: I was assuming that you got stuck during the initial setup stage when Serial monitor don't respond. Since you like to blink the LED only once, you can do like so using static keyword. When a variable is declared as static, space for it gets allocated for the lifetime of the program.
void loop() {
static bool done = false; // will initialize only once
digitalWrite(stimulation, HIGH);
digitalWrite(led, HIGH);
delay(20);
digitalWrite(stimulation, LOW);
digitalWrite(led, LOW);
delay(30);
if(!done && Serial.available()) {
Serial.println("Stimulation Done :)");
done = true;
}
}

#define stimulation 4
#define led 13
unsigned long startMillis;
unsigned long currentMillis;
const unsigned long stimTime = 20*60000; // Stimulation Time (60s = 60000ms)
void setup() {
Serial.begin(115200);
pinMode(stimulation,OUTPUT);
pinMode(led, OUTPUT);
digitalWrite(stimulation, LOW); // force laser OFF before starting
digitalWrite(led, LOW);
Serial.println("Standby:");
Serial.println("Press any key to start stimulation");
while (!Serial.available()){} // do absolutely nothing until serial input received
startMillis = millis(); // time (ms) when input received
Serial.println("Now you wait 20min :)");
}
void loop() {
currentMillis = millis(); // time (ms) beginning of the loop
if (currentMillis - startMillis <= stimTime) {
digitalWrite(stimulation, HIGH); // Laser ON
digitalWrite(led, HIGH); // Internal Led ON
delay(20); // Keep laser ON for 20ms
digitalWrite(stimulation, LOW); // Laser OFF
digitalWrite(led, LOW); // Internal Led OFF
delay(30); // Keep laser OFF for 30ms
}
else { // After 20min do nothing (stop stimulation)
}
}

Related

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

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);
}

How to work with 2 HCSR04 Arduino Component?

Any ideas for the code of working with 2 different ultrasonic sensors? The idea is when either one of the sensors detects an obj in front of the sensor, it automatically turns on a buzzer. But for now, I only use the 2 ultrasonic sensors. This is my code, doesnt work as expected:
#define trigPin1 3
#define echoPin1 2
#define trigPin2 4
#define echoPin2 5
long duration, distance, RightSensor,LeftSensor;
void setup()
{
Serial.begin (9600);
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
}
void loop() {
SonarSensor(trigPin1, echoPin1);
RightSensor = distance;
SonarSensor(trigPin2, echoPin2);
LeftSensor = distance;
Serial.print(LeftSensor);
Serial.print(" | ");
Serial.println(RightSensor);
}
void SonarSensor(int trigPin,int echoPin)
{
digitalWrite(trigPin, LOW);
delay(2);
digitalWrite(trigPin, HIGH);
delay(2);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
}
A better way to approach this problem would be to make a function that returns the distance long. The code would look like this:
long duration, distance, RightSensor,LeftSensor;
void setup()
{
Serial.begin (9600);
pinMode(trigPin1, OUTPUT);
pinMode(echoPin1, INPUT);
pinMode(trigPin2, OUTPUT);
pinMode(echoPin2, INPUT);
}
void SonarSensor(int trigPin,int echoPin)
{
digitalWrite(trigPin, LOW);
delay(2);
digitalWrite(trigPin, HIGH);
delay(2);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = (duration/2) / 29.1;
return distance;
}
void loop()
{
RightSensor = SonarSensor(trigPin1, echoPin1);
LeftSensor = SonarSensor(trigPin2, echoPin2);
Serial.printIn(LeftSensor);
Serial.print(" | ");
Serial.printIn(RightSensor);
}
If you are getting wrong readings try using this code for the function:
void SonarSensor(int trigPin,int echoPin) {
digitalWrite(trigPin, LOW);
delayMicroseconds(2);
digitalWrite(trigPin, HIGH);
delayMicroseconds(10);
digitalWrite(trigPin, LOW);
duration = pulseIn(echoPin, HIGH);
distance = duration * 0.034 / 2;
return distance;
If you want to use the original code, move the void SonarSensor before void loop and make distance a global long.

How do I show 2 different numbers on a 2 digit 10 pin 7 segment display?

int a = 13;
int b = 6;
int c = 11;
int d = 10;
int e = 9;
int f = 8;
int g = 7;
int digit1 = 5;
int digit2 = 4;
void setup()
{
pinMode(a, OUTPUT);
pinMode(b, OUTPUT);
pinMode(c, OUTPUT);
pinMode(d, OUTPUT);
pinMode(e, OUTPUT);
pinMode(f, OUTPUT);
pinMode(g, OUTPUT);
pinMode(digit1, OUTPUT);
pinMode(digit2, OUTPUT);
}
void six() {
digitalWrite(a, LOW);
digitalWrite(b, HIGH);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
digitalWrite(digit1, HIGH);
delay(1000);
}
void nine() {
digitalWrite(a, LOW);
digitalWrite(b, LOW);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, HIGH);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
digitalWrite(digit2, HIGH);
}
void loop()
{
six();
nine();
}
I have got this code in which I want to show the number 69 on my display but all it is showing is 66 Can anyone tell me what the problem is and if it is in the code or the wiring (in the wiring diagram i couldn't find a 2 digit display but i used a 1 digit one as it has the same amount of pins so keep in mind that the wiring is for a 2 digit one).
[Thanks in advance.
wiring diagram
You are trying to display 2 digits at the same time... That won't work. You must set the lines for each digit sequentially, using the common to select the digit you are controlling.
Your code is almost there. All you need to add is some delay, and turning off all segments while you tinker with the output lines.
Example:
// ...
void six()
{
digitalWrite(a, LOW);
digitalWrite(b, HIGH);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, LOW);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
}
void nine()
{
digitalWrite(a, LOW);
digitalWrite(b, LOW);
digitalWrite(c, LOW);
digitalWrite(d, LOW);
digitalWrite(e, HIGH);
digitalWrite(f, LOW);
digitalWrite(g, LOW);
}
void showDigit(int digit)
{
switch(digit)
{
case -1: // all off
digitalWrite(digit1, HIGH);
digitalWrite(digit2, HIGH);
break;
case 0: // digit 1 ON
digitalWrite(digit1, LOW);
digitalWrite(digit2, HIGH);
break;
case 1: // digit 2 ON
digitalWrite(digit1, HIGH);
digitalWrite(digit2, LOW);
break;
}
}
// ...
void loop()
{
showDigit(-1);
six();
showDigit(0);
delay(10); // this delay is usually in the 10-30ms range
showDigit(-1);
nine();
showDigit(1);
delay(10);
}
Usually other processing will take place during the 'delay' time.. I suggest you look up on state machine algorithms so your Arduino project can seamlessly control multiple multi-segments LEDs and do other processing at the same time. But that's a totally different subject.
The reduced the duty cycle wil dim the LEDs a bit, but that can be compensated by reducing the segment series resistors.
IMPORTANT: Make sure the digit1 and digit2 lines are not connected to each other, or you may fry your Arduino. If you only have one display, you'll be able to see only one digit.

Why is the red light not lighting up?

So I am very new to this IoT stuff and what I am trying to create here is somewhat like traffic violation detection.
My idea is: when the red light is on and if the PIR sensor detects movement, the buzzer/LED turns on.
Here's the image:
Here's what the code looks like:
int pir = 2;
int rojo = 12;
int amarillo = 11;
int verde = 10;
int led = 7;
void setup() {
pinMode(pir, INPUT);
pinMode(led, OUTPUT);
Serial.begin(9600);
pinMode(verde, OUTPUT); // It declares the green pin as output
pinMode(amarillo, OUTPUT);// It declares the yellow pin as output
pinMode(rojo, OUTPUT);
}
void loop() {
digitalWrite(verde, HIGH); // It turns on the green led
delay(15000); //wait 15 seconds
digitalWrite(verde, LOW); // It turns off the green led
delay(250); //wait 0.25 seconds
digitalWrite(amarillo, HIGH); // It turns on the yellow led
delay(3000); //wait 3 seconds
digitalWrite(amarillo, LOW); // It turns off the yellow led
delay(250); //wait 0.25 seconds
int val = digitalRead(pir);
Serial.println(val);
digitalWrite(rojo, HIGH); // It turns on the red led
delay(15000); //wait 15 seconds
digitalWrite(rojo, LOW);
if (rojo == HIGH) {
if (val == HIGH) {
digitalWrite(led, HIGH);
} else {
digitalWrite(led, LOW);
}
delay(10);
}
}
The problem is here:
digitalWrite(rojo, HIGH); //It turns on the red led
delay(15000); //wait 15 seconds
digitalWrite(rojo, LOW);
if (rojo == HIGH) {
if (val == HIGH) {
digitalWrite(led, HIGH);
} else {
digitalWrite(led, LOW);
}
delay(10);
}
First of all, rojo is a pin number, not a value you want to use in this compare.
Second, during your delay delay(15000), the code stops running, so movement is not detected during this time.
The only way to detect during the 15s delay is by using millis() for your timing and delay (or using an interrupt).
You could try something like this (untested):
digitalWrite(rojo, HIGH); //It turns on the red led
unsigned long int redStartTime = millis();
while (millis() - redStartTime <= 15000) {
delay(100);
int val = digitalRead(pir);
if (val == HIGH) {
digitalWrite(led, HIGH);
} else {
digitalWrite(led, LOW);
}
}
digitalWrite(rojo, LOW);
I didn't test this, but you get the idea.
Note that I don't know if the motion detector returns HIGH or LOW when something moves; you may need to change the code there.
You need to change the position of your if
int pir=2;
int rojo=12;
int amarillo=11;
int verde=10;
int led=7;
void setup()
{
pinMode(pir,INPUT);
pinMode(led,OUTPUT);
Serial.begin(9600);
pinMode(verde,OUTPUT); //It declares the green pin as output
pinMode(amarillo,OUTPUT);//It declares the yellow pin as output
pinMode(rojo,OUTPUT);
}
void loop()
{
digitalWrite(verde,HIGH); //It turns on the green led
delay(15000); //wait 15 seconds
digitalWrite(verde,LOW); //It turns off the green led
delay(250); //wait 0.25 seconds
digitalWrite(amarillo,HIGH); //It turns on the yellow led
delay(3000); //wait 3 seconds
digitalWrite(amarillo,LOW); //It turns off the yellow led
delay(250); //wait 0.25 seconds
int val = digitalRead(pir);
Serial.println(val);
digitalWrite(rojo,HIGH); //It turns the red led
if(val==HIGH){ //---> //I dont know if this value can be compared with HIGH, on my programm whe costum use numbers!
digitalWrite(led,HIGH);
}
else{
digitalWrite(led,LOW);
}
delay(15000); //wait 15 seconds
digitalWrite(rojo,LOW);
delay(10);
}

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