Log in

View Full Version : DMX on 250000 baud receive



syscoder
- 5th March 2007, 12:41
Dear friends i have found a example in the forum.

i want to receive dmx512 signal from the tranmitter. i have an lightingdesk for dmx512 ch control. and i will build and device to receive it

i have pic 16f628 and 20 mhz osc i use mcs 2.3 and pbp2.47 for programming. i searched in the forum and saw many examples thanks for help . is this true to receive for ; İ HAVE PIC16F628 and it will be dimming 1 led

Which command we have to use here "Pulsin" or " Hserin" ? u use here pulsin


INCLUDE "modedefs.bas"

DEFINE OSC 20 ' osc for pic 16f628
DEFINE HSER_TXSTA 24h
DEFINE HSER_RCSTA 90h
DEFINE HSER_SPBRG 4
DEFINE HSER_BAUD 250000
DEFINE HSER_CLROERR 1
ASM
ERRORLEVEL -306, -302
ENDASM

CMCON = 7

' Variables diverves

counter VAR word ' Variable de travail WORD
idleflag VAR WORD
dummy VAR WORD
RCIF VAR byte
startcode VAR WORD
aminus VAR WORD
adresse_grada VAR WORD
x VAR WORD
newlevel1 VAR WORD
newlevel1 = RCREG 'This is your target channel data

adresse_grada = 20 ' my adress for exemple 20

'This next routine is called on a gosub from my main housekeeping loop:

checkdmx:

counter = 1 'just a dummy variable
pulsin portB.1,0,counter 'here I'm looking for the break signal

if counter = 0 then
idleflag = 1 'either no dmx, or break was too long to count
'return
endif


if counter < 40 then checkdmx 'watching for 'break
'if you get here, an active low pulse was detected, but it was too short.
'probably just part of the datastream. So go back and look again.

'otherwise, a valid break was found and it's time to read the start code

dummy = RCREG 'clear out any garbage which may be in the USART
dummy = RCREG
SPBRG = 0
TXSTA.2 = 0 'brgh = 0
TXSTA.4 = 0
RCSTA.7 = 1
RCSTA.6 = 0 'setting 8 bit receive mode, no parity, etc
RCSTA.4 = 0 'check the datasheet to see what all these bits do
RCSTA.4 = 1 'now, the USART is on and ready to receive

while RCIF = 0:wend 'hover here after break, before start code

startcode = RCREG 'This is the first byte received after the break

if startcode <> 0 then checkdmx 'do your own stuff here on a non-zero code

aminus = adresse_grada - 1 'address1 is my target address

for x = 1 to aminus 'set up a loop to count almost to the address
while RCIF = 0:WEND 'sit here until a byte is received
dummy = RCREG 'stash the byte somewhere unimportant
next x

newlevel1 = RCREG 'This is your target channel data
portA.2 = newlevel1 'i want dimming a LED on PORTA.2
RCSTA.7 = 0 'turn off the USART

goto checkdmx
return

skimask
- 5th March 2007, 14:11
Which command we have to use here "Pulsin" or " Hserin" ? u use here pulsin

counter = 1 'just a dummy variable
pulsin portB.1,0,counter --->>>>>>>'here I'm looking for the break signal<<<<<-------

'otherwise, a valid break was found and it's time to read the start code
dummy = RCREG 'clear out any garbage which may be in the USART
dummy = RCREG
SPBRG = 0
TXSTA.2 = 0 'brgh = 0
TXSTA.4 = 0
RCSTA.7 = 1
RCSTA.6 = 0 'setting 8 bit receive mode, no parity, etc
RCSTA.4 = 0 'check the datasheet to see what all these bits do
RCSTA.4 = 1 'now, the USART is on and ready to receive
while RCIF = 0:wend 'hover here after break, before start code
startcode = RCREG 'This is the first byte received after the break
if startcode <> 0 then checkdmx 'do your own stuff here on a non-zero code
aminus = adresse_grada - 1 'address1 is my target address
for x = 1 to aminus 'set up a loop to count almost to the address
while RCIF = 0:WEND 'sit here until a byte is received
dummy = RCREG 'stash the byte somewhere unimportant
next x
newlevel1 = RCREG 'This is your target channel data
portA.2 = newlevel1 'i want dimming a LED on PORTA.2
RCSTA.7 = 0 'turn off the USART

goto checkdmx
return

Just like the code above says...pulsin is used to find the 'break', and the code reads the serial port receive register directly...

syscoder
- 5th March 2007, 15:43
yes i now it.

but i want to know how to use "hsein" command to receive for dmxsginal

is everything true here in the code?can i use it for dimming a led ?

skimask
- 5th March 2007, 22:12
yes i now it.

but i want to know how to use "hsein" command to receive for dmxsginal

is everything true here in the code?can i use it for dimming a led ?

PBP manual, page 75-81. Whether or not the code is accurate or correct for DMX512...well, quite frankly, this is posted in the "MELabs PICBASICPro" forums, not the "DMX512 Questions" forum.

JEC
- 6th March 2007, 08:36
Heh...

That's my code snipped from a year or so ago.

It does work, and it's dead stable. But you need to understand that it's only a subroutine, called from the main program loop. You get to write the main loop.

The reason for not using HSERIN is that I found there was a slight startup delay when using the command. Using PULSIN to find the break, then calling HSERIN took too long and I was losing data. As you may know, the make-after-break signal can in some cases only be a few microseconds long.

At 20 MHz, you get 5 assembly instructions per microsecond, which may not be enough.

When I first wrote the code I didn't dig too deeply in PBP's internals to see what exactly was happening when HSERIN was invoked. But it seemed like an overhead issue within the command.

And note that the 'skip' function which can be used as part of HSERIN is only byte sized. So 'skip 254' works but 'skip 257' doesn't.

It was easier to access the registers directly and be assured that everything was being received properly.

Note that there's absolutely no guarantee that each and every packet coming down the wire is exclusively dimmer data.

JEC

DynamoBen
- 8th March 2007, 02:48
Like most things there is more than one way to accomplish a task. Last year I saw the post from JEC about DMX. While it was nice to hear that DMX was possible with PICBasic I really wanted something that was interrupt based.

After doing some research I found that all you need to do is look for a framing error, after which should be the start code (there may be several framing errors in a row). Over the last few days I have created the interrupt code snip below. While I haven't tested it exhaustively it seems to work.



DimmerCount VAR WORD ; Location in DMX string
DMXStartAddr VAR WORD ; DMX start address
DMXStartCode VAR BYTE ; DMX Start code (Dimmer=0)
Dummy VAR BYTE
DMX_State VAR BYTE ; Stage of DMX reception

Valid_Break CON 1
Valid_SC CON 2
Valid_Data CON 3

Disable

INTERRUPT_SUB:
IF OERR Then
CREN = 0
CREN = 1 ; Clear Overrun Errors
High Err_LED ; Notify user of overrun error
DMX_State=0
EndIF

IF FERR Then
FERR = 0
DMX_State=Valid_Break
Else
GoSub RX_DMX_Data
EndIF

Dummy=RCREG ; Empty UART of junk data
Resume

RX_DMX_Data:
IF DMX_State=Valid_Break Then
HSerin 20,NoData,[DMXStartCode] ; Start code of 0 = dimmer data

IF DMXStartCode=0 Then
DMX_State=Valid_SC
Else
High Err_LED ; Notify user of Error in Start Code
DMX_State=0
EndIF
EndIF

IF DMX_State=Valid_SC Then
For DimmerCount=0 TO DMXStartAddr; Count incoming data bytes (frames)
Dummy=RCREG ; Read unwanted values
Next DimmerCount
DMX_State=Valid_Data
EndIF

IF DMX_State=Valid_Data Then
HSerin 20,NoData,[STR DataBuffer\Number_Of_Channels]
DMX_State=0
EndIF

IF DMX_State=0 Then
Resume
EndIF

GoTo RX_DMX_Data

NoData:
DMX_State=0
Resume

Enable
End

JEC
- 8th March 2007, 03:07
Very elegant. Nice job, DynamoBen.

Darrel Taylor
- 8th March 2007, 04:18
Well, I can see some potential problems with that program.

So be ready for some more questions from programmer07, oops, I mean syscoder. :(
<br>

mister_e
- 8th March 2007, 04:24
Assuming it's a snip and a ISR... first observation, something like a L?CALL have to be change ;) but it's a first & fast observation.

DynamoBen
- 8th March 2007, 04:33
Its a first draft and I offer it up as-is so I make not warranties. ;) I'm open to suggestions or improvements.

BTW the question did seem familar.

syscoder
- 14th March 2007, 19:23
dear dynamoben thanks for your answer i will try it, is there anybody here that tryed it and working?
and how can i use it for 16f628 and 20 mhz osc and i will use only 3 led to dimmer them imean 3 chanel ?

syscoder
- 19th March 2007, 22:00
ok friends thank you for helping i will try to make it and will see if it is working then i will post code here cause i see there is many people here need help to receive dmx signal like me
i understand pulsin is for the break signal and hserin is to receive dmx

syscoder
- 21st March 2007, 10:50
hi friends i search in the forum and found many examples thanks. i have pic 16f876 , 20 mhz osc and 1 led ,i have dmx512 lighting desk too and i want to dimm a led on dmxadres 1 (0-255 to led intensty) but there is some problem on this code it is not working. i found this code in the forum and made it again for my pic but couldnt find the problem.can you look to my code and say what is my problem here?or you can send other example code to receive dmx ..

' PIC 16F876 - 20MHZ OSC

DEFINE OSC 20 ' 20 MHZ OSC
DEFINE HSER_TXSTA 24h ' Enable transmit
DEFINE HSER_RCSTA 90h ' Enable serial port & continuous receive
DEFINE HSER_SPBRG 4 ' 250 000 Baud @ 20MHz, 0.0%
DEFINE HSER_CLROERR 1 ' Clear overflow automatically

ASM
ERRORLEVEL -306, -302
ENDASM

ADCON0 = 0
ADCON1 = 7

counter var word
idleflag var word
dummy var word
RCIF VAR BYTE
startcode var word
aminus var word
adress var word
x var word
level1 var word
adress = 1 ' My Start Adress


checkdmx:
counter = 1 ' Dummy variable
pulsin portC.7,0,counter 'Here looking for the break signal
if counter = 0 then
idleflag = 1 'either no dmx , or break was too long to count
'return
endif
if counter < 40 then checkdmx ' watching for "break"
dummy = RCREG
dummy = RCREG
SPBRG = 0
TXSTA.2 = 0
TXSTA.4 = 0
RCSTA.7 = 1
RCSTA.6 = 0
RCSTA.4 = 0
RCSTA.4 = 1

while RCIF = 0: wend
startcode = RCREG 'firs byte after break
if startcode <> 0 then checkdmx
aminus = adress -1

for x = 1 to aminus
while RCIF = 0: wend
dummy = RCREG
next x

level1 = RCREG
portC.1 = level1 'i want to dimm led on port c.1
RCSTA.7 = 0

goto checkdmx
return

DynamoBen
- 21st March 2007, 14:24
*sigh* Why don't you read the responses to your numerous other posts on this topic elsewhere in the forum.

JEC
- 21st March 2007, 14:29
newlevel1 = RCREG 'This is your target channel data
portA.2 = newlevel1 'i want dimming a LED on PORTA.2
RCSTA.7 = 0 'turn off the USART

--------

Just curious - how do you expect a single pin, which at any given time can only have one of two discretes states, to represent all 255 possible values of DMX channel data?

Hint: Pulse Width Modulation is your friend. It's a way to time-average a bunch of discrete states (ones and zeros) to approximate various channel levels.

Search for 'PWM' and see what you find. Check out 'HPWM' in your PBP manual. You'll also find many, many examples of software controlled PWM buried in this forum.

And if you're really ambitious, google for Artistic License's 'Bit Angle Modulation' white paper. It's ingeniously simple and requires almost no work to code the routine in software.

JEC

EDIT: Didn't realize this same question had been replied to in two other threads in the past few hours. Sorry to repeat what everyone else has been saying re: PWM & R'ing the Friendly Manual.

skimask
- 21st March 2007, 15:38
*sigh* Why don't you read the responses to your numerous other posts on this topic elsewhere in the forum.

Yep, still done in this section too...

ShoKre
- 19th November 2007, 09:50
maybe that's way ?

this was i found searching, is well commented and easy to modify, i was wondering how much channel is possible to drive if I put out analog in and change pic to 18f452 with pll_en (40mhz)
or is it clever (or possible) to port (interrupt driven) triac drivers and dmx receiver into a asm interrupt handler subroutine in bas file, so i can touch other not critical pieces of code...

I know it is not easy to do, but can be interesting to everyone in this thread...

my programming knowledge i poor when talking about asm_interrupt but I will give a try..

http://epanorama.net/digipack/Digi_Pack/dmx_pack.asm