Allow a button press to queue another function with use of a shiftregister

Hello Arduino community,
I have made a crossroad traffic light simulator with 5 stoplights 5 buttons for traffic control and a led with button and speaker for train warnings using the arduino uno and the shiftregister 74HC595 with the 74HC595 library. I have tried using the BlinkWithoutDelay example but cant get it to work with my functions on buttonpress. And the fact that I am using a library for the shiftregister control of LEDs it just doesnt seem to work without delay.
My crossroad works nicely from state0 while there are no functions running, the only thing I wish to do is allow my project to queue the functions from buttonpress like run changelight1() directly after changelight2() finishes because I pressed stoplightbutton 1 during changelight2().

picture of my project: http://i68.tinypic.com/23rmk2b.jpg
source shiftregister library: http://shiftregister.simsso.de/
Thanks in advance.

// Libraries
#include <ShiftRegister74HC595.h>
#include "pitches.h"
// constants
const int G1 = 13;
const int Y1 = 12;
const int R1 = 11;
const int G2 = 10;
const int Y2 = 9;
const int R2 = 8;
const int T = 7;
const int R5 = 5;
// code to initialize shiftregister
const int numberOfShiftRegisters = 1;
const int latchPin = 4;
const int clockPin = 3;
const int dataPin = 2;
ShiftRegister74HC595 sr (numberOfShiftRegisters,dataPin, clockPin, latchPin);
// Variables
int delayGreen = 3000;
int delayYellow = 750;
int delayRed = 1000;
int pushButton1 = A0;
int pushButton2 = A1;
int pushButton3 = A2;
int pushButton4 = A3;
int pushButton5 = A4;
int alarmButton = A5;
int buttonValue1 = 0;
int buttonValue2 = 0;
int buttonValue3 = 0;
int buttonValue4 = 0;
int buttonValue5 = 0;
int alarmValue =0;
// music
int melody[] = {
  NOTE_C4, NOTE_G3, NOTE_G3, NOTE_A3, NOTE_G3, 0, NOTE_B3, NOTE_C4
};
int dad[] ={
 NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_C4, NOTE_D4, NOTE_E4, NOTE_C4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_E4, NOTE_F4, NOTE_G4,
 NOTE_G4, NOTE_A5, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_C4, NOTE_G4, NOTE_A5, NOTE_G4, NOTE_F4, NOTE_E4, NOTE_C4,
 NOTE_C4, NOTE_G3, NOTE_C4, NOTE_C4, NOTE_G3, NOTE_C4};
int alarm[] = {
  NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5, NOTE_C5
};
int noteDurations[] = {
  4, 8, 8, 4, 4, 4, 4, 4
};
int alarmDurations[] = {
  2, 2, 2, 2, 2, 2, 2, 2
};
int dadDurations[] = {
 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 8, 8, 8, 8, 4, 4, 8, 8, 8, 8, 4, 4, 4, 4, 2, 4, 4, 2
  };
void setup() {
pinMode(G1,OUTPUT); 
pinMode(Y1,OUTPUT);
pinMode(R1,OUTPUT);
pinMode(G2,OUTPUT);
pinMode(Y2,OUTPUT);
pinMode(R2,OUTPUT);
pinMode(R5,OUTPUT);
pinMode(T,OUTPUT);
pinMode(pushButton1,INPUT);
pinMode(pushButton2,INPUT);
pinMode(pushButton3,INPUT);
pinMode(pushButton4,INPUT);
pinMode(pushButton5,INPUT);
pinMode(alarmButton,INPUT);
// set stoplight1 and 5 to red and 2-4 to green
digitalWrite(R1,HIGH);
digitalWrite(R5,HIGH);
digitalWrite(G2,HIGH);
sr.set(0,HIGH);
sr.set(3,HIGH);
// thanks for the example https://www.arduino.cc/en/Tutorial/toneMelody
for (int thisNote = 0; thisNote < 8; thisNote++) {

    // to calculate the note duration, take one second
    // divided by the note type.
    //e.g. quarter note = 1000 / 4, eighth note = 1000/8, etc.
    int noteDuration = 1000 / noteDurations[thisNote];
    tone(6, melody[thisNote], noteDuration);

    // to distinguish the notes, set a minimum time between them.
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    noTone(6);
  }
}

void loop() {
buttonValue1 = digitalRead(pushButton1);
buttonValue2 = digitalRead(pushButton2);
buttonValue3 = digitalRead(pushButton3);
buttonValue4 = digitalRead(pushButton4);
buttonValue5 = digitalRead(pushButton5);
alarmValue = digitalRead(alarmButton);

if (alarmValue == HIGH){
trainIncoming();
delay(1);
}
if (buttonValue1 == HIGH || buttonValue2 == HIGH){
changeLights1();
delay(1);
}
if (buttonValue3 == HIGH){
overloadPiano();
delay(1);
}
if (buttonValue4 == HIGH || buttonValue5 == HIGH){
changeLights3();
delay(1);
}

}
void changeLights1(){
// Y3, Y4 -- G3, G4 off
sr.set(0,LOW);
sr.set(3,LOW);
sr.set(1,HIGH);
sr.set(4,HIGH);
delay(delayYellow);
sr.set(1,LOW);
sr.set(4,LOW);
delay(delayYellow);
sr.set(1,HIGH);
sr.set(4,HIGH);
delay(delayYellow);
digitalWrite(Y2,LOW);
sr.set(1,LOW);
sr.set(4,LOW);
delay(delayYellow);
sr.set(1,HIGH);
sr.set(4,HIGH);;

// turn off yellow, then turn on red
sr.set(1,LOW);
sr.set(2,HIGH);
sr.set(4,LOW);
sr.set(5,HIGH);
digitalWrite(G1,HIGH);
digitalWrite(R1,LOW);
delay(delayGreen);

// turn off green, then blink yellow for for 2.5 seconds
digitalWrite(G1,LOW);
digitalWrite(Y1,HIGH);
delay(delayYellow);
digitalWrite(Y1,LOW);
delay(delayYellow);
digitalWrite(Y1,HIGH);
delay(delayYellow);
digitalWrite(Y1,LOW);
delay(delayYellow);
digitalWrite(Y1,HIGH);

// turn off yellow, then turn on red
digitalWrite(Y1,LOW);
digitalWrite(R1,HIGH);
sr.set(0,HIGH);
sr.set(3,HIGH);
sr.set(2,LOW);
sr.set(5,LOW);
}
void changeLights3(){
// red off, green for 3 seconds
digitalWrite(G2,LOW);
digitalWrite(Y2,HIGH);
sr.set(0,LOW);
sr.set(1,HIGH);
delay(delayYellow);
digitalWrite(Y2,LOW);
sr.set(1,LOW);
delay(delayYellow);
digitalWrite(Y2,HIGH);
sr.set(1,HIGH);
delay(delayYellow);
digitalWrite(Y2,LOW);
sr.set(1,LOW);
delay(delayYellow);
digitalWrite(Y2,HIGH);
sr.set(1,HIGH);

digitalWrite(Y2,LOW);
sr.set(1,LOW);
digitalWrite(R2,HIGH);
sr.set(2,HIGH);
sr.set(6,HIGH);
digitalWrite(R5,LOW);
delay(delayGreen);

// turn off green, then blink yellow for for 2.5 seconds
sr.set(6,LOW);
sr.set(7,HIGH);
delay(delayYellow);
sr.set(7,LOW);
delay(delayYellow);
sr.set(7,HIGH);
delay(delayYellow);
sr.set(7,LOW);
delay(delayYellow);
sr.set(7,HIGH);

// turn off yellow, then turn on red
digitalWrite(G2,HIGH);
digitalWrite(R2,LOW);
sr.set(0,HIGH);
sr.set(2,LOW);
sr.set(7,LOW);
digitalWrite(R5,HIGH);
}
// train incoming set all stoplights to red
void trainIncoming(){
sr.set(0,LOW);
sr.set(1,HIGH);
delay(delayYellow);
sr.set(1,LOW);
delay(delayYellow);
sr.set(1,HIGH);
delay(delayYellow);
sr.set(1,LOW);
delay(delayYellow);
sr.set(1,HIGH);

sr.set(1,LOW);
sr.set(2,HIGH);

for (int thatNote = 0; thatNote < 8; thatNote++) {
  
    int noteDuration = 1000 / alarmDurations[thatNote];
    tone(6, alarm[thatNote], noteDuration);
    digitalWrite(T,HIGH);
    int pauseBetweenNotes = noteDuration * 1.50;
    delay(pauseBetweenNotes);
    digitalWrite(T,LOW);
    noTone(6);
  }
sr.set(2,LOW);
sr.set(0,HIGH);
}
// Loop the train through leds and turn them all green at the end while dadMelody is playing
void overloadPiano(){
digitalWrite(G1,HIGH);
delay(100);
digitalWrite(Y1,HIGH);
delay(100);
digitalWrite(R1,HIGH);
delay(100);
for(int x = 0; x < 10; x++){ 
digitalWrite(G2,HIGH);
digitalWrite(G1,LOW);
delay(100);
digitalWrite(Y2,HIGH);
digitalWrite(Y1,LOW);
delay(100);
digitalWrite(R2,HIGH);
digitalWrite(R1,LOW);
delay(100);
sr.set(0,LOW);
digitalWrite(G2,LOW);
delay(100);
sr.set(1,HIGH);
digitalWrite(Y2,LOW);
delay(100);
sr.set(2,HIGH);
digitalWrite(R2,LOW);
delay(100);
sr.set(3,HIGH);
sr.set(0,LOW);
delay(100);
sr.set(4,HIGH);
sr.set(1,LOW);
delay(100);
sr.set(5,HIGH);
sr.set(2,LOW);
delay(100);
sr.set(6,HIGH);
sr.set(3,LOW);
delay(100);
sr.set(7,HIGH);
sr.set(4,LOW);
delay(100);
digitalWrite(R5,HIGH);
sr.set(5,LOW);
delay(100);
digitalWrite(G1, HIGH);
sr.set(6,LOW);
delay(100);
digitalWrite(Y1,HIGH);
sr.set(7,LOW);
delay(100);
digitalWrite(R1,HIGH);
digitalWrite(R5,LOW);
delay(100);
}
digitalWrite(G2,HIGH);
digitalWrite(Y1,LOW);
sr.set(0,HIGH);
digitalWrite(R1,LOW);
sr.set(3,HIGH);
sr.set(6,HIGH);
for (int dadNote = 0; dadNote < 32; dadNote++) {
  
    int noteDuration = 1000 / dadDurations[dadNote];
    tone(6, dad[dadNote], noteDuration);
    digitalWrite(T,HIGH);
    int pauseBetweenNotes = noteDuration * 1.30;
    delay(pauseBetweenNotes);
    digitalWrite(T,LOW);
    noTone(6);
  }
delay(200);
digitalWrite(R1,HIGH);
digitalWrite(G1,LOW);
sr.set(6,LOW);
digitalWrite(R5,HIGH);


}

in the attachment there is the legenda

CrossroadArduino2.txt (1.41 KB)

The tone function is a blocking function the same as delay. When you are using either then your Arduino is in effect doing nothing.

What you have tried to do is too much at once without testing.

I have tried using the BlinkWithoutDelay example but cant get it to work with my functions on buttonpress. And the fact that I am using a library for the shiftregister control of LEDs it just doesnt seem to work without delay.

That is simply not true, there is nothing stopping you using that technique with shift registers. I suspect that you did not understand what you were doing. It would have been a much more interesting post if you showed your failed attempt at using LEDs with shift registers in the blink without delay technique. Just a simple sketch to make sure you have the fundamentals correct is all that is needed. Don't pile on the complications at first, build things up from smaller working code.

Hi Mike,

Thank you for your reply, I had a busy weekend.
As for the blinkwithoutdelay example I was busy experimenting and I was wondering why the following for loop doesnt work?

for (int x = 0; x < 3; x++){
if (currentMillis - previousMillisG1 >= delayYellow){
previousMillisG1 = currentMillis;

  if (ledStateY1 == LOW) {
    ledStateY1 = HIGH;
    } else {
      ledStateY1 = LOW;
    }
 digitalWrite(Y1, ledStateY1);
}
}

The same issue I have with writing the following function:
Why doesnt the statemachine go to the if?

void changeLights1(){
sr.set(0,LOW);
sr.set(3,LOW);
sr.set(1,HIGH);
sr.set(4,HIGH);
if (currentMillis - previousMillisY1 >= delayYellow){
sr.set(1,LOW);
sr.set(4,LOW);
previousMillisY1 = currentMillis;  //750
  if (currentMillis - previousMillisY1 >= delayYellow){
  sr.set(1,HIGH);
  sr.set(4,HIGH);
  previousMillisY1 = currentMillis;  //1500
    if (currentMillis - previousMillisY1 >= delayYellow){
    sr.set(1,LOW);
    sr.set(4,LOW);
    previousMillisY1 = currentMillis;  //2250
      if (currentMillis - previousMillisY1 >= delayYellow){
      sr.set(2,HIGH);
      sr.set(5,HIGH);
      digitalWrite(G1,HIGH);
      digitalWrite(R1,LOW);
}
}
}
}
}

I was wondering why the following for loop doesnt work?

It would help to include all the code so we can see the definition type of the variables and what values they are set at before entering the loop.

Well it obviously does work, but it is not doing what you expected. What are you expecting?
Why is there a for loop? It will iterate much faster than the micro second timer and never do the stuff in the middle. Or at best it will do it occasionally once.

Same with the second example. It looks like if it misses the first if then the function is over. Without seeing the rest of the code or knowing what to expect it is hard to be more specific.

The common factor then is you are not doing it correctly.

Sorry the rest was the same with some added. I was trying to convert a standard delay function to the blinkwithoutdelay kind.

// Libraries
#include <ShiftRegister74HC595.h>
// constants
const int G1 = 13;
const int Y1 = 12;
const int R1 = 11;
const int G2 = 10;
const int Y2 = 9;
const int R2 = 8;
const int T = 7;
const int R5 = 5;
// code to initialize shiftregister
const int numberOfShiftRegisters = 1;
const int latchPin = 4;
const int clockPin = 3;
const int dataPin = 2;
ShiftRegister74HC595 sr (numberOfShiftRegisters,dataPin, clockPin, latchPin);
// Variables
const long delayGreen = 3000;
const long delayYellow = 750;
const long delayRed = 1000;
int pushButton1 = A0;
int pushButton2 = A1;
int pushButton3 = A2;
int pushButton4 = A3;
int pushButton5 = A4;
int alarmButton = A5;
int buttonValue1 = 0;
int buttonValue2 = 0;
int buttonValue3 = 0;
int buttonValue4 = 0;
int buttonValue5 = 0;
int alarmValue =0;
int ledStateY1 = LOW;

unsigned long currentMillis = millis();
unsigned long previousMillisY1 = 0;
unsigned long previousMillisG1 = 0;


void setup() {
pinMode(G1,OUTPUT); 
pinMode(Y1,OUTPUT);
pinMode(R1,OUTPUT);
pinMode(G2,OUTPUT);
pinMode(Y2,OUTPUT);
pinMode(R2,OUTPUT);
pinMode(R5,OUTPUT);
pinMode(T,OUTPUT);
pinMode(pushButton1,INPUT);
pinMode(pushButton2,INPUT);
pinMode(pushButton3,INPUT);
pinMode(pushButton4,INPUT);
pinMode(pushButton5,INPUT);
pinMode(alarmButton,INPUT);
digitalWrite(R1,HIGH);
digitalWrite(R5,HIGH);
digitalWrite(G2,HIGH);
sr.set(0,HIGH);
sr.set(3,HIGH);

}


void loop() {

unsigned long currentMillis = millis();
buttonValue1 = digitalRead(pushButton1);
buttonValue2 = digitalRead(pushButton2);
buttonValue3 = digitalRead(pushButton3);
buttonValue4 = digitalRead(pushButton4);
buttonValue5 = digitalRead(pushButton5);
alarmValue = digitalRead(alarmButton);
changeLights1();
for (int x = 0; x < 3; x++){
if (currentMillis - previousMillisG1 >= delayYellow){
previousMillisG1 = currentMillis;

  if (ledStateY1 == LOW) {
    ledStateY1 = HIGH;
    } else {
      ledStateY1 = LOW;
    }
 digitalWrite(Y1, ledStateY1);
}
}
}
void changeLights1(){
sr.set(0,LOW);
sr.set(3,LOW);
sr.set(1,HIGH);
sr.set(4,HIGH);
if (currentMillis - previousMillisY1 >= delayYellow){
sr.set(1,LOW);
sr.set(4,LOW);
previousMillisY1 = currentMillis;  //750
  if (currentMillis - previousMillisY1 >= delayYellow){
  sr.set(1,HIGH);
  sr.set(4,HIGH);
  previousMillisY1 = currentMillis;  //1500
    if (currentMillis - previousMillisY1 >= delayYellow){
    sr.set(1,LOW);
    sr.set(4,LOW);
    previousMillisY1 = currentMillis;  //2250
      if (currentMillis - previousMillisY1 >= delayYellow){
      sr.set(2,HIGH);
      sr.set(5,HIGH);
      digitalWrite(G1,HIGH);
      digitalWrite(R1,LOW);
      previousMillisG1 = currentMillis;  //3000
        if (currentMillis - previousMillisG1 >= delayGreen){
          digitalWrite(G1,LOW);
          digitalWrite(Y1,HIGH);
          previousMillisY1 = currentMillis; //6000
           if (currentMillis - previousMillisY1 >= delayYellow){
           digitalWrite(Y1,LOW);
           previousMillisY1 = currentMillis; //6750
            if (currentMillis - previousMillisY1 >= delayYellow){
            digitalWrite(Y1,HIGH);
            previousMillisY1 = currentMillis;
             if (currentMillis - previousMillisY1 >= delayYellow){
             digitalWrite(Y1,LOW);
             previousMillisY1 = currentMillis;
              if (currentMillis - previousMillisY1 >= delayYellow){
              digitalWrite(R1,HIGH);
              sr.set(0,HIGH);
              sr.set(3,HIGH);
              sr.set(2,LOW);
              sr.set(5,LOW);
            }
           }
          }
        }
      }
    }
   } 
  }
 }
}

Like I said you are not doing it right. Have you addressed that for loop yet?

What does it do and what do you want it to do?

The change lights function is so wrong. Work through it you will see that you change previousMillis and then straight after see if is greater than a delay. It is never going to be. If it fails any if statement then the function is over, you don't want to do that. There are areas of code that can never be executed.

