If Else statement in Loop

Hello, I’m a newbie and I really need some helps for my project.

I’m building a simple parking reservation system using NodeMCU and an Android apps. I have 2 LEDs which are Red and Yellow and also an IR Sensor.

So here how I want it to work,

By default both LEDs are off. When a user click on Reservation button on the app, the yellow led will light up and when the user finally park their car which will be detected by the IR Sensor, the red LED will light up and the yellow LED will light off.

The code for the apps is working but when I combine with the IR Sensor code, it doesn’t work. Can someone help me? I’ve commented HERE on the code that need to be focused at. Thanks in advance.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>

#define IR D6              //  connect IR Sensor on pin D6
#define RedLED D4          //  connect Red LED on pin D4
#define YellowLED D3       //  connect Red LED on pin D4

int slot1;
String  command;

const char* ssid = "TP-LINK_M5_D79F4C";    // WiFi Name
const char* password = "10250712";         // WiFi Password

ESP8266WebServer server(80);

//SCL - D1 and SDA - D2
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);   

void setup(){
  
   Serial.begin(9600);
   pinMode(IR, INPUT);   
   pinMode(RedLED, OUTPUT);
   pinMode(YellowLED, OUTPUT);

  
  // turn on LCD backlight                      
  lcd.backlight();
  lcd.begin(16, 2);             // LCD 16 columns and 2 rows
  lcd.print("Smart Parking");   // Print on first row of LCD
  delay(10);
  lcd.setCursor(0, 1);          // Move the cursor to the next line and print
  lcd.print("System");
  delay(3000);
  lcd.clear();
  Serial.println("Starting Project......");
  Serial.println();


  //WiFi connection
  Serial.println();
  Serial.print("Wifi connecting to ");
  Serial.println( ssid );
  WiFi.begin(ssid,password);
  Serial.println();
  Serial.print("Connecting");

  while( WiFi.status() != WL_CONNECTED ){
      delay(500);
      Serial.print(".");        
  }

  Serial.println();
  Serial.println("Wifi Connected Success!");
  Serial.print("NodeMCU IP Address: ");
  Serial.println(WiFi.localIP() );

  // Starting WEB-server 
  server.on ( "/", HTTP_handleRoot );
  server.onNotFound ( HTTP_handleRoot );
  server.begin();
}

//Button on the apps

 void Reserve()
  {
     digitalWrite(YellowLED, HIGH);
  }

void loop(){
  
 slot1 = digitalRead(IR);    // read IR Sensor
 delay(500);

 // HERE
  server.handleClient();
  command = server.arg("State");
  if (command == "Reserve") Reserve();

 else if (slot1 == 0)                    // parking is occupied
 {                
   digitalWrite(RedLED, HIGH);
   lcd.setCursor(1, 0);                 // move the cursor to the next line and print
   lcd.print("Slot 1: 0");
   delay(500);
}

 else if  (slot1 == 1)                               // parking is vacant
 {
   digitalWrite(RedLED, LOW);            
   lcd.setCursor(1, 0);   
   lcd.print("Slot 1: 1");
   delay(100);
 }

}

void HTTP_handleRoot(void) 
{
 if(server.hasArg("State"))
 {
    Serial.println(server.arg("State"));
 }
 server.send ( 200, "text/html", "" );
 delay(1);
}

Could you describe the behavior when it “doesn’t work?

Perhaps start by adding some debugging Serial.print statements to trace the of slot1 through the loop.

you should handle the command = server.arg("State");only when you get the HTTP request in HTTP_handleRoot not every time in the loop.

You should not turn on the yellow led if a car is already parked there

your code needs a better state machine (3 states: SLOT_EMPTY, SLOT_RESERVED, SLOT_OCCUPIED)

I'm not sure if you want to work your logic the following way:

whenever your variable command contains the character-sequence "Reserve" execute
the command Reserve();

whenever the variable command contains something different than the character-sequence "Reserve"

check if slot1 == 0
and if true
do

    digitalWrite(RedLED, HIGH);
    lcd.setCursor(1, 0);                 // move the cursor to the next line and print
    lcd.print("Slot 1: 0");
    delay(500);

whenever the variable command contains something different than the character-sequence "Reserve"
AND check if slot1 == 0 results in false

check if (slot1 == 1) and if true
do

    digitalWrite(RedLED, LOW);
    lcd.setCursor(1, 0);
    lcd.print("Slot 1: 1");
    delay(100);

best regards Stefan
any newbee can apply the most professional habit from the first line of code they write on their own:
add only ONE thing at a time. Test/debug that ONE thing until that ONE thing works reliable - repeat.
The sad thing is: only the REAL professionals write code this way.

J-M-L:
you should handle the

command = server.arg("State");

only when you get the HTTP request in HTTP_handleRoot not every time in the loop.

