PDA

View Full Version : Decoding DMX with picbasic pro



fred.pacc
- 27th January 2006, 10:14
hello,

I have studied the posts concerning dmx with picbasic, I want to dimming a led on portC.5 on a 18F452. I try this basic code but unfortunately it doesn't run.

the dmx is converted by a driver SN75176 connected on pin 26 (RC.7/RX/DT). Please is someone can look my code for help me.

sorry for my bad english i'm french..... ;)
greating



'************************************************* ***************
'* Name : UNTITLED.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2006 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 26/01/2006 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
DEFINE OSC 16 ' for pic 18f452
DEFINE HSER_BAUD 250000
DEFINE HSER_CLROERR 1
ASM
ERRORLEVEL -306, -302
ENDASM

' 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

adresse_grada = 20

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

checkdmx:

counter = 1 'just a dummy variable
pulsin portc.7,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
pwm portc.5, newlevel1 ,100 'i want dimming a LED on PORTC.5
RCSTA.7 = 0 'turn off the USART

goto checkdmx
return

uludere72
- 27th January 2006, 15:25
http://www.melabs.com/resources/samples.htm

here is a program for dimmer may be helpful for you?



' Lamp dimmer
' ===========
'
' File name : LampDim.bas
' Company : Mister E
' Programmer : Steve Monfette
' Date : 23-12-2004
' Device : PIC12F675
'
'
' This program is use to dim intensity of an AC line load
' like lamp, motor and other. Developped for 60 Hz line.
'
' This allow to increase or decrease intensity.
' If the user doesn't held at least 0.5 sec:
' 1. "Increase" : we will set the output for full brightness
' 2. "Decrease" : we will turn off the output
'
'
' The software need :
' 1. A full wave signal from the AC line on GP4
'
' The software use :
' 1. TIMER1 overflow to check if pushbutton are hold for
' more than 0.5 Sec
' 2. Interrupt on GP4 (AcLine input) to synchronise Triac
'
'
' Device programming mode and hardware definition
' ===============================================
' Using Internal Clock, no clock out
' Enable Watch dog timer
' Disable MCLR pin
' Enable Power-up timer
' Enable Brown-out detect
'
@ __config _INTRC_OSC_NOCLKOUT & _WDT_ON & _MCLRE_OFF & _PWRTE_ON & _BODEN_ON
'
'
TRISIO = %11111011
OPTION_REG.7=0 ' Enable pull-ups
WPU=%00000011 ' Enable pull-ups on GP0, GP1
CMCON=7 ' Disable analog comparator
ANSEL=0 ' Disable analog converter

Pb_Inc var GPIO.0 ' Input for INCREMENT/ON push button
Pb_Dec var GPIO.1 ' Input for DECREMENT/OFF push button
Triac var GPIO.2 ' Output to TRIAC gate
ACLine var GPIO.4 ' Input for the FullWave rectify AC line
'
' Software definition
' ===================
'
'
'
MaxDelay var word
TriacDelay var Word
Debounce_AutoRepeatDelay var word
FullBright var bit
'
'
' Interrupts definition
' =====================
'
'
'
INTCON=%10001000 ' Enable interrupt on GPIO change
IOCB.4=1 ' Enable interrupt on GP4 change
PIE1.0=0 ' disable TMR1 overflow interrupt
T1CON=%00110100 ' Set TIMER1
' prescaler 1:8
' internal clock (Fosc/4) 1MHZ
' synchro internal
' we will use TIMER1 overflow
' $ffff * 8* (1/(4MHZ / 4)) = 0.524 Sec
ON INTERRUPT GOTO ACDetect
'
' Hardware and variable initialisation
' ====================================
'
'
Maxdelay=6000 ' Set Maximum delay (set to 8000 for 50Hz)
FullBright=0 ' disable Full Brightness flag
triac=0 ' disable Triac Gate
triacdelay=0 ' Set delay to minimum
gosub ResetTimer1 ' reset Timer1
'
' Main
' ====
' Get entry from user to Increment of Decrement intensity
'
'
start:
'
' Test Increment push button
' --------------------------
' If hold more than .5 Sec, increment triac gate delay by 500 uSec
' case else Full brightness at output
'
while Pb_inc=0
gosub TestTimer1 ' test status of TIMER1
while (Pb_inc==0) AND (PIR1.0==0) 'loop while holding push button
'and no TIMER1 overflow

wend

if PIR1.0==1 then ' If timer overflow (pushbutton hold for > 0.5 sec),
T1CON.0=0 ' disable TMR1
gosub Debounce_AutoRepeat
if (triacdelay<maxdelay) then="">
triacdelay=triacdelay+500 'increment Triac gate delay
else
triacdelay=maxdelay ' if triacDelay>MaxDelay,
fullbright=1 ' set the full brightness Flag
endif
else
triacdelay=maxdelay ' If pushButton was hold less than .5 sec
Fullbright=1 ' Set the full brightness flag
endif
wend
gosub ResetTimer1
'
' Test Decrement push button
' --------------------------
' If hold more than .5 Sec, increment triac gate delay by 500 uSec
' Case else, turn off output
'
while Pb_dec=0
gosub TestTimer1 ' Test status of TIMER1
while (Pb_dec==0) AND (PIR1.0==0) 'loop while holding push button
'and no TIMER1 overflow

wend

if PIR1.0==1 then ' If timer overflow (pushbutton hold for > 0.5 sec),
T1CON.0=0 ' disable TIMER1
gosub Debounce_AutoRepeat
if (triacdelay>0) then
Fullbright=0 ' Reset TRIAC always ON flag
triacdelay=triacdelay-500
endif
else
Fullbright=0 ' Reset TRIAC always ON flag
triacdelay=0
endif
wend
gosub ResetTimer1
goto start
'
'
' TestTimer1
' ----------
'
' Enable TIMER1 if :
' not enable and not in overflow
'
TestTimer1:
if (T1CON.0==0) AND (PIR1.0==0) then 'if TIMER1 not enable
'and TIMER1 not overflow
T1CON.0=1 'enable TIMER1
endif
return
'
'
' ResetTimer1
' -----------
'
' Subroutine to clear Timer1
' 1. Overflow flag
' 2. Disable Timer
' 3. Clear counter
'
ResetTimer1:
PIR1.0=0 'clear timer overflow
T1CON.0=0 'disable timer
TMR1L=$00 'clear counter
TMR1H=$00 '
return
'
'
' Debounce_AutoRepeat
' -------------------
'
' Subroutine to debounce push button.
' Also provide kind of auto-repeat when push button
' are held down.
'
' each delay = 20 mSec
' Use of PAUSEUS to be sure getting ACLine interrupt
'
Debounce_AutoRepeat:

for Debounce_AutoRepeatDelay=1 to 2000
pauseus 10
next
return
'
'
' ACDetect
' --------
'
' Interrupt routine called by ACLine (GP4) pin state change
'
disable
ACDetect:
if ACline==1 then ' Check for rising edge of AC signal
if triacdelay > 0 then
Triac=1 ' Activate TRIAC
if FullBright==0 then ' In case Brightness flag is not set
pauseus triacdelay ' do the selected delay
triac=0 ' Disable TRIAC
endif
else
triac=0
endif
endif
INTCON.0=0 ' Clear GPIF (interrupt on GP4 change)
resume
enable

</maxdelay)>

fred.pacc
- 27th January 2006, 17:12
Thanks for your answer,

My problem is more decoding DMX frame with picbasic , firstly I try to detect the break at the beginning of the dmx frame....

Thanks too for the link.

Greeting

fred.pacc
- 6th February 2006, 09:07
Hello,

I find a break
but i don't understand the RCIF fonction!!

I think that RCIF is my problem because he is always at 0 thus RCREG he is already full !!

How made for use the RCIF??


Greeting

JEC
- 6th February 2006, 17:29
Have you read the chapter about the USART in the datasheet? It takes a few tries for it all to sink in, usually.

If you're reading zeros, that means it's either empty, or it actually thinks a zero was received.

Depending on how you've structured your code, you may consider turning OFF the USART while you look for the break.

Once you've found the break signal, turn on the USART and clear it a few times, just to make sure it's ready for whatever data you're hoping to capture.

JEC

fred.pacc
- 6th February 2006, 19:47
Hello,
Can you say to me if my code is good for the definition of the variables (rcif)and if there are not other errors.

Thank you


'************************************************* ***************
'* Name : UNTITLED.BAS *
'* Author : [select VIEW...EDITOR OPTIONS] *
'* Notice : Copyright (c) 2006 [select VIEW...EDITOR OPTIONS] *
'* : All Rights Reserved *
'* Date : 26/01/2006 *
'* Version : 1.0 *
'* Notes : *
'* : *
'************************************************* ***************
DEFINE OSC 20 ' for pic 16f627
DEFINE HSER_BAUD 250000
DEFINE HSER_CLROERR 1

' 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

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

JEC
- 6th February 2006, 20:32
Hi -

From what I can tell, you've copied the code I posted a few months ago verbatim. And I know that the code is good.

What I posted was a *subroutine* which checks for DMX at a particular address.

But, if what you've posted is in fact your entire project, it seems that you haven't added anything to it all!

RCIF needs to be defined as whichever bit of the PIR register it actually is. Without it being defined, you code may return strange results. PIR1.5? Check your datasheet.

The PULSIN routine in my code looks for DMX on PORTB.1, which is the RX pin for the processor I used. Your first post from a few days ago mentions that you're hoping to receive on PORTC.7. But you haven't changed the PULSIN command to suit, so there's no chance it will work right out of the box.

You're using a different oscillator than I did. Have you confirmed that SPBRG and BRGH have the same values?

How do you know you're even finding the break signal? Have you added any flags or pin-twiddles which let you know where the program is at any given time?

One thing I did when I started writing the code was to insert something like this:

If break signal was received
high PORTB.FOO
pauseus 10
low PORTB.FOO
endif

Then, I could monitor the incoming signal and the FOO pin at the same time on my 'scope. Once I saw the FOO pin pulsing at exactly the proper position, I moved on to decoding other parts of the DMX stream. But if you don't catch the break signal properly, you don't have a chance at getting the rest of the stream.

There are so many inconsistencies here that it's hard to know where to start...

John

fred.pacc
- 10th February 2006, 06:57
Thank you JEC for your very detailed answer.
Indeed I am only at the beginning of my project.

My objective is to be able to decode DMX stream with a 16F627 or a 18Fxxx (what explains the differences of port RX between my different "post"), to use it for different functions not yet definite.


All that in PICBASIC if possible.
By the way I use an 20 MHz oscillator.
I wish to proceed by small steps

1) first, detect signal DMX, and light a LED if it is present on RX pin.

For example, if the break is detected.

2) Then, store DMX value on a preset address, (in my example address 20).


3) View this value in a way or another


4) using this value to dim a LED, if possible on a pin of the processor use.


Thank you for all your examples, but I am almost a beginner in programming, so I require also the good DEFINE of the variables used.

I will continue my experiments with these new councils.

So long.
Fred

skatnimit
- 11th September 2006, 14:34
hi fd

i tryed your code and i add like this .


newlevel1 = RCREG 'This is your target channel data

================================================== =

PWM portb.3 ,newlevel1 100 ' send pluse to led at
' portb.3 i use 16f628 xtal = 20 mhz

serout portb.2, t9600 [#newlevel1 10,13 ] ' send data to monitor
'on pc rs 232

'portA.2 = newlevel1 ' i don't use
================================================== =

RCSTA.7 = 0 'turn off the USART

-------------
and led is work diming from low to full bright when i add my volum from ch 1

but i have another problem it read data not same as my dmx transmit
like ch1 send data 200 but my code read out 100 and not sure it moveing
even i don't move volume..

ok if someone know how to fix please let me know..

GOD bless you ok have a goo day.