Benötige Hilfe mit meinem DMX-Sender (Mega8, Bascom)

Gast #886548
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
Gast #887404
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
Gast #887449
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
Gast #888298
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...
Gast #975496
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?)
Gast #1297437
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
Gast #1298374
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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren