0
votes

So I am doing a project. My task is to create a traffic light system that contains three modes that I can select from, by inputting the numbers 1,2 or 3 to the serial monitor. Everything was alright until I decided to add three push-buttons to the breadboard so I am also able to select any mode via the buttons. So far I have been unable to make the Arduino accept input from the serial monitor and the push buttons at the same time, I don't know if i'm in the right path or not to achieving my objective. I just need a small guidance to this, pls. Here is my current code:

//----------------------- Variables
#define ECHOPIN 3
#define TRIGPIN 2
  char inVal; 
  String inString = ""; 
  const int red_led = 11;
  const int yellow_led = 12;
  const int green_led = 13;
  const int on_delay= 2000, off_delay= 1000; //led delays
  const int min_distance = 10; // Distance sensor min distance
  const int The_buzzer = 4;
  float real_distance; // Distance obtained from function
  int ldrPin = A0; // LDR pin          
  unsigned int sensorValue = 0;  
  float voltage;
  float light_amount;
  int brightness = 600; // amount of light treshhold
  int button_one = 5;
  String ButtonOne;


void setup() {

  pinMode(red_led, OUTPUT);  
  pinMode(yellow_led, OUTPUT); 
  pinMode(green_led, OUTPUT);
  pinMode(The_buzzer, OUTPUT);
  Serial.begin(9600); 
  pinMode(ECHOPIN, INPUT);
  pinMode(TRIGPIN, OUTPUT);
  pinMode(button_one, INPUT);
}


void loop() {


if (Serial.available()>0)

distanceSensor(0); // distance sensor function

{

  inVal=Serial.read();
  switch((inVal) | (ButtonOne == "HIGH")) 
{ 
    case '1': // ------------------------- Regular Mode
    while (true)
    {
    red_light();
    yellow_light();
    green_light();
    yellow_light();
    }
    break;


case '2': // ------------------------ Pedestrian Mode
while (true)
{

real_distance = distanceSensor(0);

if (real_distance < min_distance)
{
  for (int a= 0; a < 10; a++)
  {
  tone(The_buzzer,1000);
  delay(1000); 
  noTone(The_buzzer);
  delay(1000);
  digitalWrite(yellow_led, HIGH);
  delay(100);
  digitalWrite(yellow_led,LOW);
  }
}

real_distance = distanceSensor(0);

if (real_distance > min_distance)
{
red_light();
yellow_light();
green_light();
yellow_light();
}
}
break;


case '3': // --------------------------- NIGHT MODE 

while (true)
{
light_amount = LDRSensor(0);
real_distance = distanceSensor(0);



if (light_amount > brightness)
{
red_light();
yellow_light();
green_light();
yellow_light();
red_light();
delay(100);
}

if (light_amount < brightness || real_distance < min_distance)
{

 real_distance = distanceSensor(0); // distance sensor reading

  if (real_distance > min_distance)
  {
  digitalWrite(green_led, LOW);
  digitalWrite(red_led, HIGH);
  }

  if (real_distance < min_distance )
  {

    while(real_distance < min_distance && light_amount < brightness)
    { //maybe change this
    digitalWrite(red_led, LOW);
    digitalWrite(green_led, HIGH);
    real_distance = distanceSensor(0);
    }

    digitalWrite(green_led, LOW);
  }
  }



}
break;

default:
standby_mode(); // blinks all leds until 1,2 or 3 is selected



}
}
}

//---------------------------------------  FUNCTIONS  -----------------------


//----------------------------------- Red light function
void red_light()
{
digitalWrite(red_led, HIGH);
delay(on_delay);
digitalWrite(red_led,LOW);
}

//---------------------------------- Yellow light function
void yellow_light()
{
digitalWrite(yellow_led, HIGH);
delay(off_delay);
digitalWrite(yellow_led,LOW);
}

//--------------------------------- Green light function
void green_light()
{
digitalWrite(green_led, HIGH);
delay(on_delay);
digitalWrite(green_led,LOW);

}

