Barrier Project Problem

Hi,

I have done programming in various languages, so I can say that I have experience in programming. But, I haven't used Arduino for a while and now I have to do a project using Arduino.

I have written a code for a barrier which can be used to control the number of people in a shop. If the number of people inside the shop is less than the maximum number allowed, barrier will let the customer enter the shop.

Moreover, barrier can be used in different configurations such as; it can be used as both entrance and exit(if the barrier is set to neither entrance or exit), or only entrance(if the barrier is set to entrance), or only exit(if the barrier is set to exit). This configuration will be determined by choosing one of the 3 states of a switch. Also, considering that barrier may be placed on the right side or left, there is another switch which determines which side it is placed(if placedOnLeftSide is set, then the barrier is placed on the left side).

There is also a laser sensor which can determine if someone passed the barrier when the barrier is lowered. The sensor also triggers an alarm led and a buzzer if someone tries to pass the barrier while it is lowering or raising or raised already.

But, I couldn't make the code work properly. Since, I haven't used Arduino for some time I may be doing something wrong. I want to ask if you can check my code and tell me if it is correct. I have been struggling to make this code work for a couple of days, but I couldn't.

For example, even though the laser of the sensor I connected to the pin 33 (accidentSensor) is not interrupted(it should be LOW), I see that both alarmBuzzer and alarmRed turns on. I can't find any meaning to this.

I attached the code file, and also pasting it here. Thank you for any contributions.

The Code:

#include <LiquidCrystal.h>

LiquidCrystal lcd(41, 40, 39, 38, 37, 36);
int lowerBarrier = 26;
int raiseBarrier = 27;
int barrierRaised = 28;
int barrierLowered = 29;
int stateEntrance = 30;
int stateExit = 31;
int placedOnLeftSide = 32;
int accidentSensor = 33;
int TouchButtonFront = 34;
int TouchButtonRear = 35;
int alarmBuzzer = 36;
int alarmLED = 37;
bool barrierIsLowering = false;
bool barrierIsRaising = false;
bool enteringRequest = false;
bool exitingRequest = false;
bool firstRun = true;
int maxNumberOfPeople = 10;
int numberOfPeopleInside = 0;

void shopIsFull(){
lcd.clear();
lcd.home();
lcd.print(" SHOP IS FULL. PLEASE WAIT.");
}
void youCanPass(){
lcd.clear();
lcd.home();
lcd.print("PASS AFTER BARRIER IS LOWERED");
}
void byeBye(){
lcd.clear();
lcd.home();
lcd.print(" THANK YOU FOR VISITING ");
}
void defaultScreen(){
lcd.clear();
lcd.home();
lcd.print("NUMBER OF PEOPLE INSIDE: ");
}
bool enterRequest(){
if(numberOfPeopleInside < maxNumberOfPeople){
digitalWrite(lowerBarrier, HIGH);
barrierIsLowering = true;
youCanPass();
}else{
shopIsFull();
}
return true;
}
bool exitRequest(){
byeBye();
digitalWrite(lowerBarrier, HIGH);
barrierIsLowering = true;
return true;
}

void setup() {
lcd.begin(16, 2);

pinMode(lowerBarrier, OUTPUT);
pinMode(raiseBarrier, OUTPUT);
pinMode(barrierLowered, INPUT);
pinMode(barrierRaised, INPUT);
pinMode(stateEntrance, INPUT);
pinMode(stateExit, INPUT);
pinMode(placedOnLeftSide, INPUT);
pinMode(accidentSensor, INPUT);
pinMode(TouchButtonFront, INPUT);
pinMode(TouchButtonRear, INPUT);
pinMode(alarmBuzzer, OUTPUT);
pinMode(alarmLED, OUTPUT);

barrierIsLowering = false;
barrierIsRaising = false;
enteringRequest = false;
exitingRequest = false;
firstRun = true;
maxNumberOfPeople = 10;
numberOfPeopleInside = 0;

if(firstRun == true){
if(digitalRead(barrierRaised) == LOW){
digitalWrite(raiseBarrier, HIGH);
barrierIsRaising = true;
firstRun = false;
}
}
}

void loop() {
if(barrierIsLowering == false && barrierIsRaising == false){
if(digitalRead(placedOnLeftSide) == HIGH){ // The system is placed on the left side
if(digitalRead(stateEntrance) == LOW && digitalRead(stateExit) == LOW){ // Entrance and exit can be done on the same gate
if(digitalRead(TouchButtonFront) == HIGH && digitalRead(barrierRaised) == HIGH){ // Entering request
enteringRequest = enterRequest();
}else if(digitalRead(TouchButtonRear) == HIGH && digitalRead(barrierRaised) == HIGH){ // Exitting request
exitingRequest = exitRequest();
}
}else if(digitalRead(stateEntrance) == HIGH){ // Only entrance can be done on the gate
if(digitalRead(TouchButtonFront) == HIGH && digitalRead(barrierRaised) == HIGH){ // Entering request
enteringRequest = enterRequest();
}
}else if(digitalRead(stateExit) == HIGH){ // Only exitting can be done on the gate
if(digitalRead(TouchButtonRear) == HIGH && digitalRead(barrierRaised) == HIGH){ // Exitting request
exitingRequest = exitRequest();
}
}
}else if(digitalRead(placedOnLeftSide) == LOW){ // The system is placed on the right side
if(digitalRead(stateEntrance) == LOW && digitalRead(stateExit) == LOW){ // Entrance and exit can be done on the same gate
if(digitalRead(TouchButtonFront) == HIGH && digitalRead(barrierRaised) == HIGH){ // Exitting request
exitingRequest = exitRequest();
}else if(digitalRead(TouchButtonRear) == HIGH && digitalRead(barrierRaised) == HIGH){ // Entering request
enteringRequest = enterRequest();
}
}else if(digitalRead(stateEntrance) == HIGH){ // Only entrance can be done on the gate
if(digitalRead(TouchButtonRear) == HIGH && digitalRead(barrierRaised) == HIGH){ // Entering request
enteringRequest = enterRequest();
}
}else if(digitalRead(stateExit) == HIGH){ // Only exitting can be done on the gate
if(digitalRead(TouchButtonFront) == HIGH && digitalRead(barrierRaised) == HIGH){ // Exitting request
exitingRequest = exitRequest();
}
}
}
}

if(barrierIsLowering == true && digitalRead(barrierLowered) == HIGH){
digitalWrite(lowerBarrier, LOW);
barrierIsLowering = false;
}
if(barrierIsRaising == true && digitalRead(barrierRaised) == HIGH){
digitalWrite(raiseBarrier, LOW);
barrierIsRaising = false;

if(enteringRequest == true){
numberOfPeopleInside++;
enteringRequest = false;
}
if(exitingRequest == true){
numberOfPeopleInside--;
exitingRequest = false;
}
defaultScreen();
}

if(digitalRead(accidentSensor) == HIGH){
if(barrierIsLowering == true || barrierIsRaising == true){
digitalWrite(lowerBarrier, LOW);
barrierIsLowering = false;
digitalWrite(raiseBarrier, LOW);
barrierIsRaising = false;

digitalWrite(alarmBuzzer, HIGH);
digitalWrite(alarmLED, HIGH);
}else if(digitalRead(barrierRaised) == HIGH){
digitalWrite(alarmBuzzer, HIGH);
digitalWrite(alarmLED, HIGH);
}else if(digitalRead(barrierLowered) == HIGH){
delay(5000);
digitalWrite(raiseBarrier, HIGH);
barrierIsRaising = true;
}
}

if(barrierIsLowering == true && barrierIsRaising == true){
digitalWrite(lowerBarrier, LOW);
digitalWrite(raiseBarrier, LOW);
barrierIsLowering = false;
barrierIsRaising = false;
}
}

BarrierProject_Updated_Again.ino (5.6 KB)

 if(barrierIsLowering == true && barrierIsRaising == true)