You should not turn on the yellow led if a car is already parked there

your code needs a better state machine (3 states: SLOT_EMPTY, SLOT_RESERVED, SLOT_OCCUPIED)

Thank you Sir for the answer. You mean I have to add these lines of code into the HTTP_handleRoot? And also can you show me how should I do the 3 states? I'm sorry Sir, I'm not very good in coding and I really need helps.

 server.handleClient();
 command = server.arg("State");
 if (command == "Reserve") Reserve();

StefanL38:
I'm not sure if you want to work your logic the following way:

whenever your variable command contains the character-sequence "Reserve" execute
the command Reserve();

whenever the variable command contains something different than the character-sequence "Reserve"

check if slot1 == 0
and if true
do

    digitalWrite(RedLED, HIGH);

lcd.setCursor(1, 0);                // move the cursor to the next line and print
    lcd.print("Slot 1: 0");
    delay(500);




whenever the variable command contains something different than the character-sequence "Reserve"
AND check if slot1 == 0 results in false


check if (slot1 == 1) and if true 
do


digitalWrite(RedLED, LOW);
    lcd.setCursor(1, 0);
    lcd.print("Slot 1: 1");
    delay(100);





best regards Stefan
any newbee can apply the most professional habit from the first line of code they write on their own:
add only ONE thing at a time. Test/debug that ONE thing until that ONE thing works reliable - repeat.
The sad thing is: only the REAL professionals write code this way.

Thank you Sir for the answer. I would like to try the logic you gave me but it's still not clear to. Do i need to do it in multiple sets of If Else statement? I'm sorry Sir, I'm not very good in coding and I'm still learning.

petedd:
Could you describe the behavior when it “doesn’t work?

Perhaps start by adding some debugging Serial.print statements to trace the of slot1 through the loop.

Hi Sir, the apps code and IR sensor code are working fine separately but when I combine them in void loop, only sensor is working while the apps code doesn't working. I believe it has something to do with my If Else statements but I don't know the exact way to fix. I'm sorry I'm very weak in coding but I'm willing to learn from this forum.

You create a state variable (ideally an enum)

Initial value at boot is either SLOT_EMPTY or SLOT_OCCUPIED depending on what the IR sensors says

The loop is a switch on the state for 3 possible values: SLOT_EMPTY, SLOT_RESERVED, SLOT_OCCUPIED

in case of SLOT_EMPTY you check if a car took the spot. That would be a violation of the rules since there was no reservation made. Your system needs to handle that and burn the offending car. :)... state becomes SLOT_OCCUPIED

In case of SLOT_OCCUPIED you check if the car is now gone. If so, the spot is free again and your state goes back to SLOT_EMPTY and you deal with the led

In case of SLOT_RESERVED, you check if a car took the spot. If so, state becomes SLOT_OCCUPIED and you deal with the led

Then separately the loop also calls the http handler which will allow for a slot reservation if the state is SLOT_EMPTY. You need to define how you let the web user know if she got the reservation or not.

J-M-L:
You create a state variable (ideally an enum)

Initial value at boot is either SLOT_EMPTY or SLOT_OCCUPIED depending on what the IR sensors says

The loop is a switch on the state for 3 possible values: SLOT_EMPTY, SLOT_RESERVED, SLOT_OCCUPIED

in case of SLOT_EMPTY you check if a car took the spot. That would be a violation of the rules since there was no reservation made. Your system needs to handle that and burn the offending car. :)... state becomes SLOT_OCCUPIED

In case of SLOT_OCCUPIED you check if the car is now gone. If so, the spot is free again and your state goes back to SLOT_EMPTY and you deal with the led

In case of SLOT_RESERVED, you check if a car took the spot. If so, state becomes SLOT_OCCUPIED and you deal with the led

Then separately the loop also calls the http handler which will allow for a slot reservation if the state is SLOT_EMPTY. You need to define how you let the web user know if she got the reservation or not.

Thank you very much Sir for the explanation. I already made the switch/case statement and the sensor works perfectly fine. Can you check if my SLOT_RESERVED case is correct?

enum {
  SLOT_EMPTY,
  SLOT_OCCUPIED,
  SLOT_RESERVED
};

unsigned char parkingState = SLOT_EMPTY;

void loop(){

  switch (parkingState) {

     case SLOT_EMPTY :
     Serial.println ("Slot: 1");
     digitalWrite(RedLED, LOW);
     lcd.setCursor(1, 0);   
     lcd.print("Slot: 1");
     delay(100);
     if (digitalRead(IR) == 0) {
      parkingState = SLOT_OCCUPIED;
      break;
     }

     else {
      break;
     }

     case SLOT_OCCUPIED :
     Serial.println ("Slot: 0");
     digitalWrite(RedLED, HIGH);
     lcd.setCursor(1, 0);
     lcd.print("Slot: 0");
     delay(500);
     if(digitalRead(IR) == 1) {
      parkingState = SLOT_EMPTY;
      break;
     }

     else {
      break;
     }

     case SLOT_RESERVED :
     Serial.println ("Slot: R");
     digitalWrite(YellowLED, HIGH);
     if(digitalRead(IR) == 1) {
      parkingState = SLOT_EMPTY;
      break;
     }

     else {
      break;
     }

     default :
     parkingState = SLOT_EMPTY;
     break;
  }
}

void HTTP_handleRoot(void) 
{
 if(server.hasArg("State"))
 {
    Serial.println(server.arg("State"));
 }
 
 server.send ( 200, "text/html", "" );
 delay(1);
}

Now I'm a bit confused where to put the this part. Can you help me?

void Cancel()
  {
     digitalWrite(YellowLED, LOW);
  }

 void Reserve()
  {
     digitalWrite(YellowLED, HIGH);
  }

 server.handleClient();
 command = server.arg("State");
 if (command == "Reserve") Reserve();
 else if (command == "Cancel") Cancel();

an enum is a type, so you could write it this way

 enum : byte { // : byte to have byte storage. default otherwise is int which is 4 bytes. waste of memory space
  SLOT_EMPTY,
  SLOT_OCCUPIED,
  SLOT_RESERVED
} parkingState = SLOT_EMPTY;

try to stick to semantics, digitalRead() returns HIGH or LOW, so for code readability don't write    if(digitalRead(IR) == 1) { but     if(digitalRead(IR) == HIGH) {

when you declare  server.on ( "/", HTTP_handleRoot );you are telling your server instance to call the function HTTP_handleRoot() when someone tries to access the root (/) of your web site.

The idea would be that when someone validates a slot, you set the parkingState to SLOT_RESERVED within the handler, which in turn will impact that state machine the next time it runs.

Note: that's a weird idea to have the same handler when the requested page does not exist.

  server.onNotFound ( HTTP_handleRoot );

is there a user interface for your web site? I don't see any HTML. how do I know which slot I want to reserve? can I cancel ? can I see the status of the parking slots?

J-M-L:
an enum is a type, so you could write it this way

 enum : byte { // : byte to have byte storage. default otherwise is int which is 4 bytes. waste of memory space

SLOT_EMPTY,
  SLOT_OCCUPIED,
  SLOT_RESERVED
} parkingState = SLOT_EMPTY;




try to stick to semantics, digitalRead() returns HIGH or LOW, so for code readability don't write`     if(digitalRead(IR) == 1) {` but `     if(digitalRead(IR) == HIGH) {`

when you declare`  server.on ( "/", HTTP_handleRoot );`you are telling your server instance to call the function HTTP_handleRoot() when someone tries to access the root (/) of your web site.

The idea would be that when someone validates a slot, you set the parkingState to SLOT_RESERVED within the handler, which in turn will impact that state machine the next time it runs.

Note: that's a weird idea to have the same handler when the requested page does not exist.

server.onNotFound ( HTTP_handleRoot );




is there a user interface for your web site? I don't see any HTML. how do I know which slot I want to reserve? can I cancel ? can I see the status of the parking slots?

I use an Android App (MIT App Inventor 2) instead of a website. Is is possible? Should I post the code blocks here?

so are you using a web interface or a Serial (bluetooth) interface ?

J-M-L:
so are you using a web interface or a Serial (bluetooth) interface ?

J-M-L:
so are you using a web interface or a Serial (bluetooth) interface ?

I'm using WiFi to connect the apps with the NodeMCU board, if that's what you meant

OK - so likely an HTTP based component. What are the URL being triggered?

J-M-L:
OK - so likely an HTTP based component. What are the URL being triggered?

The URL will be triggered when I enter the IP address of the NodeMCU on the apps. And the when I click on the Reserve button on the apps, it will be working with with the “/?State=Reserve” . I have attached the image for the code blocks to let you know what actually I’m talking about.

The “State” and “Reserve” are from the code below.

void Cancel()
  {
     digitalWrite(YellowLED, LOW);
  }

 void Reserve()
  {
     digitalWrite(YellowLED, HIGH);
  }

 server.handleClient();
 command = server.arg("State");
 if (command == "Reserve") Reserve();
 else if (command == "Cancel") Cancel();

I’m sorry if this is messed up but I hope I can solve the problems because I don’t know what else to do.

Image.PNG

here is the image

Image.PNG

start by testing if your / URL is triggered and print the details of the request including "State". then you'll know if that part works

J-M-L:
start by testing if your / URL is triggered and print the details of the request including "State". then you'll know if that part works

Thank you Sir, I'll be working on that part.