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:
All the Best,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
Daniel




Bookmarks