mikrocontroller.net

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


Autor: Andre (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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é

On Urxc Receive_isr
Enable Urxc

On Utxc Transmission_isr
Enable Utxc

dim Dmxstatus as byte : dmxstatus = 0

Ucsrc = &B10001110                                          '8N2

Enable Interrupts

udr = 0    ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren

'************************
'*                      *
'*   DMX-Senderoutine   *
'*                      *
'************************

Transmission_isr:

If Dmxstatus = 0 Then                                       'Bei "Sende Break"
   Waitus 9
   $baud = 90900                                            'niedrigere Baudrate
   Udr = 0                                                  'erzeugt Frameerror
   Dmxstatus = 1                                            '1 = "Sende Nullbyte"
End If

If Dmxstatus = 1 Then                                       'Bei "Sende Nullbyte"
   $baud = 250000                                           'normale Baudrate
   Waitus 9
   Udr = 0                                                  'sendet Nullbyte
   Dmxstatus = 2                                            '2 = Sende "Rot"
End If

If Dmxstatus = 2 Then                                       'Bei "Sende Rot"
   Waitus 9
   Udr = 128                                                'Roten Wert senden auf Kanal 1
   Dmxstatus = 3                                            '3 = sende Grün
End If

If Dmxstatus = 3 Then                                       'Bei "Sende Grün"
   Waitus 9
   Udr = 128                                                'Grünen Wert senden auf Kanal 2
   Dmxstatus = 4                                            '4 = sende Blau
End If

If Dmxstatus = 4 Then                                       'Bei "Sende Blau"
   Waitus 9
   Udr = 128                                                'Blauen Wert senden auf Kanal 3
   Dmxstatus = 5                                            '5 = sende Rest-Nuller
End If

If Dmxstatus > 4 And Dmxstatus < 50 Then                    'Nach Bluem Wert einige Nullen senden
   Waitus 9
   Udr = 0                                                  '0 senden
   Incr Dmxstatus                                           'erhöhen
End If

If Dmxstatus = 50 Then                                      'letzte null gesendet?
   Waitus 9
   Dmxstatus = 0                                            'Status auf "Sende Break" setzen
   Udr = 0
End If

Return

Autor: Bylith (Gast)
Datum:

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

Autor: Andre (Gast)
Datum:

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

Autor: Matthias Lipinsky (lippy)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Bascommaherundguckda (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Andre (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Andre (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

$regfile = "M8515.dat"
$crystal = 8000000


Enable Utxc


Dim Dmxstatus As Byte : Dmxstatus = 0
Dim K1 As Byte
Dim K2 As Byte
Dim K3 As Byte
Dim K4 As Byte
Dim K5 As Byte
Dim K6 As Byte
Dim K7 As Byte
Dim K8 As Byte



Ucsrc = &B10001110                                          '8N2

Ddrd.7 = 1
Ddre.0 = 1


Portc = &B11111111









Enable Interrupts

Udr = 0                                                     ' Einmalige Ausgabe einer null um den ersten "Transmission Complete" Interrupt zu generieren

'************************
'*                      *
'*   DMX-Senderoutine   *
'*                      *
'************************

Main:

K1 = Pinc.0
K2 = Pinc.1
K3 = Pinc.2
K4 = Pinc.3
K5 = Pinc.4
K6 = Pinc.5


K1 = K1 * 255
K2 = K2 * 255
K3 = K3 * 255
K4 = K4 * 255
K5 = K5 * 255
K6 = K6 * 255



Transmission_isr:

If Dmxstatus = 0 Then                                       'Bei "Sende Break"
   Waitus 9
   $baud = 9090                                             'niedrigere Baudrate
   Udr = 0                                                  'erzeugt Frameerror
   Dmxstatus = 1                                            '1 = "Sende Nullbyte"
End If

If Dmxstatus = 1 Then                                       'Bei "Sende Nullbyte"
   $baud = 25000                                            'normale Baudrate
   Waitus 9
   Udr = 0                                                  'sendet Nullbyte
   Dmxstatus = 2                                            '2 = Sende "Rot"
End If

If Dmxstatus = 2 Then                                       'Bei "Sende Rot"
   Waitus 9
   Udr = K1                                                 'Roten Wert senden auf Kanal 1
   Dmxstatus = 3                                            '3 = sende Grün
End If

If Dmxstatus = 3 Then                                       'Bei "Sende Grün"
   Waitus 9
   Udr = K2                                                 'Grünen Wert senden auf Kanal 2
   Dmxstatus = 4                                            '4 = sende Blau
End If

If Dmxstatus = 4 Then                                       'Bei "Sende Blau"
   Waitus 9
   Udr = K3                                                 'Blauen Wert senden auf Kanal 3
   Dmxstatus = 5                                            '5 = sende Rest-Nuller
End If


If Dmxstatus = 5 Then                                       'Bei "Sende Blau"
   Waitus 9
   Udr = K4                                                 'Blauen Wert senden auf Kanal 3
   Dmxstatus = 6                                            '5 = sende Rest-Nuller
End If

If Dmxstatus = 6 Then                                       'Bei "Sende Blau"
   Waitus 9
   Udr = K5                                                 'Blauen Wert senden auf Kanal 3
   Dmxstatus = 7                                            '5 = sende Rest-Nuller
End If

If Dmxstatus = 7 Then                                       'Bei "Sende Blau"
   Waitus 9
   Udr = K6                                                 'Blauen Wert senden auf Kanal 3
   Dmxstatus = 8                                            '5 = sende Rest-Nuller
End If





If Dmxstatus > 7 And Dmxstatus < 50 Then                    'Nach Bluem Wert einige Nullen senden
   Waitus 9
   Udr = 0                                                  '0 senden
   Dmxstatus = Dmxstatus + 1                                'erhöhen
End If

If Dmxstatus = 50 Then                                      'letzte null gesendet?
   Waitus 9
   Dmxstatus = 0                                            'Status auf "Sende Break" setzen
   Udr = 0
End If


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?)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Timo (Gast)

>Was Ist der fehler?

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

MFG
Falk

Autor: Timo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Stimmt ^^

Autor: Paul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Richtig

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

Autor: Timo (Gast)
Datum:

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

Autor: Henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Timo (Gast)

Du hast bei der Baudrate eine 0 vergessen.

Autor: testit (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: testit (Gast)
Datum:

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

Autor: Henne (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.