Programming help

Hi
i am working on a arduino project with a group. I was responsible for the physical construction while one of my team mates was responsible for the coding aspect. My team mate has left the course and so i am left to code the box which is due in the next two weeks. While my supervisor has offered full marks on the assignment due to my contribution being complete, i would still like to complete the project.
Because of my low coding skill i was hoping for some help with programming my box.

Part 1
The design of the box is that until the button is pressed nothing happens.
Once the button is held down the program activates.

While the button is pressed the three green and 1 red led light up. If the button is released the green lights will turn off 1 by 1 each second untill only the red is left.

Part 2
Once the red led is left it should start blinking and the arduino should pulse the buzzer until the button is held down.
if the button is held down while the green lights are turning off it should interrupt the program and return to the held state.

with my basic skills i have programmed part 1 but cannot figure out how to get part 2 to work.
i believe i need to use interupts but do not know how to program them.
would someone be able to help?

green leds are 5,6,7
red led is 8

my code is pasted below.

void setup() {
  /* Button LED */
  pinMode(2, OUTPUT);
  /* Button */
  pinMode(3, INPUT_PULLUP);

  /* LEDs Descending */
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  /* Buzzer */
  pinMode(11, OUTPUT);
}

// the loop function runs over and over again forever
void loop() {
  for (;;) {
    if (digitalRead(3) == LOW) {
      delay(100);
      if (digitalRead(3) == LOW)
        break;
    }
  }

  digitalWrite(11, LOW);

  digitalWrite(2, LOW);

  digitalWrite(5, HIGH);
  digitalWrite(6, HIGH); 
  digitalWrite(7, HIGH);
  digitalWrite(8, HIGH);

  for (;;) {
    if (digitalRead(3) == HIGH) {
      delay(100);
      if (digitalRead(3) == HIGH)
        break;
    }
  }

  for (uint8_t i = 5; i < 8; i++) {
    delay(1000);
    digitalWrite(i, LOW);
  }

  digitalWrite(11, HIGH);
}

any help would be greatly appreciated

At any point in time your program will be in one of several states and the code for that state will need to be executed. That lends itself to using what has become known as a state machine.

At first it sounds scary but it need not be. I would start by working out what the states will be, what the code is doing when in each state and assigning a number to each state. For each state decide what conditions need to be set before entering the state, such as the start time for states needing timing and the conditions, such as changes of input and/or time passing, that will cause the state to end and the destination state when the current one ends. Note that there may be different destination states depending on the exit conditions of the current state.

