Simple avr program behaving weirdly "sometimes"

321 views Asked by At

I am new to AVR, but i have programmed PICs before, only this time i am doing everything in linux too so you'll guess that i am using avrdude...

My goal for this project is to change a bicolor LED's color depending on a certain state.

By default, the led is RED (if you make the connections right of course), then i want it to go to yellow (which is a quick change between green and red) while the user is holding the button down then on release, it will go to green, then the next time it will turn off.

So, to recap,

LED is red

While i hold the button down its gonna be yellow

When i release it will be green

While i hold the button down again its gonna be yellow

When i release it will be off

While i hold the button down again its gonna be yellow

When i release it will be red (and so on...)

In my actual code, everything works really well sometimes, but sometimes the led gets stuck at yellow and i have no clue why

Any ideas?

Code is on ideone : http://ideone.com/LI9gH

Thanks

2

There are 2 answers

3
Yann Vernier On BEST ANSWER

I'm guessing you're simply seeing the random generator missing the button changes about 1/3rd of the time, because the debouncing is slightly off. Consider the time spent in different states:

check button
wait 10ms
check button again
if button values differ, update state
if yellow
  shine red for 1ms
  shine green for 4ms then leave green on
otherwise
  set current color

That's your main loop. As you can see, it checks the button in two instants during about 15ms time; and it doesn't compare to the last value for which it updated state, only with the value 10ms prior. Release the button during the 5ms period of "yellow", and allumerAmbre will not reset until the next release that happens to fall in the 10ms period. Also, the yellow wound up 1/15 red, possibly not the mix you intended.

1
MRAB On

I don't know where the problem is, but I can suggest an alternative approach if that helps. :-)

Because you're cycling through a sequence of LED states, you could merely list them in an array and step along it (wrapping around when you reach the end), updating the LED each time, whenever the button state changes.

EDIT:

Here's an alternative:

colours = [red, yellow, green, yellow, off, yellow]
current button = released
state = 0
repeat
    check button
    if button != current button
        current button = button
        state += 1
        if state >= len(colours)
            state = 0
    // showing the colour sets the LED and includes a delay
    show colours[state]