I have not looked at your code in detail, but judging by the names of the variables the above test is never likely to be true

Why did you not post your code in code tags to make it easier to copy for examination ?

this code is very hard to follow with all the nested if statements and direct reads of pins

i believe it would be easier to implement this as a state machine, but even that gets complicated

one aspect of a state machine is to separate the raw input information from the stimulus to the state machine. In other words, read all the inputs, potential debounce, filter, possibly combine them to determine a stimulus to the state machine

and then for each state determine the action based on the stimulus without needing to be concerned about whether an input is high or low.

i made an attempt at some code (tested). (ignore the ledPins)

What I like about table driven state machines that use symbols that make it easy to see if no action or no state change occurs is that it's easy to see the logic in just a few lines without having to look at a lot of code

i attempted to capture the event of approaching the barrier causing it to open, and leaving the barrier causing it to close. entering is contingent on the occupancy of the store while leaving is not. this is not part of the state macine but a condition that determines a stimulus (incomplete)

There's an assumption that crossing a sensor on one side of the barrier should be followed by a sensor crossing on the opposite. But a more accurate sensor would be a double sensor that also indicates direction. Such a sensor would indicate a person is moving toward or away from the barrier. This might be required if some crosses that sensor toward the barrier and is then told they need to wait and they then back away making room for someone to leave. I attempted to capture this by having separate stimuli for entering and exiting the barrier on the same side, the outside.

another thing about state machines is they help you think about the problem instead of the code and you realize all the complexities.

have no idea what you ment by barrier on left or right side

// control entrance barrier and display

byte butPins [] = { A1, A2, A3 };
byte ledPins [] = { 10, 11, 12 };

#define N_PINS sizeof(butPins)

byte butLst [N_PINS] = {};

int  debug = 0;

// -----------------------------------------------------------------------------
void setup (void)
{
    Serial.begin (115200);

    for (unsigned n = 0; n < N_PINS; n++)  {
        digitalWrite (ledPins [n], HIGH);
        pinMode      (ledPins [n], OUTPUT);

        pinMode      (butPins [n], INPUT_PULLUP);
        butLst [n]  = digitalRead (butPins [n]);
    }
}

// -----------------------------------------------------------------------------
enum { B_RELEASED, B_PRESSED };

byte butState [N_PINS] = {};
byte butPress [N_PINS] = {};
int  nButPressed       = 0;

void
chkButtons (void)
{
    char s [40];
    for (unsigned n = 0; n < N_PINS; n++)  {
        byte but = digitalRead (butPins [n]);

        if (butLst [n] != but)  {
            butLst [n] = but;

            if (debug) {
                sprintf (s, "%s: but %d change", "chkBut", n);
                Serial.println (s);
            }

            if (LOW == but)  {  // button pressed
                butState [n] = B_PRESSED;
                butPress [n] = 1;
                nButPressed ++;
                if (debug) {
                    sprintf (s, "%s: but %d pressed %d",
                        __func__, n, butPress [n]);
                    Serial.println (s);
                }
            }
            else  {
                butState [n] = B_RELEASED;
                nButPressed --;
                if (debug) {
                    sprintf (s, "%s: but %d released", "chkBut", n);
                    Serial.println (s);
                }
            }
        }
    }

    delay (10);         // debounce
}

// -----------------------------------------------------------------------------
char s [40];

void ____ (void) {
}

void alarm (void) {
    Serial.println (__func__);
}

void close (void) {
    Serial.println (__func__);
}

void enter (void) {
    Serial.println (__func__);
}

void in    (void) {
    Serial.println (__func__);
}

void leave (void) {
    Serial.println (__func__);
}

void open  (void) {
    Serial.println (__func__);
}

void test  (void);

// -------------------------------------
typedef enum {
    ST_CL,
    ST_OP,
    ST_EN,
    ST_IN,
    ST_EX,
    ST_LE,
    ST_AL,
    ST_N,
    ST___,
} State_t;

typedef enum {
    STIM_NONE,
    STIM_ENTER,
    STIM_EXIT,
    STIM_LEAVE,
    STIM_CONFLICT,
} Stim_t;

int  nextState[][ST_N] = {
//    closed  open, enter,    in,  exit, leave, alarm
    { ST___, ST___, ST_OP, ST_CL, ST___, ST_OP, ST___ },    // STIM_NONE
    { ST_EN, ST___, ST___, ST___, ST___, ST___, ST___ },    // STIM_ENTER
    { ST___, ST_CL, ST___, ST___, ST___, ST___, ST___ },    // STIM_EXIT
    { ST_LE, ST_IN, ST___, ST___, ST___, ST___, ST___ },    // STIM_LEAVE
};

void (*func [][ST_N]) (void) = {
//    closed  open, enter,    in,  exit, leave, alarm
    {  ____,  ____,  open, close,  ____,  open,  ____  },    // STIM_NONE
    { enter, alarm,  ____,  ____,  ____,  ____,  ____  },    // STIM_ENTER
    {  ____, close,  ____,  ____,  ____,  ____,  ____  },    // STIM_EXIT
    { leave,    in,  ____,  ____,  ____, alarm,  ____  },    // STIM_LEAVE
};

// -------------------------------------
void test  (void) {
    Serial.println (__func__);
    for (int row = 0; row < 4; row++)  {
        for (int col = 0; col < ST_N; col++)  {
            char s [30];
            sprintf (s, " %2d", nextState [row][col]);
            Serial.print (s);
        }
        Serial.println ();
    }
}
// -------------------------------------
const char *stims [] = {
    "STIM_NONE",
    "STIM_ENTER",
    "STIM_EXIT",
    "STIM_LEAVE",
    "STIM_CONFLICT",
};

// -------------------------------------
int state = ST_CL;

void
updateState (
    Stim_t stim)
{
    char s [80];
#if 1
 // if (STIM_NONE != stim)  {
    if (____ != func [stim][state] || STIM_NONE != stim)  {
        sprintf (s, "%s: %d %s", __func__, state, stims [stim]);
        Serial.println (s);
    }
#endif

    int nxtSt = nextState [stim][state];

    func [stim][state] ();

    if (ST___ != nxtSt)  {
        state = nxtSt;
#if 1
        sprintf (s, " %s: %d", __func__, state);
        Serial.println (s);
#endif
    }
}


// -----------------------------------------------------------------------------
void
wait ()
{
    Serial.println (__func__);
}

// -----------------------------------------------------------------------------
#define BUT_ENTER   0
#define BUT_EXIT    2
#define BUT_LEAVE   1

#define MAX_OCCUPANCY   5
int occupancy = 0;

void
loop (void)
{
    chkButtons ();

    Stim_t stim = STIM_NONE;

    if (nButPressed)  {
        if (butPress [BUT_ENTER] && butPress [BUT_LEAVE])  {
            stim = STIM_CONFLICT;
        }
        else if (butPress [BUT_ENTER])  {
 //         Serial.println ("loop: enter press");
            if (MAX_OCCUPANCY > occupancy)  {
                stim = STIM_ENTER;
                occupancy++;
            }
            else
                wait();
            butPress [BUT_ENTER] = 0;
        }
        else if (butPress [BUT_LEAVE])  {
 //         Serial.println ("loop: leave press");
            stim = STIM_LEAVE;
            butPress [BUT_LEAVE] = 0;
        }
        else if (butPress [BUT_EXIT])  {
 //         Serial.println ("loop: exit press");
            stim = STIM_EXIT;
            occupancy--;
            butPress [BUT_EXIT] = 0;
        }

#if 0
        if (STIM_NONE != stim)  {
            sprintf (s, " %s: %s", __func__, stims [stim]);
            Serial.println (s);
        }
#endif
    }

    updateState (stim);
}

It turns out code was without flaws, the problem with the project was that every input turned out to be floating.

I used changed every input as "INPUT_PULLUP" and changed the supply connections. It worked. I will leave this code here in case someone wants to do the project.

Thanks UKHeliBob and gcjr for caring and help.