My first PIC project is a LED controller (henceforth referred to as “LC”) for my Quadcopter 1. The LC will receive commands over a RC channel and control four high intensity LEDs that I will connect to the underside of the arms of the quadcopter. I will describe the features of the LC in a separate post. This post describes the first stage of programming the LC.
In this stage I wrote code that allows me to control any number of LEDs (well, in practice I can attach only four LEDs to the PIC12F1822) by defining different properties for each LED. The code is object-oriented in the sense that the behaviour of each LED is defined in an instance of a struct (=an object) and functions operate on these objects. I considered implementing a full object oriented model in which the functions are also included in the struct, but I FEEL that the overhead of this approach is too much for the tiny PIC controller and the inefficient compiler (the free XC8) that I use.
The following video shows the LC in use with two LEDs that blink at a different rate. The yellow LED blinks three times and then waits while the green LED blinks five times and waits. These two LEDs can be used as indicators to the internal state of the LC which has a major state (yellow LED) and a sub-state (green Led).
So let’s describe the code.
The application consists of three files:
- Main function with the main loop
- LED Controller header file
- LED Controller implementation
I will start with the main function because it shows how the LC code is used.
Main.c starts with setting up the configuration bits. Then the ISR counts the number of times Timer0 overflows where each overflow happens every 0.25 of a millisecond. The calculation is as follows:
- Timer 0 prescaler (PSA) is set to 8 which means that the timer counts at a rate of 1Mhz
- On each overflow TMR0 is set to 6 so it counts 250 ticks before it overflows again.
Then the main function starts with initialising the ports and defining the LEDConfig instances for the two LEDs. Finally the main loop starts. After every 4 overflows of Timer 0 (which are more or less equivalent to 1ms) the main loop calls the HandleLEDs function that updates the state of the LEDs.
Note that main needs only instantiate the LEDConfig structs, pass them to the LC and then notify the LC once every 1ms.
LED Controller header file
The header file defines the “blink interval” and “off interval”, the LEDConfig struct and declares the functions that operate on instances of LEDConfig. The “blink” and “off” intervals specify the amount of time a LED is on or off while blinking and the amount of time it is off between bursts of blinking.
LED Control C file
The C file manages the array of LEDConfig structs so that the user of this code (i.e. the main function in this example) needs only create these structs and pass them to the LC. Main must also notify the LED controller of every “tick” of the clock and the LC takes care of everything else.
I found this site somewhat useful to understand how Timer 0 should be used.