Here we use input output to simulate traffic lights using three leds of appropriate colour. The leds are connected to pins A0(RED), A1(AMBER) and A2(GREEN)
Step 1: Wire the device to the three leds
Step 2: Cut and past the following into the editor:
// #include "http://www.byvac.com//mBlib/flb/Library/2016/lib_io.bas"
// The leds are connected to port A
pins 1 to 3
constant RED
{PORTA(PORT),0}
constant AMBER
{PORTA(PORT),1}
constant GREEN
{PORTA(PORT),2}
// set the pins to be output
function init()
io_pinRole(*RED(),OUT,WOFF)
io_pinRole(*AMBER(),OUT,WOFF)
io_pinRole(*GREEN(),OUT,WOFF)
endf
The first thing to notice is the // #include at the top of the program, this is a library file which makes input output easier. The 'include' will direct the IDE to place the contents of this file into flash and so will be there semi-permanently.
Lines 4 to 6 relate the hardware to a meaningful name. The syntax may be a little strange but on RED you can see PORTA and 0 making it reasonably obvious. The only function so far is init() which will set the lines to output.
Step 3: Send the text over to the device using the |A
IMPORTANT wait until it is completed, this will take a little longer the first time as the library is being loaded into flash. Subsequent loads will detect the presence of the library and will not load it again. Note the numbers at the top of the terminal.
Fig 2 Counter indicates loading progress
Step 4: type init()
Step 5: type io_pinSet(*RED(),1) (note the * before the RED())
This will illuminate the RED led if not illuminated already, if not check the wiring, do the same for the AMBER and GREEN, io_pinSet(*RED(),0) will switch it off.
See how the syntax is updated, this actually refers to the syntax colouring used in the editor. To see the effect of this press the reset highlight button, see fig. 4
There are just 4 states that a set of traffic lights can be in that is:
We can model this is a function.
Step 6: Add the text below to the editor under the init() function, don't forget the blank line at the end:
function light_state(n)
select(n)
case(1)
io_pinSet(*RED(),1)
io_pinSet(*AMBER(),0)
io_pinSet(*GREEN(),0)
case(2)
io_pinSet(*RED(),1)
io_pinSet(*AMBER(),1)
io_pinSet(*GREEN(),0)
case(3)
io_pinSet(*RED(),0)
io_pinSet(*AMBER(),0)
io_pinSet(*GREEN(),1)
case(4)
io_pinSet(*RED(),0)
io_pinSet(*AMBER(),1)
io_pinSet(*GREEN(),0)
endselect
endf
Step 7: Send to the device using |A
Step 8: type:
This will test all of the states
There are a few options we could use here, lets say we want the following:
(1) RED: 15 seconds
(2) RA:
2 seconds
(3) GREEN 15 seconds
(4) AMB
4 seconds
Step 8: Copy and paste text below into the editor below the last function
function method1()
init()
print "Running\r\n"
while comkey?(2) = 0
light_state(1) // red for 15 seconds
wait(15000) // 1000 = 1 second
light_state(2) // red and amber for 2
wait(2000)
light_state(3) //
green for 15 seconds
wait(15000)
light_state(4) //
amber 10 seconds
wait(10000)
wend
endf
The above uses simple a simple wait to go onto the next state. The 'comkey?(2)' is reading the input from UART2 to which the terminal is connected, when a key is received from the terminal comkey?(2) will NOT be zero anymore and so the loop will finish. NOTE that is is only read at the start of the sequence so pressing a key at the terminal will only stop the loop when the sequence has fished, this could take up to 42 seconds given the above timings.
The big disadvantage with this method is that the device cant do anything else as the wait() function will tie the device up, known as a blocking function. If the device was needed to do other things then another method is needed.
Built into ByPic is a task scheduling system that is very useful for handing of a job so that we can get on with something else. A task will run a function on a timed interval which is more or less what is needed. We could set up a task for each light however if the timing drifts a bit off then the lights will get out of sequence so we create a function called traffic_ir.
Step 9: copy the traffic_ir function below and add to the end of the existing code.
dim current_seconds
function traffic_ir()
if current_seconds > 40 then
current_seconds = 0
endif
if
current_seconds = 0 then // red
light_state(1)
endif
if
current_seconds = 15 then // red+amber
light_state(2)
endif
if
current_seconds = 20 then // green
light_state(3)
endif
if
current_seconds = 35 then // amber
light_state(4)
endif
current_seconds = current_seconds + 1 // update count
endf
Note that there is also a variable defined called current_time, this will keep track of the number of seconds that have passed, see as a particular value is reached it changes the state of the traffic lights.
Step 10: Add the code below to the end of the file
function method2()
init()
current_seconds = 0
taskadd("traffic_ir()",1,1000,1)
endf
Type method2() This uses the built in scheduler to run the sequence. Not that you can still type into the terminal and even disrupt the sequence. Try print current_time to see where it is up to.
This is a bit more complex but will allow other operations when the program is running, similar to the task. Times are more accurate than the task and so should be reserved for accurate timings. This method uses a timer and interrupt, the timer will trigger the interrupt every second and a global variable will keep track of the seconds
Step 9: Add the two lines below to the top of the file, above the lib.io.bas include file.
// #include
"http://www.byvac.com//mBlib/flb/Library/2016/lib_tmr.bas"
// #include "http://ww.byvac.comm//mBlib/flb/Library/2016/lib_ir.bas"
And this text to the end of the current program
function method3()
init()
current_seconds = 0
print "Running\r\n"
tmr_init(*TIMER23(),7,312500) // 1 second
ir_set(*TIMER23(),3,"traffic_ir")
endf
Step 10: IMPORTANT type reset before loading the above program. This will clear the schedule as it will still try to do its scheduling whilst downloading is taking place and this will interfere with the download process. Use |A to send the whole thing over again.
Step 11: Type method3()
This concluded the traffic light program. Again to send any additional text using |A or |S then because the timer and interrupt are going , type reset first.