A programing exercise - School Bus Alternating Lights

Hi guys;

I just finish my programing excercise or "homework". It a school bus alternating light simulator. It simply the same way when you operated a school bus warning lights system and with a stop arm and crossing gate. I did have a few problems when I program it, because when I close the door, the master is still on, and then close the master and re-open the door, I have the lights on, but it not supposed to. Because of that problem, I re-wrote the code and I have no problem ( so far ) My solution was to check for the master in all the while() loop and to use if ( (state==1) && (state2==1)) . The Master Switch is reponsible to turn on the school bus warning system. Sorry that my code look a bit "confusing". I was logical when I program it.

Anyway, feel free to comments, to "correct" my mistakes and teacher , please mark me :smiley: and tell me if I could do it better.

I drive a school bus for a living in Toronto, ON Canada, I know in the USA, they also use school buses. But I don't if they use school buses in the UK, France, Germany, Itally, ( Europe ) Russia, Asia ( Japan , China ) , Argentina, Brazil, Mexico ( South America ) , or in Australia ? Just wonderring

Here my code :

/*
  size : 1776 bytes
    
  Version 1.1
  
  file name : schoolbussignal.pde
  
  School Bus Alternating Light Simulator
  
  It simulate the activation system to activate the alternating
  red light, stop sign and crossing gate of the school bus.

  Here the parts you need :
 
  4 - 330 ohms limiting resistors for the LED's
  2 - Red LED
  2 - Green KED
  3 - 10 K resistor pull-down resistor
  2 - SPDT or SPST switch or DIP switch
  1 - Push-on button switch
  
  How it work :
  
  1. To activate the system, turn on MASTER switch.
  2. Press the push button to activate the Red Lights ONLY.
  3. When the door is open, a swtich is close ( the door switch is ON )
     and activate the stop sign ( left side of the bus )
     and crossing ( front of the bus ) gate.
  4. Close the door ( turn the door off ) to turn off everythings.
  5. When open the door ( turn on/off door switch ) and 
     Master switch is OFF, nothing will happen.
  6. Even you press the push button and the Master switch is OFF, 
     nothing will happen.  
    
  Program by Serge J Desjardins aka techone
  
  Compile and Tested 
   
*/  

// input pin
// pin 9 and 8 are not use in the program except in void setup()

byte businpin[5]={12,11,10,9,8};

/*
   pin 12 : Master Switch
   pin 11 : Door Switch
   pin 10 : Push button to activate
   pin 9 : Front gard gate switch
   pin 8 : Stop Sign switch
*/

// output pin
// pin 5 and 3 are not use by the program except in void setup()

byte busoutpin[6]={7,6,5,4,3,2};

/*
   pin 7 : Alterning Light A
   pin 6 : Alterning Light B
   pin 5 : Front gard gate motor direction
   pin 4 : Front gard gate motor on/off
   pin 3 : Stop sign motor direction
   pin 2 : Stop sign motor on/off
*/
byte i;

boolean master=0; // Master Switch
boolean door=0;  // Door Switch
boolean pushbutton=0; // Push Button
boolean buttonstate=0; // State Control
boolean doorstate=0;

void setup()
{ // init out & in pin
  for (i=0;i<5;i++)
  {
    pinMode(businpin[i],INPUT);
    pinMode(busoutpin[i],OUTPUT);
  }
  pinMode(busoutpin[5],OUTPUT);
  for (i=0;i<6;i++)
  {
    digitalWrite(busoutpin[i], LOW);
  }  
  buttonstate=0;
  doorstate=0;
  turnoff(); 
}