//------------------------------ --- Distance sensor function
float distanceSensor(int x)
{
 digitalWrite(TRIGPIN, LOW);
 delayMicroseconds(2);
 digitalWrite(TRIGPIN,HIGH);
 delayMicroseconds(10);
 digitalWrite(TRIGPIN,LOW); 
 float distance = pulseIn(ECHOPIN, HIGH);
 distance = distance/58;
 Serial.print(distance);
 Serial.println("cm");
 delay(200);

 float distance_reading = distance;

 return distance_reading;
}

//------------------------------------- LDR sensor function

float LDRSensor(int h)
{
  sensorValue = analogRead(ldrPin);    
  voltage = sensorValue * (5000.0 / 1024.0);
  Serial.print("Sensor Output: ");
  Serial.println(sensorValue);
  Serial.print("Voltage (mv): ");
  Serial.println(voltage);
  Serial.println();
  delay(5000);
  return sensorValue;
}


//------------------------------------- Buzzer Function

void buzzer(unsigned char delayms)
{
  analogWrite(The_buzzer, 20);
  delay(delayms);
  analogWrite(The_buzzer, 0); 
  delay(delayms);   

}

// ------------------------------------- Standby Mode

void standby_mode()
{
  for ( int a= 10; a < 14; a++)
  {
    digitalWrite(a,HIGH);
  }

    delay(off_delay);

  for (int b=10; b < 14; b++)
  {
    digitalWrite(b,LOW);
  }
    delay(off_delay);

}
2
What is that unexpected distanceSensor(0); // distance sensor function in the beginning of the loop() function between if (Serial.available()>0) and the block {...} ?J. Piquard
There is no code that calls your loop function, so you may need to post more. But, AFAICT, once you enter a give case within the switch statement, you have an infinite loop. (e.g. for case '1':, you do while (true) with no break. Likewise for the other while statements for each case, so you may need to restructure things a bit, so you have one while and each case just does a single iteration. That is, move the loop outside of the switch/caseCraig Estey
The solution of your problem ==> state-machine.J. Piquard
@J.Piquard It wouldn't run the standby mode without it. However, I have made an adjustment and replaced it with the standby mode function. Thank You for your reply, I will have a look at the state machine.JCassio
@CraigEstey I have tried doing "while(inval == 3)" but if I input a different number to the serial monitor it remains in the loop. So my option was (while true). My intention is to make it loop inside each case until another number is entered to the serial monitorJCassio

2 Answers

1
votes

As I mentioned in my top comments, once you enter a given case, you never leave it (i.e. things get "stuck")

So, as I said, have a single outer loop, and each case just does one iteration.

Also, note that, below, inVal only gets changed if the serial port has input data available. So, the single loop approach mimics the multiple loops but still responds to changes in input.

Here is something that I think gets you closer to your intent [please pardon the gratuitous style cleanup]:

//----------------------- Variables
#define ECHOPIN 3
#define TRIGPIN 2
char inVal;
String inString = "";
const int red_led = 11;
const int yellow_led = 12;
const int green_led = 13;
const int on_delay = 2000,
    off_delay = 1000;                   // led delays
const int min_distance = 10;            // Distance sensor min distance
const int The_buzzer = 4;
float real_distance;                    // Distance obtained from function
int ldrPin = A0;                        // LDR pin
unsigned int sensorValue = 0;
float voltage;
float light_amount;
int brightness = 600;                   // amount of light treshhold
int button_one = 5;
String ButtonOne;

void
setup()
{

    pinMode(red_led, OUTPUT);
    pinMode(yellow_led, OUTPUT);
    pinMode(green_led, OUTPUT);
    pinMode(The_buzzer, OUTPUT);
    Serial.begin(9600);
    pinMode(ECHOPIN, INPUT);
    pinMode(TRIGPIN, OUTPUT);
    pinMode(button_one, INPUT);
}

void
loop()
{

    // distance sensor function
    if (Serial.available() > 0)
        distanceSensor(0);

    while (1) {
        if (Serial.available() > 0)
            inVal = Serial.read();

        switch ((inVal) | (ButtonOne == "HIGH")) {
        case '1':  // Regular Mode
            red_light();
            yellow_light();
            green_light();
            yellow_light();
            break;

        case '2':  // Pedestrian Mode
            real_distance = distanceSensor(0);

            if (real_distance < min_distance) {
                for (int a = 0; a < 10; a++) {
                    tone(The_buzzer, 1000);
                    delay(1000);
                    noTone(The_buzzer);
                    delay(1000);
                    digitalWrite(yellow_led, HIGH);
                    delay(100);
                    digitalWrite(yellow_led, LOW);
                }
            }

            real_distance = distanceSensor(0);

            if (real_distance > min_distance) {
                red_light();
                yellow_light();
                green_light();
                yellow_light();
            }
            break;

        case '3':  // NIGHT MODE
            light_amount = LDRSensor(0);
            real_distance = distanceSensor(0);

            if (light_amount > brightness) {
                red_light();
                yellow_light();
                green_light();
                yellow_light();
                red_light();
                delay(100);
            }

            if (light_amount < brightness || real_distance < min_distance) {

                real_distance = distanceSensor(0);  // distance sensor reading

                if (real_distance > min_distance) {
                    digitalWrite(green_led, LOW);
                    digitalWrite(red_led, HIGH);
                }

                if (real_distance < min_distance) {

                    while (real_distance < min_distance && light_amount < brightness) { // maybe change this
                        digitalWrite(red_led, LOW);
                        digitalWrite(green_led, HIGH);
                        real_distance = distanceSensor(0);
                    }

                    digitalWrite(green_led, LOW);
                }
            }
            break;

        default:  // blinks all leds until 1,2 or 3 is selected
            standby_mode();
            break;
        }
    }
}

//---------------------------------------  FUNCTIONS  -----------------------

//----------------------------------- Red light function
void
red_light()
{
    digitalWrite(red_led, HIGH);
    delay(on_delay);
    digitalWrite(red_led, LOW);
}

//---------------------------------- Yellow light function
void
yellow_light()
{
    digitalWrite(yellow_led, HIGH);
    delay(off_delay);
    digitalWrite(yellow_led, LOW);
}

//--------------------------------- Green light function
void
green_light()
{
    digitalWrite(green_led, HIGH);
    delay(on_delay);
    digitalWrite(green_led, LOW);

}

//------------------------------ --- Distance sensor function
float
distanceSensor(int x)
{

    digitalWrite(TRIGPIN, LOW);
    delayMicroseconds(2);
    digitalWrite(TRIGPIN, HIGH);
    delayMicroseconds(10);
    digitalWrite(TRIGPIN, LOW);
    float distance = pulseIn(ECHOPIN, HIGH);

    distance = distance / 58;
    Serial.print(distance);
    Serial.println("cm");
    delay(200);

    float distance_reading = distance;

    return distance_reading;
}

//------------------------------------- LDR sensor function

float
LDRSensor(int h)
{

    sensorValue = analogRead(ldrPin);
    voltage = sensorValue * (5000.0 / 1024.0);
    Serial.print("Sensor Output: ");
    Serial.println(sensorValue);
    Serial.print("Voltage (mv): ");
    Serial.println(voltage);
    Serial.println();
    delay(5000);

    return sensorValue;
}

//------------------------------------- Buzzer Function

void
buzzer(unsigned char delayms)
{

    analogWrite(The_buzzer, 20);
    delay(delayms);
    analogWrite(The_buzzer, 0);
    delay(delayms);
}

// ------------------------------------- Standby Mode

void
standby_mode()
{

    for (int a = 10; a < 14; a++) {
        digitalWrite(a, HIGH);
    }

    delay(off_delay);

    for (int b = 10; b < 14; b++) {
        digitalWrite(b, LOW);
    }
    delay(off_delay);
}
0
votes

I think you didn't get the way arduino sketches works. The loop() function is called every time in a continuous loop (like a while(true)), so you should make your logic take advantage of this fact.

You use infinite loops inside the loop() function (which is already an infinite loop) so your code gets stuck in one of these loops and never get out, so it will never read the serial buffer or the GPIO pins.