The state machine normally has a bunch of tests to see what function to call and then it calls it. You seem to have this all mixed up. The problem is that you should start off simple and then only when it works expand things.

I have tried to search for examples of for loops in combination with millis() timer. But sadly I couldnt find any examples. As you explained the for loop in your last post I understand it loops way faster than the millis() in the the middle and wont do its work. The idea behind the loop was that I only wanted to see the led blink 3 times before it stops (I tried putting the code in setup but it didnt work).

As for the function I thought it should work simply as the state machine will wait for the millis() to pass before allowing the if statement to do its work, as shown in the blinkwithout delay example. I currently have like no clue on how to queue those blinkswithoutdelay examples and work through the function once on a buttonpress.

This code will do the initial blink. But the problem is that even written like this it is blocking so you have no advantage in using millis.

int x = 0;
while(x<3){
 if (currentMillis - previousMillisG1 >= delayYellow){
    previousMillisG1 = currentMillis;
    x++;
    if (ledStateY1 == LOW) {
         ledStateY1 = HIGH;
       } 
     else {
         ledStateY1 = LOW;
      }
 digitalWrite(Y1, ledStateY1);
  }
}

As for the function I thought it should work simply as the state machine will wait for the millis() to pass before allowing the if statement to do its work, as shown in the blinkwithout delay example.

It will not because you are not reading what that code actually does.

OK last time of asking because I have asked you twice before.
What do you want that function to do.

I can see what it does and basically it does not do anything, but until I know what you want it to do I can’t help. What I can tell you is that the code is nothing like the blink without delay example in structure.

Have a read of this:- State Machine

If you want to see a project that uses an extensive state machine look at this one:-
http://www.thebox.myzen.co.uk/Hardware/Dice_Game.html
The code is downloadable from a link in the text.

HappyPenguin:
The idea behind the loop was that I only wanted to see the led blink 3 times before it stops

This seems to be the only description of the output required.

So let's try to go back to basics on this one. You want it to blink 3 times. So there must be some kind of counter that counts the number of blinks. To make it blink there must be a defined interval that the LED is on and another for when it is off. To make 3 blinks there must be 3 on and 3 off, so you need to count to 6 as a minimum.

So why is a for() loop the wrong structure? Well, you need the main loop to run continuously, checking the time to see if it's time to do something different. When it is time, then it changes the state of the output and advances the counter. There's no requirement to use a for() to do that. A for() loop might be required to go through a whole bunch of outputs and change them all 'simultaneously' but it won't be useful for the main timing feature.

Can you try to write your main loop() function so that it has a counter that counts up to 6? Depending on the value of the counter, it will do different things such as turning the light on or off. When it gets to 6, there's no more actions to do, so it just stays at 6 'forever'.

Then that can be expanded. When it's at 6, it could start looking to see if a button is pressed and reset the state back to 0.

What I want the function to do is change the led from the stoplight with intervals. For example the led is red -> button press -> red light goes out green light goes on (wait 3 secs)-> green light goes out yellow light blinks 3 times with (0.75 secs in between)-> yellow light goes out and red light stays on.
And while this is happening I want the arduino to register any other button presses and queue the other function for another stoplight to happen right after the first one is done.

Like in the realworld crossroad with multiple stoplights and sensors underground. On my first post the program is using delay and the steps are linear the rest of the stoplights follow the situation. However I have the problem that the arduino isnt registering any buttonpresses while in the function with delay. So the buttonpresses stay unresponsive. I want the 2nd and after buttons to respond and run the function from the buttonpress after the first function from the button press is done in a chronological order.

Sorry if my english is poor or any unclear matters I am dutch/chinese.

You need to break that sequence into a state diagram. Each state, meaning what light is on is drawn on a diagram and you put a circle round it. Then you draw lines from one state to the next, these lines represent your transitions and you label them with the condition that causes the transition between states. Transitions such as "button pushed", time elapsed in previous state exceeds xx seconds and so on.

Then you number these states and write code for what happens when each state is entered.

The first thing in your loop function will be a check of those things you want to do in the background, like look to see if there have been any push buttons have been pressed. If they have you set a boolean flag so that you know a press has occurred but you don't do anything about it yet.

Now get your program will check what state you are in and change state when appropriate.
When the end state makes a transition back to the start state you check your boolean flags to see what state to go to. If a flag has been set remember to clear it once you have taken the action that it indicates.

Now start by drawing that diagram and posting it so we all know what you are trying to implement. It is no good saying:-

Like in the realworld crossroad with multiple stoplights and sensors underground.

Because the way this works in the real world depends entirely on what country you are in, so what is obvious to you is not in other countries.

If you separate your code into sections for input, output and processing, it will get smaller and easier to work with.

Inside of loop(), make your code like parts of a virtual machine. They can interact but each part gets driven by loop() and events/data. Your loop() should run 10's of 1000's of times per second and only occasionally does something like a button press happen to cause a series of changes that ends up changing a light now and then. From button input to first change should take less than a millisecond unless you want it to wait for something.

There should be an array of light states. A signal with red,amber,green light only needs 0, 1,or 2 for which light should be on. HINT: don't use ints, use bytes for values that fit in 0 to 255.

There should be a section or function that changes lights to correspond to changed array values. Make it only check/change One Signal in any one pass through loop(). Do NOT for-loop to check all the signals, just do one at a time. There's no need to check them all at once. Next one will always be Very Soon.

There should be one section or function that only watches the button, debounces if needed, and returns a status that includes completed state-changes. It should run once per pass through loop().

There should be one section or function that reads button status and on just-pressed, does what it should. Huh? you say? How does it know? Because it keeps a State value to know and changes that according to what is done. The switch-case structure will make this easy to break into pieces.
This part will change the light states array as needed, not the pins.

There should be one section or function to run the timed events of lights. State machine and timers, be sure!
This part will change the light states array as needed, not the pins.

Each section/function runs once per pass through loop(), the driving wheel. None should take more than a few 10's of microseconds. If the job of the section/function takes longer then put in a State value and switch-case to let it do each step in a subsequent execution.
It is important that no part runs too long because that will block the rest from updating/checking/doing until it is done hogging cpu cycles.

Every section/function can be written and debugged in a small sketch then transferred into the project sketch where of course interactions may need a final debugging but you get that no matter how you code.

First I have made a diagram of the steps that needs to be followed for the program.
https://drive.google.com/file/d/0B1lFUYbHC3O7YXNWZ2VnU1kzZ0U/view?usp=sharing

And the layout of the crossroad.
https://drive.google.com/file/d/0B1lFUYbHC3O7Ukh2ZTc1UU1lOWs/view?usp=sharing

I do understand that I have to break up the program in segments and small sketches but I have no clue how to code it without examples.

Is this a school project?

How to help may change but help you get anyway.

First is planning, where the parts are decided and then details filled in.
I have given you an outline using the I - P - O approach.

IPO -- all parts are either Input, Output, or Process. They share data while each code stands and runs by itself.

One Input part for every sensor, button or other input like Serial. I2C and SPI and other inputs get parts as well so no matter what else, the virtual machine is always watching inputs and taking in data.

Serial input, even most buttons take time to finish gathering input. To the Arduino loop(), often 1000's of passes may go by waiting for a contact button to finish sparking as the contacts close that last 0,1mm or less. When you realize that your code can see that, what happens in maybe 2 milliseconds at such detail as if it is slow motion it is okay to get excited and imagine -- that is a sign that you have begun to believe and maybe write in things to let you check just how many times your sketch DOES loop().

Think about the Input sections needing to be run over and over mostly waiting for a thing to happen or an interval to get done and then the crank turns a bit, wait, turn, wait, turn until the data is finished be it a button press or full text arrived so the next section can use it.

Input sections serve Input hardware and incoming data, take it from the actual and turn it into abstract values that are simpler for deciding what to do code (Process) to use. You will see.

I will give you a button library if you want. It is 2 files you put in the sketch folder and include in the sketch. You won't have to code those details. Or you can use another if you want, cheap keypads have libraries that integrate at higher level but I can't say how fast they are (only makes a difference to other code parts) or how much bigger except Much.

Output sections serve Output hardware like leds and Serial messages out.

One exception is that for debugging, any part may have lines to print and show which branch of logic the code actually took and what values key variables (like State) hold. That helps to trace what happens and makes it possible to spot some kinds of bugs to fix.

Process sections are to read data set by Input sections and make data to drive the Output sections.

We'll get you through this. Once you see and learn, it will be a major tool in your coding bag of tricks.

Truthfully, I find it harder to explain fully than to write but I have long experience with it.

Here is an example that uses the library to handle 4 buttons and reports the status of each when used.

I use 4 jumper wires for buttons. To “press” one, I ground it. The pin is moded safe to ground.
I touch the end to the grounded on-board USB port box. Only thing to watch out for is make sure the board doesn’t rock under the pin (I have to hold the board steady, a real button would be nicer!) and make several contacts and breaks in an eye blink. For testing, it suffices me, they are worst-case tests.

If you want, I will add blinking the onboard led (pin 13) and make each button control that.
It might make a nice way to show how to write a task in a small sketch and import it to the project.
But first, understand this example.

There are uses of C here that you won’t know but they are optimizations and shortcuts. Please ask if they get in your way to seeing the overall principle. Each part is explainable.

The example sketch that only handles and reports on buttons:

/* buttonarrayclass example -- by GoForSmoke 2015 for public domain use
   revised with better library Oct 2106

  This uses 2 buttons or switches or jumpers for pins 2 & 3 to GND.
  Depending on switch, debounce value may need tuning.

  Button class object output is a state value for the main sketch code.
   // bit 0 = current, bit 1 = previous, bit 2 = bounce
  0, button currently still pressed. bits 000; same current and previous
  1, button has just been released. bits 100; different current and previous
  2, button has just been pressed.  bits 010; different the other way
  3, button currently still released. bits 110; same current and previous
  4 or more means the button is being debounced but not finished.
*/

#include "Arduino.h"
#include "button.h" // check for newest

// these variables are here to ward off the WinXP bug!
// if you're not running Windoze XP you won't need them
// but in any case, the compiler will optimize them away.
int a, b, c;
byte d, e, f;

const byte howManyButtons = 4;
byte buttonIdx;
byte buttonPin[ howManyButtons ] = { 4,5,6,7 };
button user[ howManyButtons ]; // button array

const byte ledpin = 13;

void setup()
{
  Serial.begin( 250000 );
  Serial.println( F( "\n  Startup\n" ));

  pinMode( ledpin, OUTPUT ); // default is INPUT LOW, now is OUTPUT LOW
  
  for ( buttonIdx = 0; buttonIdx < howManyButtons; buttonIdx++ )
  {
    user[ buttonIdx ].setButton( buttonPin[ buttonIdx ], 5 ); // buttons on pins 4,5,6,7
  }
  buttonIdx = 0;
}

void loop()
{
  static byte buttonRead; // allocated once, used often

  buttonRead = user[ buttonIdx ].runButton(); // turns the crank once, make sure it runs often!

  if ( buttonRead == 2 ) // just pressed
  {
    digitalWrite( ledpin, HIGH );
    Serial.print( F( "button " ));
    Serial.print( buttonIdx );
    Serial.print( F( " pressed millis() == " ));
    Serial.println( millis());
  }
  else if ( buttonRead == 1 ) // just released
  {
    digitalWrite( ledpin, LOW );
    Serial.print( F( "button " ));
    Serial.print( buttonIdx );
    Serial.print( F( " released millis() == " ));
    Serial.println( millis());
    Serial.println( );
  }
  
  if ( ++buttonIdx >= howManyButtons ) buttonIdx = 0; // adds 1 then tests limit
}

The library header file, button.h. You don’t need to know what’s in this to use it.

/*
  button.h for public domain use by GoForSmoke May 29 2015
  Revised Sept 2016  
  To use:
  make a buttonclass object in your sketch
  run that object every time through loop(), it is quickly done
  when you want to know the status of the button, you read the object
  it returns state;  bit 0 = current, bit 1 = previous, bit 2 = bounce
*/

// button library, Sept 25th, 2016 by GoForSmoke

#ifndef button_h
#define button_h

#include "Arduino.h"

#define CURRENT_1 1
#define PREVIOUS_2 2
#define BOUNCE_4 4

typedef class button
{
private:
  byte arduPin;
  byte buttonState; // bit 0 = current, bit 1 = previous, bit 2 = bounce
  byte startMs;
  byte debounceMs; 

public:
  button(); // default constructor
  void setButton( byte, byte ); // pin, debounce millis
  button( byte, byte ); // pin, debounce millis
  void setUpButton( void );
  byte runButton( void ); // returns buttonState as below
  // buttonState: bit 0 = current, bit 1 = previous, bit 2 = bounce
  byte buttonRead();  // returns buttonState as above
};

#endif

The library code file, button.cpp. You don’t need to know what’s in this to use it.

// button library, Sept 25th, 2016 by GoForSmoke

#include "Arduino.h"
#include "button.h"

button::button() // default constructor for arrays, needs the full setup
{
  buttonState = CURRENT_1;
}

button::button( byte ap, byte dbm )
{
  arduPin = ap;
  debounceMs = dbm;
  buttonState = CURRENT_1;
};

void button::setButton( byte ap, byte dbm ) // pin, debounce millis
{
  arduPin = ap;
  debounceMs = dbm;
  pinMode( arduPin, INPUT_PULLUP );
};


void button::setUpButton( void )
{
  pinMode( arduPin, INPUT_PULLUP );
};

byte button::buttonRead()
{
  return buttonState;
};


byte button::runButton( void )
{
//  static byte msNow;

  buttonState &= BOUNCE_4 | CURRENT_1; // clears previous state bit
  buttonState |= ( buttonState & CURRENT_1 ) << 1; // copy current state to previous
  buttonState &= BOUNCE_4 | PREVIOUS_2; // clears current state bit
  buttonState += digitalRead( arduPin ); // current state loaded into bit 0

//  msNow = (byte) millis(); // gets the low byte of millis

  if ( buttonState & 3 == CURRENT_1 || buttonState & 3 == PREVIOUS_2 )  // state change detected
  {
    buttonState ^= BOUNCE_4;      // toggles debounce bit
    // on 1st and odd # changes since last stable state, debounce is on
    // on bounces back to original state, debounce is off 
    if ( buttonState & BOUNCE_4 )
    {
//      startMs = msNow;    // starts/restarts the bounce clock on any change.
      startMs = (byte) millis();    // starts/restarts the bounce clock on any change.
    }
  }
  else if ( buttonState & BOUNCE_4 ) // then wait to clear debounce bit
  {
//    if ( msNow - startMs >= debounceMs ) // then stable button state achieved
    if ( (byte)((byte)millis()) - startMs >= debounceMs ) // then stable button state achieved
    {
      //   understand that stable state means no change for debounceMs. When time
      //   is over the state bits are manipulated to show a state change.
      buttonState &= CURRENT_1; // clear all but the current state bit
      if ( buttonState == 0 )  buttonState = PREVIOUS_2;  // HIGH->LOW
      else                     buttonState = CURRENT_1;  // LOW->HIGH
      //   buttonState now appears as a debounced state change in bits 0 and 1
    }
  }

  return buttonState;
};

To use these, start a new project in the IDE and paste the main example code into it then SaveAs and give it a name.

On the far right you see a magnifier icon and under that a down-pointing caret. Click the caret to get the Tab menu and click New Tab. You will be asked for a name, give it button.h and the tab will open up blank. Paste the button.h code from this post in and then save the file with IDE File->Save.

Do that again for button.cpp. Be sure to save.

Now all 3 files should be in your sketch folder, run a compile to test it. Any problems, get back to me!

First I have made a diagram of the steps that needs to be followed for the program.

But it is not a state diagram is it? Also the resolution is so low so that you can't read the words.

And the layout of the crossroad.

Well you really could have fooled me, in fact you did. I have no idea what that represents.

but I have no clue how to code it without examples.

Come off it I have given you examples in reply #7.

First things first this is a self build project and indeed for school and also the first time I used a arduino.
So somethings that should be obvious to others might be new to me.

Mike:
In the attachment is the diagram I hope its clear this time.
For what the layout represents each of the Leds (Green/Yellow/Red)+ button represents a stoplight with sensor and the arrow is the way a car can travel on the crossroad. the lines on the left represent the a train road. I will try out the example in post 7 now.

GoForSmoke:
I tried compiling and it gave me some warning “sketch¥button.h:39:1: warning: ‘typedef’ was ignored in this declaration };” I wired the 4 buttons to 4,5,6,7 and it have the arduino plugged into my pc however when I open the serialmonitor under tools its not giving any response on buttonpresses.

As I said in the last reply :- "But it is not a state diagram is it?"

It is a flow diagram. Read what a state diagram is:-

HappyPenguin:
GoForSmoke:
I tried compiling and it gave me some warning "sketch¥button.h:39:1: warning: 'typedef' was ignored in this declaration };" I wired the 4 buttons to 4,5,6,7 and it have the arduino plugged into my pc however when I open the serialmonitor under tools its not giving any response on buttonpresses.

Do you have the buttons wired to ground or 5V with resistors?

The buttons need to ground the pins, why I can use jumpers for buttons is I can ground them.

I am using IDE 1.6.9, same warnings but if I don't write it like I did the 8 bit timers don't work right.

Additional info:

AVR pins can be set as INPUT, INPUT_PULLUP, and OUTPUT.
INPUT_PULLUP feeds the pin 5V through 20K to 50K ohms. That's enough to keep it HIGH until it gets grounded which takes the pin below 1.1V to switch the pin state to LOW. To read HIGH again the voltage must be raised past 3V on a 5V system. INPUT_PULLUP weakly tries to keep the pin over 3V, it can't compete with 0V ground. Weakly tries is good because not enough current is sourced by the pin to hurt the chip or burn most anything up. The 5V pullup keeps the wire electrical potential/pressure up, it's not affected by weak field effects. Serial port wires use HIGH for 0 and LOW for 1 to take advantage of that. If you put a wire on a pin moded INPUT and leave it dangle, changing electric fields will cause the read to vary, or generally go HIGH and stay there.

I use pin mode INPUT_PULLUP to not have to wire up a resistor per pin by using the strong ones in the chip and getting a ground-safe, low-current switch.

Mike:
My bad I confused the flowdiagram with the statediagram. This one should be correct. For the ease of use I think I will skip the blinking of the yellow led and just leave it on in a state. I might have missed a couple of things, so thanks in advance for pointing them out if you find them.

GoforSmoke:
I wired all the buttons to 5v and resistors. Does it make a difference between being able to or unable to read the output of serialwrite? At the moment I am using IDE 1.6.12.