Better processing of a serial bitstream


Closed Thread
Results 1 to 3 of 3
  1. #1
    Join Date
    Jun 2006
    Posts
    12

    Default Better processing of a serial bitstream

    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
    Last edited by breesy; - 7th June 2007 at 11:38.

  2. #2
    skimask's Avatar
    skimask Guest


    Did you find this post helpful? Yes | No

    Default

    I did the same thing awhile back, use an 8 pin PIC without a UART, ran RGB LEDs using PWM, tried to control/run them using serial input.
    Problem is, it takes X amount of time to receive serial bytes using the software 'bit-bang' method, which invariably interrupts your PWM for the LEDs, causing the flickering.

    My solution (and I'm sorry I can't give you the code I used 'cause I got paid a fair amount of money for it and the owner of that code is a tinkerer himself), using a 12F683, was to use the built in 8Mhz oscillator to run the TMR0 and use the overflow interrupt, this gave me a 7812.5Hz loop, which you could use to sample a serial input line using a 7812.5 baud rate. Well, that doesn't work too well because the bits have to be perfectly centered and everything.
    So, I use a bit of multi-sampling, over-clocking, majority logic, whatever you want to call it, whatever it's really called...I don't know.
    I knocked my transmitter baud rate down to 488.28125 (or at least as close to that as I could get it), and sampled the receive bit 16 times and I'd count the amount of time the bit was high and/or low and pick the higher number of the two.
    The one special case is the initial 'start' bit. If all 8 bits ended up being a '1', then I'd continue to look for another 4 bits of high without any low in there anywhere. Same thing for the stop bits.
    Basically, I made it up as I went along... It's kinda like bit-banging a serial port, but the program keeps running in the background.

    Oh, and at the same time the TMR0 overflow would interrupt, after checking the serial input, I'd update the RGB PWM for the LEDs.
    Worked out kinda slick...

    Hope that gives you some ideas...

  3. #3
    Join Date
    May 2006
    Location
    Del Rio, TX, USA
    Posts
    343


    Did you find this post helpful? Yes | No

    Default

    How often do you need to send each slave a seperate RBG value? If most of your transmissions will have the same values for many of the slaves, you might try something along these lines. Use a 4 byte + 3 Byte string. The 4 bytes is used to address the slaves, each with their own individual control bit. The 3 bytes are the RGB values. Any slave whose bit is set in the 4 bytes will use the RGB values, others will ignore the data.

    This would allow you to send a much smaller data packet, and the slave processing overhead would still be pretty minimal. Also, you could use the left over 7 bits (from the 4 byte group) to have a bunch of "commands" preprogrammed that the slaves could respond to accordingly.

    The obvious downside is that if you need to have individual values for all 75 slaves it is much more data then what you've got.

    Also, you might be able to dump the interrupt and just poll the RX pin. The master could hold this low (or high) for a period of time and the slaves can poll it. If it is in the correct state for a loop or two of the main loop, the slave jumps to the recieve and waits for the data. This would rid you of the need for the "junk" data. You would have to tinker with the timing to get all the slaves to respond reliably, but it should work well. With the above technique, you looking at about 7.3ms per data packet. 25 of them is 183ms, so a bit high if you have to update all of the slaves individually.

    Just a couple of thoughts,
    SteveB
    Last edited by SteveB; - 8th June 2007 at 00:25.

Similar Threads

  1. Replies: 33
    Last Post: - 19th March 2010, 03:02
  2. Dynamic USB Serial Number (PIC18F4550)
    By awmt102 in forum mel PIC BASIC Pro
    Replies: 4
    Last Post: - 16th July 2009, 17:03
  3. PIC18F4680 to PC via MAX232 (RS232 serial) no output
    By opticsteam1 in forum mel PIC BASIC Pro
    Replies: 2
    Last Post: - 14th April 2008, 20:39
  4. interfacing to the pc serial port
    By kelangfei in forum General
    Replies: 4
    Last Post: - 7th October 2007, 22:35
  5. Replies: 2
    Last Post: - 23rd July 2006, 08:16

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts