November 21, 2024, 11:21:34 AM

News:

Got VSA?  Want to use your Prop-SX?  Now you can!  See the VSA section of the Library forum for Prop-SX code that works with VSA.


DMX Fader

Started by macgruber, October 01, 2010, 10:53:17 AM

Previous topic - Next topic

macgruber

Hello SX / electronics gurus!

I have a question about implementing an AC fader using the DMX communication protocol. After reading some of the forum posts about the implementation of DMX using the SX I am optimistic that someone might be able to help me out!

For background, I referenced an article in Nuts and Volts written by Jon regarding the implementation of a fader on something similar to the FC-4. http://www.parallax.com/Portals/0/Downloads/docs/cols/nv/vol8/col/nv146.pdf

Essentially, this circuit makes clever use of the interrupt on the SX to update the gating of a Triac. To do this, the circuit must "update" the gating of a Triac every 32.55us (120Hz/256) so that it gates at a particular point of the AC waveform. This allows the circuit to control the amount of power delivered to the load. This is all fine and great... but here is my question:

In the original article, Jon describes communicating with the SX using a baud of 38.4K. DMX is 250K! Thus, the bit time of the DMX signal is 4us. If we sample the bit 4x, as Jon did in his article, we are down to a sample period of 1us. I am wondering if this is truly possible with the SX running at 50MHz because we would only be able to execute 50 instructions before we have to trigger the interrupt again?

Any thoughts? Can the SX get stuck in an interrupt loop if you execute too many commands?

Also, one final question... Assuming that the aforementioned program is possible, Jon used the bit sampling interval to execute the dimming process (32.55 / 6.51 = 5). So, after 4 sampling intervals, update the dimmer. Fortunately, that divisor, as Jon mentioned, is very clean. In the case of the 1us interval, the math isn't so forgiving and we get a remainder of 0.51us. Would that remainder cause any major problems? I would think not because you won't really notice the difference in intensity if you gate a half a microsecond too early???

JonnyMac

October 01, 2010, 12:26:04 PM #1 Last Edit: October 01, 2010, 12:29:32 PM by JonnyMac
Just a reminder... these forums are specifically for supporting EFX-TEK products (hence I'm locking this thread).  To that end I will limit my discussion there.  You can take this information and apply it to your project.  For general SX support you should post in the Parallax forums as it is their product.

Now....

DMX on the SX is not for the faint-of-heart -- I know this from real experience.  As you indicated, the timing for serial sampling comes into play and you may have to make some compromises.  For DMX I sample the bits at 1.333 microseconds (3x per bit period).  For the triac gating period that is about 24.47 interrupts.  You could try 24 or 25 and see which works best.

The code below runs on a Prop-SX with our DMX add-on.  It is an 8-channel DC dimmer.  And, yes, it works -- the guys at Disneyland are using it right now in the Haunted Mansion (that's why I have a fresh code update).  You'll see though, that timing is tricky.  In fact, this program is an assembly program in an SX/B shell so I can keep things as tight as possible.

Note: If this isn't a must-have project right now, you may want to wait for our FC-4+ which uses the Propeller processor, has built-in RS-485 and a DMX address switch, and is fully user-programmable for other applications.   We'll provide plug-and-play DMX and AC dimming objects, you can take it from there for anything custom.  There is no guarantee that we'll have the FC-4+ ready this year, though we are pushing ourselves to get it done ASAP.

' =========================================================================
'
'   File...... DMX512-BG_Fader_x8.SXB
'   Purpose... DMX-512 interface for controlling 8 PWM outputs
'   Author.... Jon Williams
'              Copyright (c) 2008-2010 EFX-TEK
'              Some Rights Reserved
'              -- see http://creativecommons.org/licenses/by/3.0/
'   E-mail.... jwilliams@efx-tek.com
'   Started...
'   Updated... 17 SEP 2010
'
' =========================================================================


' -------------------------------------------------------------------------
' Program Description
' -------------------------------------------------------------------------
'
' DMX-512 LED dimmer for the Prop-SX
' -- uses the EFX-TEK RS-485 adapter for DMX serial and address input


' -------------------------------------------------------------------------
' Device Settings
' -------------------------------------------------------------------------

ID              "DMX-8x"

DEVICE          SX28, OSCHS1, BOR42
FREQ            50_000_000


' -------------------------------------------------------------------------
' IO Pins
' -------------------------------------------------------------------------

Lamps           PIN     RC
Lamp8          PIN     RC.7 OUTPUT
Lamp7          PIN     RC.6 OUTPUT
Lamp6          PIN     RC.5 OUTPUT
Lamp5          PIN     RC.4 OUTPUT
Lamp4          PIN     RC.3 OUTPUT
Lamp3          PIN     RC.2 OUTPUT
Lamp2          PIN     RC.1 OUTPUT
Lamp1          PIN     RC.0 OUTPUT

Ctrl            PIN     RB
Aux            PIN     RB.7 INPUT              ' auxilliary input
RX             PIN     RB.6 INPUT              ' serial in
TX             PIN     RB.5 INPUT              ' serial out (not used)
TxEnable       PIN     RB.4 OUTPUT             ' tx control (0 = off)
Addr8          PIN     RB.3 INPUT              ' bit 8 of address
Clock          PIN     RB.2 OUTPUT             ' to 74x165.2 (CLK)
Din            PIN     RB.1 INPUT              ' to 74x165.9 (QH)
ShLoad         PIN     RB.0 OUTPUT             ' to 74x165.1 (S/LD)

TX2             PIN     RA.3 OUTPUT             ' to DB-9
RX2             PIN     RA.2 INPUT              ' from DB-9
SCL             PIN     RA.1 INPUT              ' EE clock line (I2C)
SDA             PIN     RA.0 INPUT              ' EE data line (I2C)


' -------------------------------------------------------------------------
' Constants
' -------------------------------------------------------------------------

Yes             CON     1
No              CON     0


' -------------------------------------------------------------------------
' Variables
' -------------------------------------------------------------------------

flags           VAR     Byte                    ' (global)
isrFlag        VAR     flags.0
rxReady        VAR     flags.1                 ' serial byte ready

pwmState        VAR     Byte                    ' dimmer state (global)
state           VAR     Byte                    ' program state

dmxStart        VAR     Word                    ' address or red channel
breakTmr        VAR     Byte                    ' to measure DMX break
channel         VAR     Word                    ' current channel

rxCount         VAR     Byte                    ' rx bit count
rxDivide        VAR     Byte                    ' bit divisor timer
rxByte          VAR     Byte                    ' recevied byte

idx             VAR     Byte

dimmer          VAR     Byte(16)
level1         VAR     dimmer(0)
level2         VAR     dimmer(1)
level3         VAR     dimmer(2)
level4         VAR     dimmer(3)
level5         VAR     dimmer(4)
level6         VAR     dimmer(5)
level7         VAR     dimmer(6)
level8         VAR     dimmer(7)
acc1           VAR     dimmer(8)
acc2           VAR     dimmer(9)
acc3           VAR     dimmer(10)
acc4           VAR     dimmer(11)
acc5           VAR     dimmer(12)
acc6           VAR     dimmer(13)
acc7           VAR     dimmer(14)
acc8           VAR     dimmer(15)


' -------------------------------------------------------------------------
 INTERRUPT NOCODE 750_000                      ' 1.333 us
' -------------------------------------------------------------------------

' --------
' Mark ISR
' --------
'
Marker:
 ASM
   BANK  flags
   SETB  isrFlag                               ' mark for foreground
 ENDASM


' -------
' RX UART
' -------
'
Receive:
 ASM
   JB    rxReady, RX_Done                      ' skip if byte waiting
   MOVB  C, RX                                 ' sample serial input
   TEST  rxCount                               ' receiving now?
   JNZ   RX_Bit                                ' yes, get next bit
   MOV   W, #9                                 ' no, prep for next byte
   SC
    MOV  rxCount, W                            ' if start, load  bit count
   MOV   rxDivide, #5                          ' prep for ~1.6 bit periods

RX_Bit:
   DJNZ  rxDivide, RX_Done                     ' complete bit cycle?
   MOV   rxDivide, #3                          ' yes, reload bit timer
   DEC   rxCount                               ' update bit count
   SZ
    RR   rxByte                                ' position for next bit
   JNZ   RX_Done
   SETB  rxReady                               ' alert foreground

RX_Done:
 ENDASM


' -----------
' PWM Control
' -----------
'
' The scheduler allows just one PWM channel update per ISR cycle
' -- PWM frequency is 366 Hz (750_000 / 8 / 256)

Pwm_Scheduler:
 ASM
   MOV   W, pwmState                           ' point to current channel
   JMP   PC+W                                  ' jump to it
   JMP   Pwm_L1
   JMP   Pwm_L2
   JMP   Pwm_L3
   JMP   Pwm_L4
   JMP   Pwm_L5
   JMP   Pwm_L6
   JMP   Pwm_L7
   JMP   Pwm_L8

Pwm_L1:
   BANK  dimmer
   ADD   acc1, level1                          ' update accumulator
   MOVB  Lamp1, C                              ' output on if rollover
   JMP   Pwm_Done

Pwm_L2:
   BANK  dimmer
   ADD   acc2, level2
   MOVB  Lamp2, C
   JMP   Pwm_Done

Pwm_L3:
   BANK  dimmer
   ADD   acc3, level3
   MOVB  Lamp3, C
   JMP   Pwm_Done

Pwm_L4:
   BANK  dimmer
   ADD   acc4, level4
   MOVB  Lamp4, C
   JMP   Pwm_Done

Pwm_L5:
   BANK  dimmer
   ADD   acc5, level5
   MOVB  Lamp5, C
   JMP   Pwm_Done

Pwm_L6:
   BANK  dimmer
   ADD   acc6, level6
   MOVB  Lamp6, C
   JMP   Pwm_Done

Pwm_L7:
   BANK  dimmer
   ADD   acc7, level7
   MOVB  Lamp7, C
   JMP   Pwm_Done

Pwm_L8:
   BANK  dimmer
   ADD   acc8, level8
   MOVB  Lamp8, C

Pwm_Done:
   BANK  $00
   INC   pwmState                              ' point to next channel
   AND   pwmState, #%00000_111                 ' keep 0-7
 ENDASM

 RETURNINT


' -------------------------------------------------------------------------
' Subroutine Declarations
' -------------------------------------------------------------------------


' =========================================================================
 PROGRAM Start
' =========================================================================

Start:
 ASM
   CLRB  TxEnable                              ' disable transmitter
   CLRB  Clock                                 ' 75x165 clock 0-1-0
   SETB  ShLoad                                ' 75x165 to shift
   CLR   pwmState
 ENDASM


New_Frame:
 ASM
   CLR   state                                 ' wait for break
   CLR   breakTmr
   SETB  rxReady                               ' disable UART
   CLR   rxDivide                              ' reset UART
 ENDASM


Scan_Address:                                   ' read 74HC165 bits
 ASM
   CLRB  ShLoad                                ' S/L = Load
   CLRB  isrFlag
   JNB   isrFlag, $                            ' wait 1.3 us
   SETB  ShLoad                                ' S/L = Shift
   CLRB  isrFlag
   JNB   isrFlag, $
   MOV   idx, #8                               ' get eight bits

Read_Addr_Bits:
   RL    dmxStart_LSB                          ' shift for next bit
   CLRB  isrFlag
   JNB   isrFlag, $
   MOVB  dmxStart_LSB.0, Din                   ' get bit, MSB first
   SETB  Clock
   CLRB  isrFlag
   JNB   isrFlag, $
   CLRB  Clock
   DJNZ  idx, Read_Addr_Bits
   CLR   dmxStart_MSB                          ' MSB = 0
   ADDB  dmxStart_MSB, Addr8                   ' get bit8 of address
 ENDASM


Check_Address:
 IF dmxStart = 0 THEN Start                    ' trap bad addresses
 IF dmxStart > 505 THEN Start


Main:
 ASM
   CLRB  isrFlag
   JNB   isrFlag, $                            ' wait for flag
 ENDASM


Handle_State:
 ASM
   MOV   W, state
   JMP   PC+W
   JMP   Wait_4_Break
   JMP   Break_Release
   JMP   Skip_Start
   JMP   Find_Target
   JMP   Update_Channels
 ENDASM


Wait_4_Break:
 ASM                                           ' waiting for break
   INC   breakTmr                              ' update break timer
   SNB   RX                                    '  in break state?
    CLR  breakTmr                              ' no, reset timer
   CJB   breakTmr, #65, Main                   ' wait for break
   INC   state
   JMP   Main
 ENDASM


Break_Release:
 ASM
   JNB   RX, Main                              ' abort if still in break
   CLR   rxCount                               ' reset UART
   CLRB  rxReady                               ' enable UART
   INC   state
   JMP   Main
 ENDASM


Skip_Start:                                     ' skip start code
 ASM
   JNB   rxReady, Main                         ' exit if not ready
   CLRB  rxReady                               ' re-enable UART
   MOV   channel_LSB, #1                       ' reset for channel search
   CLR   channel_MSB
   INC   state
   JMP   Main
 ENDASM


Find_Target:
 IF channel < dmxStart THEN                    ' still looking?
   IF rxReady = Yes THEN                       ' byte available?
     rxReady = No                              ' re-enable UART
     INC channel                               ' update channel pointer
   ENDIF
   GOTO Main
 ELSE
 \ CLR   idx                                   ' select first channel
 \ INC   state
 ENDIF

 ' let it drop through


Update_Channels:
 ASM
   JNB   rxReady, Main                         ' abort if no byte ready
   MOV   __PARAM1, rxByte                      ' get rxByte...
   MOV   __PARAM2, idx                         ' get channel index
   MOV   FSR, #level1                          ' point to levels
   ADD   FSR, __PARAM2                         ' add index
   MOV   IND, __PARAM1                         ' dimmer(idx) = rxByte
   BANK  $00
   CLRB  rxReady                               ' re-enable UART
   INC   idx                                   ' point to next channel
   SB    idx.3                                 ' done?
    JMP  Main                                  '  no
   JMP   New_Frame                             ' prep for next DMX frame
 ENDASM


Jon McPhalen
EFX-TEK Hollywood Office