DMX project for controlling flexible LED strip.

Thread Starter

loesvan

Joined Sep 23, 2011
28
Hi Ana,

if the interrupts cause this flickering as Mike elaborated above, there is not much you can do about it with this microcontroller. If you want somthing simple I'd recommend using WS2812 LED strips. They have a one wire protocol and generate their own PWM signal, you just have to feed them the data (24bit RGB). There is a good C library that makes use of ASM code for the proper timing. I used it in some of my projects already, works great on an ARM M0 and the author tested it on Atmel MCUs and Arduino. It may also work on a PIC but I am not familiar with those. The code is here: https://github.com/cpldcpu/light_ws2812
Hi Damian, Thanks for your reply.
I have about 100 meters of RGB led flex and the controllers that i made for my self. I wood like to make my system work properly, but if it's not possible it will stay as it is.
Thank you very much. Ana
 

Thread Starter

loesvan

Joined Sep 23, 2011
28
We know that the problem is with the interrupts. What i understand buy Mikes post is that the PWM cycle is getting interrupted about 200 times before the PWM cycle has finished, I thought that the interrupts was deactivated while the PWM cycle was busy (INTCON,GIE) Would it be possible to deactivate the interrupts while PWM cycle is not completed? or have less interrupts to reduce or stop the flickering?
Sorry for my English. My father is dutch, my mother is English. My husband is Spanish and i was born in Germany so i speak no language properly. hi, hi.
Ana
 

MMcLaren

Joined Feb 14, 2010
861
if the interrupts cause this flickering as Mike elaborated above, there is not much you can do about it with this microcontroller.
The program is the problem, not the microcontroller. As I mentioned, there's no "easy fix" for that program. It would need a major re-write to make sure the software PWM isn't interrupted while maintaining the 250-kbaud DMX512 data stream.

Pete Griffith's DMX512 4-channel controller example is worth studying.

Cheerful regards, Mike
 

djsfantasi

Joined Apr 11, 2010
9,163
Just a random thought.

Could a solution be to separate functions on separate microcontrollers? One to serve as the DMX Receiver and a second as an LED controller (PEM)? With a hardware interface between the two, the PIC performing the PWM would not be interrupted by serial communications from the DMX controller.

Just blue skying. I have no actual solution available.
 

Sensacell

Joined Jun 19, 2012
3,447
At low duty cycles, erratic PWM becomes very visible.

The best way to handle PWM is by using a chip with built-in PWM modules, many of Microchip's parts have CCP (Capture/Compare/PWM)
modules that do this nicely, requires zero CPU overhead to make perfect PWM.

It's also possible to do it in code by reversing the strategy, make the PWM interrupt driven by a timer, then poll the RX for DMX data.
This only works for relatively low PWM frequencies, which also tend to look a bit jumpy. The CPU clock must be as fast as possible to avoid missing DMX data, which arrives every 40 us!
 

MMcLaren

Joined Feb 14, 2010
861
I agree that it would be much easier to implement a 3-channel DMX512 Receiver using a PIC with three hardware PWM channels. The 8-pin 12F1572 ($0.83) has a serial peripheral and three high-definition (16-bit) PWM channels, as does the 14-pin 16F1575 ($1.36). If you wanted to design a new high-performance 3-channel DMX512 Receiver from scratch, one of these chips would probably be a good choice.

Coming up with a 3-channel DMX512 Receiver with high performance 'software' PWM for the 16F628A is much more challenging (and intriguing). I wonder if a BAM (Bit Angle Modulation) driver could be made to work for this application?

A BAM driver updates the LED outputs at binary weighted intervals. That is, instead of using 256 intervals to update a traditional 8-bit (256 step) 'software' PWM output, a BAM driver would update the LED outputs at 8 binary weighted intervals which are 1, 2, 4, 8, 16, 32, 64, and 128 steps in width. A "data bender" is used at the end of each period to build an eight byte bam[] array from the duty cycle variables for each channel and the bam[] array is used for interval updates. Unfortunately, my typical BAM driver (see below) would need to be modified in some way to accomodate polling the serial port and implementing the DMX512 state machine at 200 cycle (40-usec) intervals while maintaining precise PWM outputs.

I'm sorry I don't have more time to play with this...

Good luck on your project, Ana.

Cheerful regards, Mike


Code:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  interrupt vector                                               ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
        org     0x004
        radix   dec
v_isr
        clrf    STATUS          ; force bank 0 & IRP = 0          |00
        bcf     PIR1,TMR2IF     ; clear TMR2 interrupt flag       |00
