A walking light is a row of lamps which are lighted one by one. This gives the impression that a light walks along the row. In this assignment we will make a walking light from 8 LEDs. With appropriate hardware (optocouplers and triacs) the same programs can be used to control 8 lamps.
A small problem is that for simplicity we want to use the pins of port b and when we connect a LED directly to pin B6 or B7 this would prevent in-circuit programming of the PIC. Hence we use - for these pins only - a buffer transistor.
The program for a light which always walks in the same direction is quite simple:
include 16c84_10
include jlib
port_b_direction = all_output
var byte x = 0b_0000_0001
forever loop
port_b = ! x
delay_100ms( 2 )
x = x << 1
if x == 0b_0000_0000 then
x = 0b_0000_0001
end if
end loop
After the include lines (remember to adapt the first one to the 16x84 chip and crystal you use) we first make all pins of port B outputs. Just before the forever loop we declare a variable which we initisalize to 0b_0000_0001, which means all bits off except the lowest one which is on.
The exclamation mark in port_b = ! x means that the value which is written to port B has all bits inverted. This is necessary because the LEDs are connected between the ouput pins and the + which makes the output pins active low.
Within the loop we first write the (inverted) value of x to port B and we wait 2 * 100 ms = 0.2 seconds. Next we shift the value in x one position to the left. When we do this often enough the one bit which is on will shift out at the left while off bits shift in at the right, producing a value of all bits off (all zero's). When this is the case we set x back to its initial value of 0b_0000_0001.
walk1.jal
Build the circuit and program the 16x84.
walk2.jal
Instead of a single LED which is on we can of course
take another pattern and shift it. Change the program
to have 2 LEDs on at any time. You must change both
the initial values and the test.
Instead of shifting a pattern we can also create an expanding bar: first only LED 0, then LED 0 and LED 1, etc. The trick to achieve this is a code line
x = ( x << 1 ) | 0b_0000_0001
The | means OR: each bit in x will be shiften one position
to the left and then the lowest will be set.
The net effect is that the light grows from right to left.
walk3.jal
Adapt the program.
You will have to change the IF condition too.
The best effect will likely require that you put the shifting
in the else part of the if statement.
The Nightrider car shows a light which bounces back and forth. To achieve this effect we must remember, besides the current value of x, also the current direction in which the light moves. When the light hits the left or right border the direction must be reversed.
..
const bit to_left = low
const bit to_right = high
var bit direction = to_left
..
if x == 0b_0000_0001 then
direction = to_left
end if
if x == 0b_1000_0000 then
direction = to_right
end if
if direction == to_left then
x = x << 1
else
x = x >> 1
end if
..
walk4.jal
Only the new parts of the program are shown.
Try to understand how these parts work and change your program.
walk5.jal
Change your program to let two LEDs light up.
Symmetrical patterns often look nice. A simple symmetrical pattern consists of two light which move from the edges towards the middle. This pattern has only five steps (the last one is 'all LEDs off), so its is easy to write out all steps:
forever loop
port_b = ..
delay..
port_b = ..
delay ..
port_b = ..
delay..
port_b = ..
delay..
port_b = ..
delay..
end loop
walk6.jal
Write the new program, filling in the missing parts.
Almost nothing of the previous program is left.
walk7.jal
The last program can be simplified a bit by creating a procedure
which takes one argument which it writes to port b and then
delays.
Within the loop you just call this procedure 5 times.
walk8.jal
Change your program to let the lights touch in the middle and then
move out again. Leave out the 'all LEDs off' step.
This pattern has 6 steps.