In programming the PIC microcontroller, we had to consider how to properly time the display and how to store the requisite amount of data on the PIC. We also enabled the PIC with USB communication using a firmware base provided in the course.
We planned to control the LED timing by increasing or decreasing the number of instruction cycles to delay after turning the LEDs on or clearing between frames. The delay would depend on whether the LEDs had cycled through more, as many, or fewer than all the arrays we wanted to be cycled through in a single rotation. To do this, we implemented an interrupt that occurred whenever RB0 was high. Each time through the main loop of the code, a variable counting the number of columns was incremented, and each time 100 columns were cycled through, a variable counting cycles was incremented. In the interrupt, the number of columns that should have been cycled through was calculated by multiplying the cycles by 100. That number was subtracted from the actual number of columns cycled through, multiplied by a proportionality constant, and added to the delay that kept the LEDs on before clearing them. The timing is not currently implemented in our system because the interrupt caused the LEDs to turn off when the voltage was increased, which was possibly caused by contact bounce on the reed switch triggering the interrupt too many times. Moreover, adjusting rotational speed by controlling the power input to the motor allowed for more flexibility in the display in terms of rotational effects and animation.
A diagram of how the timing of the LEDs works.
For each of m total image frames, the PIC must recognize which of the n LEDs on a post to turn on or off (as well as which of p posts to turn on for a 3D system). Initially, we stored this information as an m by n matrix on the PIC using a binary system to indicate which LEDs should be on or off for each frame. However, because the PIC18F2455 is limited to 24 kB of program memory (see page 12 of the PIC datasheet), this approach was too inefficient to be extended to large messages. Our next approach was to store LED index data as an integer that could be converted into binary directly on the PIC. While directly performing this calculation between successive time frames took too long to achieve persistence of vision, we were able to split up the information into a single array for each of the two port registers that the 10 LEDs were split between (PORTB and PORTC). Each entry in these arrays is an integer value corresponding to the binary output of the port register; for instance, if RB0, RB1, and RB2 on PORTB (bits 0, 1, and 2 of port register B, respecitvely) are set high, PORTB can be set to a value of 7:
These two numbers are calculated on the user end, and sent via USB to the PIC.
Data is transferred to the PIC from a computer using USB communication. We use three vendor requests to do this: one to set an entry in the arrays storing image information, one to clear the display, and one to define how many frames to cycle through.