Do all of this without writing any code. Then start with what I will call state 0 (doing nothing waiting for input. Personally I would use switch/case and give the states names but you can use if/else too.

Each time through loop() execute the code for the current state, ie test the input. When the input is detected turn on the LEDs and move to state 1 (red and green on). The exit condition will be release of the button which will cause a move to the next state.

It is important not to introduce delay()s into the code for the states so use millis() for timing to keep the program moving. You may find Using millis() for timing. A beginners guide, Several things at the same time and the BlinkWithoutDelay example in the IDE helpful.

Adventmatrix:
i believe i need to use interupts but do not know how to program them.

Absolutly not :wink:

You're problem is (as usual) that you use delay(). Have look at Blink without delay. The idea is that you leave the loop() running as fast as possible and only act when you need to.

The design of the box is that until the button is pressed nothing happens.

That can NOT possibly work. Part of what the Arduino program needs to do is read the state of the pin that the switch is connected to. So, the program must be running AT ALL TIMES.

What it does when the switch IS pressed, or BECOMES pressed, is for you to code.

Once the button is held down

Why does the switch (leave the buttons on your shirt; they will be useless sewn onto the Arduino) have to be held?

What, exactly, should happen when the switch becomes pressed? What, exactly, should happen when the switch becomes released? You are aware of the state change detection example, right?

Ok i've just tried to use machine states (i think).

now the button is lit up but nothing happens when i press or hold the button.
Once the button is pressed it should switch state to case 2 HELD.

here is the code

#define OFF 0
#define HELD 1
#define RELEASE 2
#define BUZZ 3
#define DELAY 1000
#define DELAY2 100

static unsigned int time;
static unsigned int button;
static unsigned int Delay;

uint8_t fsm_state = OFF;

void setup() {
  /* Button LED */
  pinMode(2, OUTPUT);
  /* Button */
  pinMode(3, INPUT_PULLUP);

  /* LEDs Descending */
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  /* Buzzer */
  pinMode(11, OUTPUT);

  time = 0;


}

// the loop function runs over and over again forever
 //state machine
void loop(){
  button = digitalRead(3);
  switch (fsm_state)
  {
    case OFF:  //Statements to execute every time LED_OFF is reached
      digitalWrite(2, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      break;
          default:
      break;
  }
  digitalRead(3);
   switch (fsm_state)
  {      
    case HELD:   //Statements to execute every time LED_ON is reached
    if(button == HIGH)
    digitalWrite(13, LOW);
      digitalWrite(2, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(8, HIGH);
      break;
    default:
      break;
  }
   switch (fsm_state)
  {
          case RELEASE:   //Statements to execute every time LED_ON is reached
    if(button == LOW)
      digitalWrite(2, HIGH);
      DELAY2;
      digitalWrite(5, LOW);
      DELAY;
      digitalWrite(6, LOW);
      DELAY;
      digitalWrite(7, LOW);
fsm_state = BUZZ;
      break;
    default:
      break;
  }
   switch (fsm_state)
  {
            case BUZZ:   //Statements to execute every time LED_ON is reached
      digitalWrite(11, HIGH);
      digitalWrite(8, HIGH);
      DELAY2;
      digitalWrite(11, LOW);
      digitalWrite(8, LOW);
      DELAY2;
  }

  }

arduino compiles with no complaint so the code is correctly written, but im figuring not correctly programmed.

PaulS:
That can NOT possibly work. Part of what the Arduino program needs to do is read the state of the pin that the switch is connected to. So, the program must be running AT ALL TIMES.

What it does when the switch IS pressed, or BECOMES pressed, is for you to code.
Why does the switch (leave the buttons on your shirt; they will be useless sewn onto the Arduino) have to be held?

What, exactly, should happen when the switch becomes pressed? What, exactly, should happen when the switch becomes released? You are aware of the state change detection example, right?

So the design is as follows:

state 0: Once the box is turned on the LED arcade button lights up, then does nothing untill the button is activated.

State 1: once the button activates the button led turns off and the three green and 1 red turn on, and stay static.

state 2: if the button is released the green leds turn off in turn after 1 second after each other.

state 3: if all the green leds are off and the red is on, the red led starts blinking and the buzzer starts going on and off at half second intervels.

if the button is held down at anytime i want it to default back to the state 1

I have not looked in detail but your use of switch/case is flawed

If should be

switch(state variable)
case X
code for case X
break

case Y
code for case Y
break

case Z
code for case Z
break
end of switch

  digitalRead(3);

If you don't care what digitalRead() returns, why bother calling it?

@LarryD's state machine and timer tutorial demonstrates the basics of what you need to implement your box. Not everything in the tutorial necessarily applies to your situation but, the essentials are there.

PaulS:

  digitalRead(3);

If you don't care what digitalRead() returns, why bother calling it?

Mate i have no coding knowledge so just stating that something won't work without giving me any indication of why it won't work doesn't help,
i need guidance not cryptic hints.

Adventmatrix:
Mate i have no coding knowledge so just stating that something won't work without giving me any indication of why it won't work doesn't help,
i need guidance not cryptic hints.

Mate, Instead of waiting for someone to spoonfeed you, you could go look at the reference page for digitalRead. You won't need to be a super-coder to understand what you've done wrong here. You call a function to read a pin but you don't save what you read to any variable. So it's done you no good.

I have gotten the state machines to work now and switch on button state.except for in case 'release'

i want it to read the button and if its low switch back to state 'held' if the button is unchanged carry on.
i just can't get it to do that, it just carries on regardless until it switches to 'buzz'

#define OFF 0
#define HELD 1
#define RELEASE 2
#define BUZZ 3
#define DELAY 1000
#define DELAY2 100

static unsigned int time;
static unsigned int button;
static unsigned int Delay;

uint8_t fsm_state = OFF;

void setup() {
  /* Button LED */
  pinMode(2, OUTPUT);
  /* Button */
  pinMode(3, INPUT_PULLUP);

  /* LEDs Descending */
  pinMode(5, OUTPUT);
  pinMode(6, OUTPUT);
  pinMode(7, OUTPUT);
  pinMode(8, OUTPUT);

  /* Buzzer */
  pinMode(11, OUTPUT);

  time = 0;


}

// the loop function runs over and over again forever
 //state machine
void loop(){
  button = digitalRead(3);
  switch (fsm_state)
  {
    case OFF:  //Statements to execute every time LED_OFF is reached
      digitalWrite(2, HIGH);
      digitalWrite(5, LOW);
      digitalWrite(6, LOW);
      digitalWrite(7, LOW);
      digitalWrite(8, LOW);
      digitalRead(button);
if (button == LOW)
      fsm_state = HELD;
break;

  }
      switch (fsm_state)
      {
    case HELD:   //Statements to execute every time LED_ON is reached
    if(button == LOW)
    {
    digitalWrite(13, LOW);
      digitalWrite(2, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(8, HIGH);
      delay (100);
      digitalRead(button);
     if (button == HIGH)
      fsm_state = RELEASE;
      break;
    }
          case RELEASE:   //Statements to execute every time LED_ON is reached
    if(button == HIGH)
      {
      digitalWrite(2, HIGH);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(8, HIGH);
      delay (1000);
      digitalRead(button);
      if (button == LOW)
      fsm_state = HELD;
      digitalWrite(5, LOW);
      delay (1000);
      digitalRead(button);
      if (button == LOW)
      fsm_state = HELD;
      digitalWrite(6, LOW);
      delay (1000);
      digitalRead(button);
      if (button == LOW)
      fsm_state = HELD;
      digitalWrite(7, LOW);
}
fsm_state = BUZZ;
      break;

            case BUZZ:   //Statements to execute every time LED_ON is reached
      digitalWrite(11, HIGH);
      digitalWrite(8, HIGH);
      delay(100);
      digitalWrite(11, LOW);
      digitalWrite(8, LOW);
      delay (100);
      digitalRead(button);
if (button == LOW)
      fsm_state = HELD;
  }

  }
if(button == LOW)
    {
    digitalWrite(13, LOW);
      digitalWrite(2, LOW);
      digitalWrite(5, HIGH);
      digitalWrite(6, HIGH);
      digitalWrite(7, HIGH);
      digitalWrite(8, HIGH);
      delay (100);
      digitalRead(button);
     if (button == HIGH)

Let's look at this case. In order to get inside the braces button has to be LOW. Next you do some digitalWrite commands, that's OK. Then you call digitalRead but don't save the value anywhere. Then you check to see if button is HIGH. You haven't done anything to assign it any new valule since you just tested and found that it was LOW. So the chances of it being HIGH at that point are exactly zero.

It might do you some good to stop trying to learn this by trial and error. Coding isn't something you can learn by the seat of your pants. You really do need to look at reference materials and examples to see how to use this stuff. I promise you'll never see a digitalRead in any example just hanging out by itself like that.

You have the same issue in many other places. You seem to think that

digitalread(3);

is going to magically place the value read into the variable button.

You obviously understood that how to make that work at the top of loop. I don't understand how it fell apart later. But if your line of code doesn't start out with

button =

and then something you aren't changing the value of button.

Delta_G:
You have the same issue in many other places. You seem to think that

digitalread(3);

is going to magically place the value read into the variable button.

You obviously understood that how to make that work at the top of loop. I don't understand how it fell apart later. But if your line of code doesn't start out with

button =

and then something you aren't changing the value of button.

So your telling me i don't need to use digitalread(button) before an if statement determined by the buttons position. i.e.

digitalread (button);
if (button == HIGH)

If you want the if statement to have an updated value from the button then you have to read the button again. BUT you have to save the value you read or you're just using the value that you read at the top of loop.

Listen, I guess you're a bit dense so I'll just spoon feed you this one. Trying to help you see it isn't getting anywhere.

If you want the variable button to have the value you read from the pin then you have to write:

button = digitalRead(3);

Just writing

digitalRead(3);

reads the pin and throws away the result.

Right now the only place you read the button is at the top of loop. But there are several places in your code where you seem to expect button to have a new value after you call

digitalRead(3);

But that DOES NOT put any value into button. Nope. The button variable will still have the same value it got when you actually did it right the one time at the top of loop.

Delta_G:
If you want the if statement to have an updated value from the button then you have to read the button again. BUT you have to save the value you read or you're just using the value that you read at the top of loop.

Listen, I guess you're a bit dense so I'll just spoon feed you this one. Trying to help you see it isn't getting anywhere.

If you want the variable button to have the value you read from the pin then you have to write:

button = digitalRead(3);

Just writing

digitalRead(3);

reads the pin and throws away the result.

Right now the only place you read the button is at the top of loop. But there are several places in your code where you seem to expect button to have a new value after you call

digitalRead(3);

But that DOES NOT put any value into button. Nope. The button variable will still have the same value it got when you actually did it right the one time at the top of loop.

If you bothered to read the whole topic instead of being an ASS by calling me dense you would know i have ZERO coding experience.

i am working on this from a couple of handout i got from someone who is doing an arduino coding course.

The reason i posted to this forum is so i could get help not so i can be insulted by an elitist ass.

The handouts i have say i need to put digitalread(*) before in IF statement.
I've been working from what is obviously an incorrect worksheet.

so if you can't be nice to someone who has obviously got no coding skills and is try to learn as best he can then get lost

I wasn't calling you dense because you didn't know how to use digitalRead. I was calling you dense because it was explained to you like three times already and you seemed to keep missing the point. In my reply before that one I laid it out pretty plain to you that any line you intend to change the value of button should start with

button =

If you aren't afraid to dive into the reference area of this site then you might make it. It's entirely up to you. If you have zero coding knowledge then get some. But if you want to base the whole thing on some handout you got then quit now. Don't just come here and get all butthurt because someone tried to explain something to you and you don't read so well and don't get it and then get called dense.

You've had plenty of posts so far pointing out that line as being wrong. Why haven't you tried to look at any other examples or reference materials to see how to use it right? That's why I called you dense. Please don't be confused as to thinking I was picking on you for not being a coder. I was picking on you for not being able to read the nice reply I wrote and gather anything from it or even to realize that there was more out there for you to read.

Check that the Flow Chart (given below) has contained every step of your program logic except the Interrupt Service Routine which you have not clearly provided. If yes, it can be helpful for you to code your program yourself giving attention to all the clues that have been given in the previous posts of this thread. While converting this Flow Chart into codes, please remember these points:
1. Keep the labels in the comment field after //
2. If you have problem to use while-do and do-while loops, you may use goto statement for the time being. Once the program works, replace all these goto statements by the appropriate loop structures.

3. You have not mentioned the DPin connection of the button; It can be taken as being connected with DPin-4/INTO with internal pull-up resistor enabled. So, the inactive level (when button is not closed) of the button is LH.
4. Use millis() function instead of delay(1000) function while blinking/checking button status; otherwise, you will most likely miss active states )button closure) of the button.
.

Few Example Codings for the Flow Chart

void setup()
{
     //;                                                   START:
     pinMode(8, OUTPUT);                        //L1:
     .............................. 
     pinMode(4, INPUT_PULLUP);             //button is connected with DPin-4 with internal pull-up
     ...............................

     bool n = digitalRead(4);                    //L2: //Read buttton status (1-bit and save in 1-bit variable n
     if (n != LOw)                                    //button is not closed
     {
         goto L2;
      }
      .....................................

      n = digitalRead(4);                   //L5: Read button status
      if (n != HIGH)
     {
         goto L5;                                      //button is not opened
     }
     ......................................
}


void loop()
{

}


ISR(INT0_vect)      //Interrupt Service Routine (ISR) due to interrupt caused by button close
{

}
  1. If you have problem to use while-do and do-while loops, you may use goto statement for the time being. Once the program works, replace all these goto statements by the appropriate loop structures.

This is incredibly bad advice.

This is incredibly bad advice.

I agree; but, seeing the programming level of the OP from OFF screen I could only conceive this unwanted advice. :slight_smile: