Welcome to the Parallax Discussion Forums, sign-up to participate.

# Push buttons being read while other actions are being performed

Posts: 30
I'm stuck on a project. I have the streetlights acting as I need them to but I'm having a difficult time trying to get the pushbutton to be read while the lights are performing.

Here are the guidelines

only one pedestrian light will go green at a time and only when the corresponding pushbutton is pushed.When the button is pushed, traffic should stopin that direction only after the completion of that traffic cycle.

b.The corresponding pedestrian light will turn green and will stay on for 30 seconds. During the last 10 seconds, the green light will be flashing to indicate that time is almost up for crossing the street.

c.Each push button can be only pushed once.After that, the pedestrian light will return to red and normal operation will resume for two complete traffic cycles in that specific direction before the same button can cause the traffic light to change.You can ignore any push made during the completion of the two cycles.

d.If traffic is stopped in a particular direction during a red light and the pedestrian light is pushed, the corresponding pedestrian light should turn green immediately.

e.The left turn traffic should yield to pedestrians crossing the N-S street so there is no need to wait for the left turn signal to turn red.

Here is my code. I tried to simplify it by using subroutines for the change from north south to east west back to the all red.

"

counter VAR WORD

counter = 0
DO

GOSUB alllightsred
GOSUB eastandwest
counter = counter + 1
DEBUG ? counter
GOSUB northandsouth
counter = counter + 1
DEBUG ? counter
IF counter = 2 THEN
DO
IF IN3 =1 AND IN0 =1 THEN
DEBUG ? IN3
PAUSE 30000
ENDIF
LOOP WHILE counter >= 2
ENDIF
LOOP

'All Lights Red'
alllightsred:
HIGH 15
HIGH 14
HIGH 13
HIGH 12
HIGH 11
PAUSE 2000
RETURN
'East Turning Light goes Green and East Light goes green'
Eastandwest:
LOW 13
LOW 12
HIGH 9
HIGH 10
PAUSE 6500
'Turning light goes yellow
LOW 10
HIGH 5
PAUSE 3500

'Turning light goes Red and West goes Green
LOW 15
LOW 5
HIGH 7
HIGH 12
PAUSE 3500
'West and East light goes Yellow'

LOW 9
LOW 10
LOW 7
HIGH 2
HIGH 4
PAUSE 3500
'West and East go red
LOW 4
LOW 5
LOW 2
HIGH 15
HIGH 13
PAUSE 5000
RETURN

northandsouth:
'North and South go green'
HIGH 8
HIGH 6
LOW 11
LOW 14
PAUSE 6500
'North and South go Yellow'
LOW 8
LOW 6
HIGH 3
HIGH 1
PAUSE 3000

'North and south go red'
LOW 3
LOW 1
HIGH 11
HIGH 14
PAUSE 3000
RETURN

"

• Posts: 22,859
First of all ... we can only give so much help on school projects ... that said, we can certainly make suggestions. You probably need to break up the PAUSEs into a subroutine that also checks all the pushbuttons and sets variables for the pushbutton states maybe every 100ms like this:
```pushed  var bit(4)
location var nib
i            var nib
temp     var bit
button   var bit(4)
time      var word

CheckButtons:
'
' This subroutine checks to see if a button is pushed.  It won't accept another push until the
' button is released and the button push is remembered until it is acted upon by resetting
' button(i) to zero.  You set time to the desired cycle time in ms and this returns after that.
'
for i = 0 to 3
temp = INA.bit0(i) ' check IN0,IN1,IN2,IN3
if pushed(i) = 0 and temp = 1 then button(i) = 1 ' was up now down?
pushed(i) = temp ' save previous state for next check
next i
pause 100 ' clock 'tic is 100ms
time = time - 100
if time > 0 then goto CheckButtons ' if time not done, repeat
return
```
Typically, you'd do some action for a cycle calling CheckButtons for any pauses in the cycle like:

' turn on light
time = 500 ' wait 500ms
gosub CheckButtons
' turn off light
time = 500 ' wait 500ms
gosub CheckButtons
button(0) = 0 ' reset button state
' now go check other buttons for stuff to do
• Posts: 1,935
This is when you learn how to use highest common denominator, and time-slice your code for that.
Though you could only use gpio irq + timer irq and hardware pwm for this simple project,
but keeping it to a simple state-machine that runs on 1/4sec ticks is easier to understand.

• Posts: 30
This is the code I have now. All that I am missing is getting the pedestrian light to go from West to East to North and South if the PBNS as been pressed while the pedestrian light for "WE" is on. I got the code to read that pbns has been pressed while it is on. I just cant figure out why it wont execute the condition I have for the crosswalk to switch after the condition is met.

"counter VAR WORD
red VAR WORD
ns VAR WORD
we VAR WORD
pbns VAR WORD
pbwe VAR WORD

counter = 0
main:

DO

HIGH 0
LOW 8
GOSUB alllightsred
GOSUB crosswalk
GOSUB turninglight
GOSUB crosswalk
GOSUB turninglightgoesyellow
GOSUB crosswalk
GOSUB turnlightred
GOSUB crosswalk
GOSUB eastandwestgogreen
GOSUB crosswalk
GOSUB westandeastgoyellow
GOSUB crosswalk
GOSUB westandeastgored
counter = counter + 1
DEBUG ? counter
GOSUB crosswalk
GOSUB northandsouthgogreen
GOSUB crosswalk
GOSUB northandsouthgoyellow
GOSUB crosswalk
GOSUB northandsouthgored
counter = counter + 1
DEBUG ? counter
GOSUB crosswalk

LOOP

'All Lights Red'
alllightsred:
FOR red = 0 TO 1000

HIGH 15
HIGH 12
HIGH 6
HIGH 7
PAUSE 1
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF
NEXT
RETURN
'Turning Light goes Green AND East Light goes green'
turninglight:
FOR we = 0 TO 2500
LOW 7
LOW 6
HIGH 9
HIGH 4
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
'Turning light goes yellow
turninglightgoesyellow:
FOR we = 0 TO 1100
LOW 4
HIGH 5
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
Turnlightred:
FOR we = 0 TO 1000
LOW 5
HIGH 6
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
Eastandwestgogreen:
'Turning light goes Red and West goes Green
FOR we = 0 TO 2000
LOW 15
HIGH 13
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
westandeastgoyellow:
'West and East light goes Yellow'
FOR we = 0 TO 1100
LOW 9
LOW 13
HIGH 14

IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
'West and East go red
westandeastgored:
FOR we = 0 TO 1100
LOW 14
HIGH 15
HIGH 7

NEXT
RETURN
northandsouthgogreen:
'North and South go green'
FOR ns = 0 TO 2500
LOW 12
HIGH 10

IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN
'North and South go Yellow'
northandsouthgoyellow:
FOR ns = 0 TO 1100
LOW 10
HIGH 11
IF IN3 = 1 AND pbwe = 0 THEN
pbns = pbns + 1
pbwe = 0
DEBUG ? pbns
ELSEIF IN2 = 1 AND pbns = 0 THEN
pbwe = pbwe + 1
pbns = 0
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN

'North and south go red'
northandsouthgored:
FOR ns = 0 TO 1100
LOW 11
HIGH 12
IF IN3 = 1 THEN
pbns = pbns + 1
DEBUG ? pbns
ELSEIF IN2 = 1 THEN
pbwe = pbwe + 1
DEBUG ? pbwe
PAUSE 1
ENDIF

NEXT
RETURN

'check for pushbutton'
crosswalk:
IF counter >= 2 AND pbns >= 1 AND pbwe = 0 AND IN10 = 1 THEN
HIGH 8
LOW 0
PAUSE 20000
FOR counter = 0 TO 100
HIGH 8
LOW 0
PAUSE 50
LOW 8
LOW 0
PAUSE 50
NEXT
counter = 0
pbns = 0
pbwe = 0
RETURN
ELSEIF counter >= 2 AND pbwe >= 1 AND IN9 = 1 THEN
FOR counter = 0 TO 10000
HIGH 1
HIGH 5
LOW 4
IF IN3 = 1 THEN
pbns = pbns + 1
DEBUG ? pbns
ENDIF
DO UNTIL IN3 = 0
IF IN3 = 0 THEN
pbns = pbns + 0
ENDIF
LOOP
NEXT

FOR counter = 0 TO 100
HIGH 1
PAUSE 50
LOW 1
PAUSE 50
NEXT
LOW 1
counter = 0
pbns = 0
pbwe = 0
RETURN

ELSEIF pbns > = 1 AND IN10 = 1 THEN
DEBUG ? pbns
DEBUG ? Counter
HIGH 8
LOW 0
PAUSE 20000
FOR counter = 0 TO 100
HIGH 8
LOW 0
PAUSE 50
LOW 8
LOW 0
PAUSE 50
NEXT
HIGH 0
LOW 8
RETURN
ELSEIF pbns= 0 AND pbwe = 0 AND counter >= 2 THEN
pbns = 0
pbwe = 0
ENDIF
RETURN"

Mike Green wrote: »
First of all ... we can only give so much help on school projects ... that said, we can certainly make suggestions. You probably need to break up the PAUSEs into a subroutine that also checks all the pushbuttons and sets variables for the pushbutton states maybe every 100ms like this:
```pushed  var bit(4)
location var nib
i            var nib
temp     var bit
button   var bit(4)
time      var word

CheckButtons:
'
' This subroutine checks to see if a button is pushed.  It won't accept another push until the
' button is released and the button push is remembered until it is acted upon by resetting
' button(i) to zero.  You set time to the desired cycle time in ms and this returns after that.
'
for i = 0 to 3
temp = INA.bit0(i) ' check IN0,IN1,IN2,IN3
if pushed(i) = 0 and temp = 1 then button(i) = 1 ' was up now down?
pushed(i) = temp ' save previous state for next check
next i
pause 100 ' clock 'tic is 100ms
time = time - 100
if time > 0 then goto CheckButtons ' if time not done, repeat
return
```
Typically, you'd do some action for a cycle calling CheckButtons for any pauses in the cycle like:

' turn on light
time = 500 ' wait 500ms
gosub CheckButtons
' turn off light
time = 500 ' wait 500ms
gosub CheckButtons
button(0) = 0 ' reset button state
' now go check other buttons for stuff to do