Step 2The dimming algorithm - charliplexed pulse width modulation
See the video for a demonstration. In the middleis the new Minidot clock, on the right is the older Minidot. Notice how much nicer the new one is.
(FYI the other displays in the background are my Minicray supercomputer status display and my captured Nebulon particle which powers the Minicray in an antimatter magnetic confinement field. See here:
http://www.youtube.com/watch?v=bRupDulR4ME
for a demonstration of the nebulon confinement chamber)
If you look in the code, open the display.c file. Note there are four arrays for mapping the tris/port values to illuminate any particular array and two arrays (one more than the Microdot code) for defining which LEDs should be illuminated for any particular pattern of LEDs.
eg:
// LED1 LED2 LED3 ...unsigned char LEDS_PORTA[31] = { 0x10, 0x00, 0x00, ...unsigned char LEDS_TRISA[31] = { 0xef, 0xff, 0xff, ...unsigned char LEDS_PORTB[31] = { 0x00, 0x02, 0x04, ...unsigned char LEDS_TRISB[31] = { 0xfd, 0xf9, 0xf9, ...unsigned char nLedsA[30];unsigned char nLedsB[30];To light up LED1 for example, you need to set the TRIS registers TRISA:B = 0xef:0xfd and PORT registers PORTA:B=0x10:0x00 and so on. If you write out the tris values in binary you'll note that at any one time, there are only two outputs enabled. The others are all set to Tri-state (hence TRIS register). This is central to charlieplexing. You'll also note that one output is always a logical '1' and the other is always a logical '0'....the direction of which turns on whichever LED is between these two output lines.
The last value in the port/tris arrays is a null value to turn on no LED at all.
In the Microdot, the update_display function cycled continuously through another array (nLeds[]) to see if that particular LED was to be illuminated. If it was, then the corresponding tris/port values were set and the LED illuminated for a period of time. Otherwise the null value was sent to the PICs TRIS/PORT registers and no LED was illuminated for a period of time. When done fast enough this gave a pattern. The rest of the program would periodically read the RTC values and make up a nice random pattern in that array....and so the display changed.
To make a dimming function, this was slightly extended so that after the 30 LEDs were either illuminated (or not) then extra periods would be spent on sending null values if the display was to be dimmed.....for full brightness then no extra periods would be spent. When repeated if there were a lot of null periods to the illuminated LEDs, the display would be dim. In effect this is multiplexed pulse width modulation.....or because the hardware is configured in a charlieplex arragement, then charlieplexed pulse width modulation.
The second diagram below shows the basic setup for this. I call this a scan frame. The first 30 periods to the frame are used to go through the LEDs.....and a variable number of extra periods define how dim the display will be. This cycle repeats. More null periods means less time for an LED to be on per frame (because the number of periods increased). Note the vertical axis doesn't mean voltage level. The actual state of the pins going to the LEDs varies depending on it's position in the charlieplex array.....in the diagram it just means on or off.
This also meant the total length of the frame in time also increased, thus decreasing the refresh rate. As the LEDs got dimmer, they would start to flicker in other words. So this method is useful only to an extent. For the clock, it was OK.
A function is called intermittantly that reads the A/D converter on the PIC and sets this brightness level. If you read the code, it also checks to see if the LED nearest the LDR is on, and doesn't do any level setting if so, this stops the display unexpectedly brighting when the pattern changed.
Next the cross fade function.
| « Previous Step | Download PDFView All Steps | Next Step » |
![]() |
Add Comment
|










































