16x84 assignment 2 : walking lights

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.

walking lights circuit

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.

work walk1.jal
Build the circuit and program the 16x84.

work 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.

work 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
   ..

work walk4.jal
Only the new parts of the program are shown. Try to understand how these parts work and change your program.

work 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

work walk6.jal
Write the new program, filling in the missing parts. Almost nothing of the previous program is left.

work 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.

work 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.