void loop()
{
  master=digitalRead(businpin[0]);
  delay (100);
  // stay in the loop and check the master switch
  while (master==0)
  { 
    master=digitalRead(businpin[0]);
    delay (100);
  }
  // check the push button
  pushbutton=digitalRead(businpin[2]);
  delay (100);
  if ((pushbutton==1) && (master==1))
  {
    // a push button is press
    buttonstate=1;
  }  
  // check the door switch
  door=digitalRead(businpin[1]);
  delay (100);
  if ((door==1) && (master==1))
  {
    // door switch is ON
    doorstate=1;
    buttonstate=1;
  }
  if ((door==1) && (master==0))
  {
     // door is open AND master switch is OFF
     doorstate=0;
     buttonstate=0;
  } 
  // stay in the loop if master switch is on
  // check for the push button ON or door switch ON  
  while ((buttonstate==0) && (doorstate==0))
  {
    // check the master switch again
    master=digitalRead(businpin[0]);
    delay (100);
    // check push button again
    pushbutton=digitalRead(businpin[2]);
    delay (100);
    if ((pushbutton==1) && (master==1))
    {
      buttonstate=1;
    }
    // check the door switch again
    door=digitalRead(businpin[1]);
    delay (100);
    if ((door==1) && (master==1))
    {
      doorstate=1;
      buttonstate=1;
    }
    // when door is open and master switch is off
    if ((door==1) && (master==0))
    {
      doorstate=0;
      buttonstate=0;
    }   
  }
  // stay in loop when the master id ON AND the push button is press
  while ((master==1)  && (buttonstate==1))
  {
     // check the master switch again
     master=digitalRead(businpin[0]);
     delay (100);
     if ((master==1) && (buttonstate==1))
     {
       // push button is press AND master is ON
       alternating();
     }
    // check the door again   
     door=digitalRead(businpin[1]);
     delay(100);
     // the door is open with master on    
     if ((door==1) && (master==1))
     {
       doorstate=1;
       alternating();
       motorson();
       alternating();
     }
     // after the door was open and closing the door     
     if ((door==0) && (doorstate==1))
     {
       buttonstate=0;
     }  
   }
   // turn off everythings when master is off or door is close
   if ((master==0) || (door==0))
   {
    doorstate=0; 
    buttonstate=0; 
    motorsoff();
    turnoff();
   }
}   
// alternating red light routine
void alternating()
{
  digitalWrite(busoutpin[0], HIGH);
  digitalWrite(busoutpin[1], LOW);
  delay(500);
  digitalWrite(busoutpin[0], LOW);
  digitalWrite(busoutpin[1], HIGH);
  delay (500); 
}  
// turn off everythings routine
void turnoff()
{
  for (i=0; i<6;i++)
   {
     digitalWrite(busoutpin[i], LOW);
   }
}
//deploy stop sign motor and crossing gate motor
void motorson()
{
   digitalWrite(busoutpin[3], HIGH);
   digitalWrite(busoutpin[5], HIGH);  
}
//re-track back stop sign and crossing gate 
void motorsoff()
{
   digitalWrite(busoutpin[3], LOW);
   digitalWrite(busoutpin[5], LOW);
}
byte businpin[5]={12,11,10,9,8};

I don't imagine you're going to change the pins while the program is running, so why not make it "const"?

boolean master=0;
master=digitalRead(businpin[0]);

"digitalRead" returns an "int", not a boolean.
I can see no reason for "master" to have global scope.
What associates "master" with "businpin" index zero?
Or indices 3 and 5 of "busoutpin" with the stop sign motor and gate motor?
Define some constants.

for (i=0;i<5;i++)
  {
    pinMode(businpin[i],INPUT);
    pinMode(busoutpin[i],OUTPUT);
  }
  pinMode(busoutpin[5],OUTPUT);

Silly, and lazy. Write two loops.

In "setup":

 buttonstate=0;
  doorstate=0;

You already initialised them when you declared them; why do it again?

Making a loop counter byte i; a global is the sort of thing that will bite you on the derriere later; don't do it.

while (master==0)
  { 
    master=digitalRead(businpin[0]);
    delay (100);
  }
  // check the push button
  pushbutton=digitalRead(businpin[2]);
  delay (100);
  if ((pushbutton==1) && (master==1))

You couldn't get to the last "if" statement with "master" having any value other than "1" - why bother testing it?

You have (on some-level) safety-critical software, yet you have whole seconds worth of "delay"s when you cannot be examining switch states.

I don't if they use school buses in the UK,

Busses?
For schools?
That's just crazy-talk.

Thank you for correcting my "mistakes" and bad habits.

"digitalRead" returns an "int", not a boolean.

I am a bit comfuse here... when a digitalRead() is executed, it reading a 1 - 5 V or 0 - 0V , therefore 0 and 1 are boolean values that is why I declare them boolean, I don't know why you have to declare them int ( -32768 to 32768 ) ? an analogRead() has to be int.

about the array or declare pins, const byte is a good programing habit.

a global is the sort of thing that will bite you on the derriere later; don't do it.

What you mean by it ? A bad habit to declare a variable global ?

Busses?
For schools?
That's just crazy-talk.

In North America, ( USA and Canada ) School buses is useed to transported kids to schools. It look like in the UK, no school buses to transported kids to schools... Humm

You should always declare the receiving variable to be the same as the return type of the function called.
Or cast it.
"digitalRead" may only return zero or 1, but it returns them as "int"s, not "boolean".

Quote
a global is the sort of thing that will bite you on the derriere later; don't do it.

What you mean by it ? A bad habit to declare a variable global ?

You shouldn't declare a variable as a global unless you really need it to be global.
Loop counts rarely, if ever, fall into that category.

void clearRow (int row)
{
  for (i = 0; i < N_COLS; ++i) {
    col [row][i] = 0;
  }
}
void clearArray ()
{
  for (i = 0; i < N_ROWS; ++i)
    clearRow (i);
}

Imagine the mess, if "i" is declared global.

Yes, we have school buses, just not the yellow variety with flashing lights and no-overtaking rule.
I was joking.

You should always declare the receiving variable to be the same as the return type of the function called.
Or cast it.
"digitalRead" may only return zero or 1, but it returns them as "int"s, not "boolean".

OK, I will respect that. I hope is OK to use byte instead.

You shouldn't declare a variable as a global unless you really need it to be global.
Loop counts rarely, if ever, fall into that category.

OK, I get it.

Yes, we have school buses, just not the yellow variety with flashing lights and no-overtaking rule.
I was joking.

That is interesting. I guess the company who operated the school buses in the UK is National Express ( one of the companies ) ? They bought the company I work here in Toronto ( well, all over Canada ) and another company in the US. Just to let you know, if a car "bust " the red flashing light and he/she get caught by the cops, it is 6 demerit point off your licence AND $2000 fine AND you may have your driving licence suspended because at 15 point and lower, no licence for 6 months according to the MTO and in the drivers hand book. ( Ministry of Transportation - Province of Ontario ).

I change my code, I kept the 2 while() loop, check for the master in both loop, 1st loop stay there until the master is on and push button or door is open. In my second loop, it check the master or the door to shut off to turn the light and motors off.

Anyway I re-wrote my code, re-tested and it work. So here it is :

/*
  size : 1692 bytes
    
  Version 2.1
  
  file name : schoolbussignal.pde
  
  School Bus Alternating Light Simulator
  
  It simulate the activation system to activate the alternating
  red light, stop sign and crossing gate of the school bus.

  Here the parts you need :
 
  4 - 330 ohms limiting resistors for the LED's
  2 - Red LED
  2 - Green KED
  3 - 10 K resistor pull-down resistor
  2 - SPDT or SPST switch or DIP switch
  1 - Push-on button switch
  
  How it work :
  
  1. To activate the system, turn on MASTER switch.
  2. Press the push button to activate the Red Lights ONLY.
  3. When the door is open, a swtich is close ( the door switch is ON )
     and activate the stop sign ( left side of the bus )
     and crossing ( front of the bus ) gate.
  4. Close the door ( turn the door off ) to turn off everythings.
  5. When open the door ( turn on/off door switch ) and 
     Master switch is OFF, nothing will happen.
  6. Even you press the push button and the Master switch is OFF, 
     nothing will happen.  
    
  Program by Serge J Desjardins aka techone
  
  Re-Modify with the help of AWOL
  
  Compile and Tested 
   
*/  

// input pin

const byte masterpin=12;
const byte doorpin=11;
const byte pushbuttonpin=10;

/*
   pin 12 : Master Switch
   pin 11 : Door Switch
   pin 10 : Push button to activate
*/

// output pin

const byte busoutpin[4]={9,8,7,6};

/*
   pin 7 : Alterning Light A
   pin 6 : Alterning Light B
   pin 5 : Front gard gate motor on/off
   pin 4 : Stop sign motor on/off
*/

byte master=0; // Master Switch
byte door=0;  // Door Switch
byte pushbutton=0; // Push Button

boolean buttonstate; // State Control
boolean doorstate;

void setup()
{ // init out & in pin
  pinMode(masterpin, INPUT);
  pinMode(doorpin, INPUT);
  pinMode(pushbutton, INPUT);
  for (int i=0;i<4;i++)
  {
    pinMode(busoutpin[i], OUTPUT);
  } 
   
  // turn the output pins off
  for (int i=0;i<4;i++)
  {
    digitalWrite(busoutpin[i], LOW);
  }  
  buttonstate=0;
  doorstate=0;
  turnoff(); 
}

void loop()
{  
  // check for the push button ON or door switch ON  
  while ((buttonstate==0) && (doorstate==0))
  {
    // check the master switch again
    master=digitalRead(masterpin);
    delay (100);
    // check push button again
    pushbutton=digitalRead(pushbuttonpin);
    delay (100);
    if ((pushbutton==1) && (master==1))
    {
      buttonstate=1;
    }
    // check the door switch again
    door=digitalRead(doorpin);
    delay (100);
    if ((door==1) && (master==1))
    {
      doorstate=1;
      buttonstate=1;
    }
    // when door is open and master switch is off
    if ((door==1) && (master==0))
    {
      doorstate=0;
      buttonstate=0;
    }   
  }
  // stay in loop when the master id ON AND the push button is press
  while ((master==1)  && (buttonstate==1))
  {
     // check the master switch again
     master=digitalRead(masterpin);
     delay (100);
     if ((master==1) && (buttonstate==1))
     {
       // push button is press AND master is ON
       alternating();
     }
    // check the door again   
     door=digitalRead(doorpin);
     delay(100);
     // the door is open with master on    
     if ((door==1) && (master==1))
     {
       doorstate=1;
       alternating();
       motorson();
       alternating();
     }
     // after the door was open and closing the door     
     if ((door==0) && (doorstate==1))
     {
       buttonstate=0;
     }  
   }
   // turn off everythings when master is off or door is close
   if ((master==0) || (door==0))
   {
    doorstate=0; 
    buttonstate=0; 
    motorsoff();
    turnoff();
   }
}   
// alternating red light routine
void alternating()
{
  digitalWrite(busoutpin[0], HIGH);
  digitalWrite(busoutpin[1], LOW);
  delay(500);
  digitalWrite(busoutpin[0], LOW);
  digitalWrite(busoutpin[1], HIGH);
  delay (500); 
}  
// turn off everythings routine
void turnoff()
{
  for (int i=0; i<4;i++)
   {
     digitalWrite(busoutpin[i], LOW);
   }
}
//deploy stop sign motor and crossing gate motor
void motorson()
{
   digitalWrite(busoutpin[2], HIGH);
   digitalWrite(busoutpin[3], HIGH);  
}
//re-track back stop sign and crossing gate 
void motorsoff()
{
   digitalWrite(busoutpin[2], LOW);
   digitalWrite(busoutpin[4], LOW);
}
for (int i=0;i<4;i++)
  {
    pinMode(busoutpin[i], OUTPUT);
  } 
   
  // turn the output pins off
  for (int i=0;i<4;i++)
  {
    digitalWrite(busoutpin[i], LOW);
  }

Why not simply

for (int i=0;i<4;i++)
  {
    pinMode(busoutpin[i], OUTPUT);
    digitalWrite(busoutpin[i], LOW);
  }

?

You know earlier when I asked what associates the pin with what it is connected to, and to define some constants?
Here, "motorson" operates on a different set of pins to "motorsoff" - is that intentionall?
If it is, maybe you could make it clearer why it is intentional, with a comment or constant describing the pin functions.

void motorson()
{
   digitalWrite(busoutpin[2], HIGH);
   digitalWrite(busoutpin[3], HIGH);  
}
//re-track back stop sign and crossing gate 
void motorsoff()
{
   digitalWrite(busoutpin[2], LOW);
   digitalWrite(busoutpin[4], LOW);
}

OK, I will respect that. I hope is OK to use byte instead.

Is that what you mean by respect? The variable used to hold the output of a function should be the same type as the function returns. Period.

@AWOL

for (int i=0;i<4;i++)
{
pinMode(busoutpin*, OUTPUT);*
_ digitalWrite(busoutpin*, LOW);_
_
} [/quote]_
Thank for that trick. I just realize that pinMode(busoutpin, OUTPUT); init the pin OUTPUT at pin i THAN digitalWrite(busoutpin, LOW); right after a pinMode.... Grr.. :cold_sweat: I did not think about that.
_> You know earlier when I asked what associates the pin with what it is connected to, and to define some constants?
> Here, "motorson" operates on a different set of pins to "motorsoff" - is that intentionall?
> If it is, maybe you could make it clearer why it is intentional, with a comment or constant describing the pin functions.
>
>
>
> ```_

> const byte busoutpin[4]={9,8,7,6};

/*
  pin 7 : Alterning Light A  <-- pin 9
  pin 6 : Alterning Light B  <-- pin 8
  pin 5 : Front gard gate motor on/off <-- pin 7
  pin 4 : Stop sign motor on/off <-- pin 6
/

> ```
No, was not intentional, it was simply OPPS... my mistakes. :blush:
@PaulS
> Is that what you mean by respect? The variable used to hold the output of a function should be the same type as the function returns. Period.
I mean respect AWOL opinion. I agree with you PaulS that when a function return , let say an int is return by a function, the value declare should be an int. I am always checking what type of variable is return by a function. In the case of digitalRead(anypin); return a 1 or 0. To my opinion they are Boolean value. That is why I declare them Boolean. So where it said that it return an int value ? That is the part that I am confuse here. It is because digitalRead is a port reading which is a byte value ? I hope you guys can see my confusion here.

It is because digitalRead is a port reading which is a byte value ?

Here is the prototype of "digitalRead", from "wiring.h"

int digitalRead(uint8_t);

Does that clear up the confusion?

No, was not intentional, it was simply OPPS... my mistakes

But you said that you'd tested it. :wink:

Here is the prototype of "digitalRead", from "wiring.h"

Ok That will explain. No boolean , a byte or int is OK. So it is a Port reading.

But you said that you'd tested it.

I tested with the pins at const byte busoutpin[4]={9,8,7,6}; not from the comment. I forgot to updated the comments. It from the old version. Opps... :blush: Heh ! no body is perfect. :wink:

I hate to break it to u but a byte, integer, boolean(true) all equal 00000001 and zero obviously too
When the processor reads it it doesn't read byte boolean or integer it reads binary

If you want to keep things simple, you might consider making a simple flasher flip flop circuit like below.

http://talkingelectronics.com/FreeProjects/5-Projects/Page16.html

winner10920:
I hate to break it to u

I don't think you're breaking anything to anyone here.

Lol just that it doesn't matter what you store it in, if it matches binary then it works, you could use an unsigned long that equals one and it'll work
you don't need to match the type to the return

You may not need to, but you really should :wink:

@zoomkat

Thank for the link.