Forum: Mikrocontroller und Digitale Elektronik Benötige Hilfe mit meinem DMX-Sender (Mega8, Bascom)


von Andre (Gast)


Lesenswert?

Servus zusammen,

ich arbeite zur Zeit an einem kleinen Beleuchtungsprojekt, und im Zuge 
dessen soll mein Mega8 DMX-Daten senden (und empfangen, aber das scheint 
zu funktionieren)

angelehnt an die bekannte und informative Seite von Hendrik stelle ich 
mir das Senden so vor wie im angehängten Code (etwas naiv, ich weis, 
aber wo ist der Fehler?)

der Zugehörige Empfänger wartet auf den "Receive complete" Interrupt, 
und ein "Frame Error" wird als Reset gewertet.

Der Empfänger tut aber leider gar nichts...

Eine Debug-LED bestätigt mir, das der DMX-Zyklus auf Sender-Seite 
permanent durchlaufen wird!

Sind die Pausen zu kurz? Geht das mit BASCOM generell nicht? (wieso?)

Ist es ein Problem wenn der URXC und der UTXC Interrupt gleichzeitig 
aktiviert sind? Das Gerät soll, über Dipschalter einstellbar, entweder 
DMX empfangen oder senden...

Fragen über Fragen, ich würde mich freuen wenn Ihr mir einen Tipp geben 
könnt!

Danke und Viele Grüße
  André

1
On Urxc Receive_isr
2
Enable Urxc
3
4
On Utxc Transmission_isr
5
Enable Utxc
6
7
dim Dmxstatus as byte : dmxstatus = 0
8
9
Ucsrc = &B10001110                                          '8N2
10
11
Enable Interrupts
12
13
udr = 0    ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren
14
15
'************************
16
'*                      *
17
'*   DMX-Senderoutine   *
18
'*                      *
19
'************************
20
21
Transmission_isr:
22
23
If Dmxstatus = 0 Then                                       'Bei "Sende Break"
24
   Waitus 9
25
   $baud = 90900                                            'niedrigere Baudrate
26
   Udr = 0                                                  'erzeugt Frameerror
27
   Dmxstatus = 1                                            '1 = "Sende Nullbyte"
28
End If
29
30
If Dmxstatus = 1 Then                                       'Bei "Sende Nullbyte"
31
   $baud = 250000                                           'normale Baudrate
32
   Waitus 9
33
   Udr = 0                                                  'sendet Nullbyte
34
   Dmxstatus = 2                                            '2 = Sende "Rot"
35
End If
36
37
If Dmxstatus = 2 Then                                       'Bei "Sende Rot"
38
   Waitus 9
39
   Udr = 128                                                'Roten Wert senden auf Kanal 1
40
   Dmxstatus = 3                                            '3 = sende Grün
41
End If
42
43
If Dmxstatus = 3 Then                                       'Bei "Sende Grün"
44
   Waitus 9
45
   Udr = 128                                                'Grünen Wert senden auf Kanal 2
46
   Dmxstatus = 4                                            '4 = sende Blau
47
End If
48
49
If Dmxstatus = 4 Then                                       'Bei "Sende Blau"
50
   Waitus 9
51
   Udr = 128                                                'Blauen Wert senden auf Kanal 3
52
   Dmxstatus = 5                                            '5 = sende Rest-Nuller
53
End If
54
55
If Dmxstatus > 4 And Dmxstatus < 50 Then                    'Nach Bluem Wert einige Nullen senden
56
   Waitus 9
57
   Udr = 0                                                  '0 senden
58
   Incr Dmxstatus                                           'erhöhen
59
End If
60
61
If Dmxstatus = 50 Then                                      'letzte null gesendet?
62
   Waitus 9
63
   Dmxstatus = 0                                            'Status auf "Sende Break" setzen
64
   Udr = 0
65
End If
66
67
Return

von Bylith (Gast)


Lesenswert?

Halt doch mal ein Oszilloskop an Deine Sendeleistung und schau, ob Dein 
DMX-Signal entsprechend den Vorgaben aussieht.

von Andre (Gast)


Lesenswert?

So, das mit dem Oszi hat geholfen, hab' so lange am Timing 'rumgebastelt 
bis es funktioniert hat! Danke!

von Matthias L. (Gast)


Lesenswert?

Ich habe zwar keine Ahnung von der "Programmiersprache" Bascom, aber ich 
kann mir nicht vorstellen, das bei solchen seriellen Ausgaben, wo es 
aufs Timing ankommt (DMX hat doch 250kBaud, oder?), sowas zur 
Realisierung des Timings geeignet ist:
>Waitus 9

Du hast es ja eigentlich schon zugegeben:
>hab' so lange am Timing 'rumgebastelt bis es funktioniert hat

von Bascommaherundguckda (Gast)


Lesenswert?

Och, Das bekommt man ziemlich genau hin. Im Simulator von BasCom kannst 
Du genau sehen und simulieren, wieviele Takte jeder Befehl benötigt. Und 
das Timing beim Senden macht ohnehin die UART. Wenn WAITUS zu ungenau 
ist, nimmst Du eben NOP - Assemblerbefehle zwischendurch (auf 1 Takt 
genau).

Wenn das Programm weiter ncihts machen soll, kannst Du (glaube ich) auch 
auf Interrupts ganz verzichten und einfach das Statusbit 
(Senden/Empfangen fertig) in der UART pollen, dann sparst Du Dir die 
Zeit zum Einstieg in die ISR

von Andre (Gast)


Lesenswert?

Jo, also das exakte Sendetiming (Stichwort 250 kbaud) macht der UART, 
hatt nur noch Probleme beim DMX-Timing mit Reset, interbyte-gap und so 
weiter, aber mit dem Oszi wars dann recht einfach...

von Andre (Gast)


Lesenswert?

Ach ja, und ich hab das Senden tatsächlich aus der ISR genommmen, 
sondern polle im normalen Programmdurchlauf auf das gesetzte 
"Transmission Complete"-Bit, dann kommen die anderen Sachen auch nciht 
zu kurz...

von Timo (Gast)


Lesenswert?

ich würde diesen Quelltext auch ganz gerne beutzen;-)

Ich arbeite momentan mit dem Tranciver von
http://www.hoelscher-hi.de/hendrik/light/dmxdimmer.htm

Ich habe schon versucht es zum laufen zu bekommen aber irgendwie will es 
nicht

1
$regfile = "M8515.dat"
2
$crystal = 8000000
3
4
5
Enable Utxc
6
7
8
Dim Dmxstatus As Byte : Dmxstatus = 0
9
Dim K1 As Byte
10
Dim K2 As Byte
11
Dim K3 As Byte
12
Dim K4 As Byte
13
Dim K5 As Byte
14
Dim K6 As Byte
15
Dim K7 As Byte
16
Dim K8 As Byte
17
18
19
20
Ucsrc = &B10001110                                          '8N2
21
22
Ddrd.7 = 1
23
Ddre.0 = 1
24
25
26
Portc = &B11111111
27
28
29
30
31
32
33
34
35
36
Enable Interrupts
37
38
Udr = 0                                                     ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren
39
40
'************************
41
'*                      *
42
'*   DMX-Senderoutine   *
43
'*                      *
44
'************************
45
46
Main:
47
48
K1 = Pinc.0
49
K2 = Pinc.1
50
K3 = Pinc.2
51
K4 = Pinc.3
52
K5 = Pinc.4
53
K6 = Pinc.5
54
55
56
K1 = K1 * 255
57
K2 = K2 * 255
58
K3 = K3 * 255
59
K4 = K4 * 255
60
K5 = K5 * 255
61
K6 = K6 * 255
62
63
64
65
Transmission_isr:
66
67
If Dmxstatus = 0 Then                                       'Bei "Sende Break"
68
   Waitus 9
69
   $baud = 9090                                             'niedrigere Baudrate
70
   Udr = 0                                                  'erzeugt Frameerror
71
   Dmxstatus = 1                                            '1 = "Sende Nullbyte"
72
End If
73
74
If Dmxstatus = 1 Then                                       'Bei "Sende Nullbyte"
75
   $baud = 25000                                            'normale Baudrate
76
   Waitus 9
77
   Udr = 0                                                  'sendet Nullbyte
78
   Dmxstatus = 2                                            '2 = Sende "Rot"
79
End If
80
81
If Dmxstatus = 2 Then                                       'Bei "Sende Rot"
82
   Waitus 9
83
   Udr = K1                                                 'Roten Wert senden auf Kanal 1
84
   Dmxstatus = 3                                            '3 = sende Grün
85
End If
86
87
If Dmxstatus = 3 Then                                       'Bei "Sende Grün"
88
   Waitus 9
89
   Udr = K2                                                 'Grünen Wert senden auf Kanal 2
90
   Dmxstatus = 4                                            '4 = sende Blau
91
End If
92
93
If Dmxstatus = 4 Then                                       'Bei "Sende Blau"
94
   Waitus 9
95
   Udr = K3                                                 'Blauen Wert senden auf Kanal 3
96
   Dmxstatus = 5                                            '5 = sende Rest-Nuller
97
End If
98
99
100
If Dmxstatus = 5 Then                                       'Bei "Sende Blau"
101
   Waitus 9
102
   Udr = K4                                                 'Blauen Wert senden auf Kanal 3
103
   Dmxstatus = 6                                            '5 = sende Rest-Nuller
104
End If
105
106
If Dmxstatus = 6 Then                                       'Bei "Sende Blau"
107
   Waitus 9
108
   Udr = K5                                                 'Blauen Wert senden auf Kanal 3
109
   Dmxstatus = 7                                            '5 = sende Rest-Nuller
110
End If
111
112
If Dmxstatus = 7 Then                                       'Bei "Sende Blau"
113
   Waitus 9
114
   Udr = K6                                                 'Blauen Wert senden auf Kanal 3
115
   Dmxstatus = 8                                            '5 = sende Rest-Nuller
116
End If
117
118
119
120
121
122
If Dmxstatus > 7 And Dmxstatus < 50 Then                    'Nach Bluem Wert einige Nullen senden
123
   Waitus 9
124
   Udr = 0                                                  '0 senden
125
   Dmxstatus = Dmxstatus + 1                                'erhöhen
126
End If
127
128
If Dmxstatus = 50 Then                                      'letzte null gesendet?
129
   Waitus 9
130
   Dmxstatus = 0                                            'Status auf "Sende Break" setzen
131
   Udr = 0
132
End If
133
134
135
Goto Main

Was Ist der fehler?
Ich habe leider kein Oszi aber der DMX prüfstecker mit den LED's drin 
leuchtet mit beiden farben (zu hohe frequenz?)

von Falk B. (falk)


Lesenswert?

@ Timo (Gast)

>Was Ist der fehler?

Lange Quelltexte gehören in den Anhang, siehe Netiquette.

MFG
Falk

von Timo (Gast)


Lesenswert?

Stimmt ^^

von Paul (Gast)


Lesenswert?

Richtig

...aber lesen kann man sie trotzdem...

von Timo (Gast)


Lesenswert?

Keiner da der mir helfen kann ?
 Andre kannst du sagen woran es bei dir gelegen hat ?

von Henry (Gast)


Lesenswert?

@ Timo (Gast)

Du hast bei der Baudrate eine 0 vergessen.

von testit (Gast)


Lesenswert?

er hat verschiedene Fehlerchen drinne ... zum Einen
setzt er in der ISR über $Baud die Baudrate, was
dazu führen kann, das sein obig gesetztes 8n2
aufgehoben wird, $baud konfiguriert normalerweise auf
8n1 ... daher verwendet man wenn man im Nachhinein
die Buadrate verändert einfach über Baud, ohne $.
Aber die Buadrate ändern ist find ich eh nicht so elegant,
ich habs so gelöst, dass ich um den FE auszulösen einfach
die UART deaktivierte und dann den Pin auf low setzte.
um dann den ersten Frame wieder zu senden einfach
UDR enablen und drauflos senden.
Die Slaves müssen um DMX konform zu laufen die einzelnen
Frames ohne Pause empfangen können, das Timing sollte daher
beim Senden unkritisch sein.
Ich habe bei mir einfach ein Array angelegt
DIM DMX_Bytes (255) as byte
und hab dann einfach

for x = 1 to 255
   printbin DMX_Bytes(x)
next

wobei DMX_Bytes(1) sollte 0 sein und gut ist

von testit (Gast)


Lesenswert?

so ein Käse ... nicht UDR wird enabled, sondern die
UART ... sorry

von Henne (Gast)


Lesenswert?

Hier noch von mir zum Ablauf ein paar Anmerkungen:

ISR vs. Polling:
Die ISR hat bei mir eine Ausführungszeit von wenigen us, ich verschwende 
keine Zeit mit Warten und halte die Zeiten recht genau ein.

Bei Polling würde entweder dauernd auf Platz im Sendepuffer gewartet 
werden oder das Timing wäre hinüber, da ich nur hin und wieder 
vorbeischaue, ob ich wieder senden darf.

Baudrate heruntersetzen:
Da Schleifen in ISRs böse sind (!) würde ein Timer für die Erzeugung des 
Breaks benötigt werden. Diesen spare ich durch Herabsetzen der Baudrate.

Interbyte Gap:
Sieht nicht schön aus und reduziert den Durchsatz - aber sonst spielen 
ein paar Gurken von Eurolite verrückt.

Der aktuelle Code hat schon ein paar Revisionen durch und Eure 
'Verbesserungen' waren bislang in der Vergangenheit auch mal eingebaut 
;-) Aber ich bin weiterhin gespannt.


PS: Bascom ist nicht gerade für seine Performance bekannt - es kann 
sein, dass es mit DMX etwas eng werden könnte. Meine Empfehlung ist 
daher C.


Viel Erfolg,
Hendrik

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.