Hi,
I have a little side task that I have been working on, basically its a string of RGB led's strung together to produce a decorative christmas lighting effect.. Each of the LED's is actually a tiny PCB with a PIC12F629 on board which PWM each colour. These chips run at 4 MHz using their internal RC oscillator, and do not have inbuilt USARTs, using debugin we can achieve a maximum of 9600 baud.
To address each PIC, a common serial line is fed to each of the PIC's and each PIC takes three bytes (one for each colour) out of the byte stream based on its ID (location in the chain). In addition there are two leading bytes of which we don't care about their value, they are merely used to trigger into the interrupt and a trailing byte. To prevent re-entry into the interrupt once we have received our LED values we wait until the sentinel byte is received.
By now your probably starting to see the problem, with 25 PICs we have a string length of 75 + 3 bytes, at 9600 baud this will take somewhere in the region of 80ms per update. During this time the lights are out, and a noticeable flicker is observed. I have considered disabling the interrupt and using a timer to re-enable it later allowing the main PWM loop to continue. However this only fixes the problem near the beginning of the string. Towards the end we are still waiting ~80ms for the data to arrive. Another alternative is to address each PIC individually however this is quite inefficient when changing the entire string at once. Theres always using a chip with PWM or a separate PWM chip, but I already have the PIC's and PCBs, and besides on longer strings the fewer and cheaper the parts the better, currently it is only a PIC, RGB LED and 1uF cap per board. So the question I pose is, is there a better solution that I am missing to spend the least time away from the main loop yet still be able to address all PIC's and update them several times a second?
I guess if I ever make another string I could use the PIC12F615 with an 8 MHz oscillator, but the fundamental problem still exists.
My current code is below:
Code:
@ __config _INTRC_OSC_NOCLKOUT & _WDT_OFF & _MCLRE_OFF & _CP_OFF
DEFINE OSC 4
DEFINE OSCCAL_1K 1
DEFINE DEBUGIN_REG GPIO ' Set Debugin pin port
DEFINE DEBUGIN_BIT 2 ' Set Debugin pin bit
DEFINE DEBUG_BAUD 9600 ' Set Debugin baud rate (same as Debug baud)
DEFINE DEBUGIN_MODE 0 ' Set Debugin mode: 0 = true, 1 = inverted
ID CON 1
vRed var Byte
vBlue var Byte
vGreen var Byte
Buffer var Byte
Junk var Byte
Counter var Byte
Shaddow var Byte
'Symbols
Symbol GIE = INTCON.7 ' Global Interrupt Enable
Symbol PEIE = INTCON.6 ' Peripheral Interrupts Enabled
Symbol INTIF = INTCON.1 ' Ext Interrupt Flag
Symbol INTIE = INTCON.4 ' Ext Interrupt Enable
Symbol INTEDG = OPTION_REG.6 ' Interrupt Edge
Symbol TMR1ON = T1CON.0 ' Timer1 On
Symbol TMR1IE = PIE1.0 ' Timer1 Interrupt Enable
Symbol TMR1IF = PIR1.0 ' Timer1 Interrupt Flag
' -------------- Pin Assignments --------------
GP0 var GPIO.0
gRed var GPIO.1
Rx var GPIO.2
GP3 var GPIO.3
gGreen var GPIO.4
gBlue var GPIO.5
Symbol Red = Shaddow.1
Symbol Green = Shaddow.4
Symbol Blue = Shaddow.5
' -------------- Initialisation --------------
Initialisation:
'OSCCAL = %11111111 ' 4 MHz Internal Oscillator
Pause 50 ' Safe Start Up Delay
ANSEL = %00000000 ' Disable Analogue Inputs
CMCON = %00000000 ' Disable Comparator
TRISIO = %00111111
Shaddow = %11111111
GPIO = Shaddow
Junk = 2 + 3 * (ID - 1)
vRed = 0
vGreen = 0
vBlue = 0
Input Rx
Output gRed
High gRed
Output gGreen
High gGreen
Output gBlue
High gBlue
'Enable Interrupts
GIE = 1
PEIE = 1
INTEDG = 0
INTIE = 1
INTIF = 0
ON INTERRUPT GOTO Int_Handle
'-------------- Main Loop --------------
Iterate:
DISABLE
If Counter = 0 Then Shaddow = %11001101
If Counter = vRed Then Red = 1
If Counter = vGreen Then Green = 1
If Counter = vBlue Then Blue = 1
GPIO = Shaddow
Counter = Counter + 1
ENABLE
Goto Iterate
DISABLE
' -------------- Interrupts --------------
Int_Handle:
GPIO = %11111111
DebugIn 1, Int_Exit, [skip Junk, vRed, vGreen, vBlue, wait (255)]
vRed = vRed
vGreen = vGreen
vBlue = vBlue
Counter = 0
Int_Exit:
INTIF = 0
Resume
ENABLE
end
All the Best,
Daniel
Bookmarks