;
;  BAM interrupt driver, Mike McLaren, 2017
;
;  perform full 8-bit PWM cycle during each 256-usec (1280 cycle)
;  interrupt for a ~3906-Hz refresh rate and about ~50% overhead.
;
T0      movf    bam+0,W         ; 2^0 interval =   1-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+0           ; clear bam[0] for next cycle     |00
        delayCy(tStep*1-3)      ; (2)                             |00
T1      movf    bam+1,W         ; 2^1 interval =   2-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+1           ; clear bam[1] for next cycle     |00
        delayCy(tStep*2-3)      ; (7)                             |00
T2      movf    bam+2,W         ; 2^2 interval =   4-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+2           ; clear bam[2] for next cycle     |00
        delayCy(tStep*4-3)      ; (17)                            |00
T3      movf    bam+3,W         ; 2^3 interval =   8-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+3           ; clear bam[3] for next cycle     |00
        delayCy(tStep*8-3)      ; (37)                            |00
T4      movf    bam+4,W         ; 2^4 interval =  16-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+4           ; clear bam[4] for next cycle     |00
        delayCy(tStep*16-3)     ; (77)                            |00
T5      movf    bam+5,W         ; 2^5 interval =  32-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+5           ; clear bam[5] for next cycle     |00
        delayCy(tStep*32-3)     ; (157)                           |00
T6      movf    bam+6,W         ; 2^6 interval =  64-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+6           ; clear bam[6] for next cycle     |00
        delayCy(tStep*64-3)     ; (317)                           |00
T7      movf    bam+7,W         ; 2^7 interval = 128-usecs        |00
        movwf   PORTB           ;                                 |00
        clrf    bam+7           ; clear bam[7] for next cycle     |00
;
;  refresh 8-byte BAM array (16 cycles per macro call)
;
        bender  Reg1,RB1        ; insert channel 1 bits           |00
        bender  Reg2,RB5        ; insert channel 2 bits           |00
        bender  Reg3,RB4        ; insert channel 3 bits           |00
        bender  Reg4,RB6        ; insert channel 4 bits           |00
        bender  Reg5,RB3        ; insert channel 5 bits           |00
        retfie                  ;                                 |00
Code:
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
;  data bender macro                                              ~
;~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

bender  macro   pwmvar,index
        btfsc   pwmvar,0        ; 2^0 bit                         |00
        bsf     bam+0,index     ;                                 |00
        btfsc   pwmvar,1        ; 2^1 bit                         |00
        bsf     bam+1,index     ;                                 |00
        btfsc   pwmvar,2        ; 2^2 bit                         |00
        bsf     bam+2,index     ;                                 |00
        btfsc   pwmvar,3        ; 2^3 bit                         |00
        bsf     bam+3,index     ;                                 |00
        btfsc   pwmvar,4        ; 2^4 bit                         |00
        bsf     bam+4,index     ;                                 |00
        btfsc   pwmvar,5        ; 2^5 bit                         |00
        bsf     bam+5,index     ;                                 |00
        btfsc   pwmvar,6        ; 2^6 bit                         |00
        bsf     bam+6,index     ;                                 |00
        btfsc   pwmvar,7        ; 2^7 bit                         |00
        bsf     bam+7,index     ;                                 |00
        endm
 
Last edited:

Thread Starter

loesvan

Joined Sep 23, 2011
28
Sorry that i took so long with the reply but i had to go away for some days. I have added to the circuit another PIC, it's a 16F88. On this PIC i made a program to decode an IR signal from a remote control so i can choose that the system works on DMX or an internal program that i made for changing colors. When it's on the changing color mode it works perfect but when it's on DMX it still flickers. The way i communicate between the DMX PIC and the 16F88 is:

DMX
BTFSC Porta,1
BSF LEDR
BTFSS Porta,1
BCF LEDR
GOTO DMX

That is the code i made for the red DMX data input, the green and blue are the same with different ports. I have been trying to send the DMX level on Reg1, Reg2, Reg3 to the 16F88 via serial but it doesn't work. ASM is difficult for me. I normally use basic for programing. The idea is to receive the DMX data and make the PWM on the 16F88 to separate the DMX and PWM like djsfantasi said on his post.
What is the best way to send the DMX data from Reg1, Reg2 and Reg3 to the 16F88? Can someone send me an example code?
I send a picture of the new circuit.
Thanks a lot ANA.
 

Attachments

MMcLaren

Joined Feb 14, 2010
861
You lost me. I'm not sure what you're trying to do there.

Ana, may I ask what you're using for a DMX Transmitter (IC, software, schematic), please?

Regards, Mike
 

Thread Starter

loesvan

Joined Sep 23, 2011
28
Top