Hallo,
für ein Projekt versuche ich DMX Daten mit einem Atmega32A zu senden.
Ich verwende die Senderoutine von Ulrich Radig
(https://www.ulrichradig.de/home/index.php/avr/atmega8-experimentierboard/avr---dmx),
die für einen Atmega88 geschrieben ist und versuche sie für den
Atmega32A anzupassen.
Als Takt nutze ich einen 16MHz Quarz, weil der Atmega gleichzeitig noch
MIDI Daten per Software UART empfangen soll.
Auf einem Atmega328 funktioniert das senden, auf dem Atmega32A bekomme
ich es jedoch nicht zum laufen.
Folgendes habe ich angepasst:
Statt des UBRR0 Registers beschreibe ich das UBRRL Register mit der
berechneten Baudrate. Da im UBRRH Register sowieso 0 steht, beschreibe
ich es nicht.
UCSR0B habe ich zu UCSRB geändert, UCSR0C habe ich zu UCSRC geändert und
das URSEL Bit gesetzt, um ins UCSRC Regsiter zu schreiben.
Den Interruptvektor habe ich von USART_TX_vect zu USART_TXC_vect
geändert.
Aus dem UART kommt zwar etwas raus, allerdings scheinen es keine
verwertbaren DMX Daten zu sein.
Ich habe leider keinen Bus Decoder, nur eine DMX Lampe zum testen.
Die Fuses sind richtig gesetzt und der Atmega läuft nachweislich mit den
16MHz.
Nach mehreren Stunden vergeblicher Fehlersuche gehen mir die Ideen
aus...
Wo liegt der Fehler?
Code:
Hi
> Warum probierst du nicht einfach:> UBRRL = 3;
zum Schreiben muss erst UBRRH, dann UBRRL beschrieben werden. Oder
einfacher
in C: UBRR = ... .
Mfg Spess
"The UBRRH Register shares the same I/O location as the UCSRC Register.
Therefore some special consideration must be taken when accessing this
I/O location.
Accessing UBRRH/ UCSRC Registers
Write Access When doing a write access of this I/O location, the high
bit of the value written, the USART Reg- ister Select (URSEL) bit,
controls which one of the two registers that will be written. If URSEL
is zero during a write operation, the UBRRH value will be updated. If
URSEL is one, the UCSRC setting will be updated."
Dirk B. schrieb:> zur Sicherheit falls der Compiler UCSRC=UBRRH lesen sollte> UCSRC = (1 << URSEL) | (1<<USBS)|(1 << UCSZ1) (1 <<UCSZ0); //8n2> (auch nur als Test-Idee)
Danke, nun funktioniert es. ;-)
Ich frage mich allerdings, warum es im Original ohne gesetzte UCSZ0 und
UCSZ1 Bits funktioniert. Wenn diese nicht gesetzt sind, werden ja nur 5
Bit pro Zeichen übertragen.
Im 'Original' ist UCSCR ein konventionelles Register und die übliche
(und wohl auch sinnvolle) Vorgehensweise nur das zu ändern was gerade
geändert werden soll (also original-Wert|= bit) funktioniert, im
speziellen Register wird wirklich UBRH gelesen (0)
Vom Prinzip wäre für das Register ein esoterischer Compiler notwendig,
der je nach Benennung des Registers anderen Code erzeugt oder für das
Register 4 Makros (UBRH_r,UBRH_w,UCSRC_r,UCSRC_w) verwendet... kurz: als
zwangsläufige/unvermeidbare Fehlerquelle hat das Register durchaus
Unterhaltungscharakter, wenn Fehlersuche nicht auch etwas
Rätselcharakter hat dann sind die Stunden natürlich nur ärgerlich.
Müsste der Code nicht auch 1:1 auf einem Atmega32 (ohne A)
funktionieren? Die Register sind ja gleich.
Es kommen nur verwertbare Daten aus dem UART, wenn ich den Wert 255 oder
0 sende. Alle anderen Zwischenwerte sorgen dafür, dass die Lampe
entweder kein DMX Signal erkennt oder flackert.
Auch dieser Atmega läuft mit 16MHz (geprüft). Der MAX485 gibt auch
saubere Signale aus.
Ich kann es mir nicht erklären.
Luca E. schrieb:> Müsste der Code nicht auch 1:1 auf einem Atmega32 (ohne A)> funktionieren? Die Register sind ja gleich.
Eigentlich schon....vielleicht wäre das der Moment doch nicht nur eine
Lampe zum Thema was gesendet wird zu befragen: viele USB-TTL-Rs232
können auch 250k, bei hterm u.ä. Programmen lässt die Baudrate auch frei
einstellen (Senden dann natürlich nur einmal )
> Es kommen nur verwertbare Daten aus dem UART, wenn ich den Wert 255 oder> 0 sende. Alle anderen Zwischenwerte sorgen dafür, dass die Lampe> entweder kein DMX Signal erkennt oder flackert.
Flackern würde bedeuten bei jedem Durchlauf würde was anderes gesendet.
Wenn die Lampe und Leitung stabil sind würde als unregelmäßige
Fehlerquelle u.U. ein Watchdog-timer in Frage kommen der den µC
neustartet.
Zur Fehlereingrenzung evtl. auch erstmal mit dem Atmega32a die Lampe
prüfen: (dmx_buffer[1]=255 ist DMX-Kanal 2 )
if(dmx_channel_tx_count == 512)
-->if(dmx_channel_tx_count == 16)// nur Kanal 1-16 und
dmx_buffer[0]=16;
...
dmx_buffer[15]=255;// alle 16 Kanäle mit unterschiedlichen Daten testen
Scheint ein Hardwareproblem gewesen zu sein. Habe gerade die Platine für
das Projekt geätzt und bestückt und den Mega32 von meinem Prototypen auf
die Platine gesteckt.
Läuft einwandfrei.
Jetzt wundert mich allerdings, warum ich mit der selben Hardware
problemlos MIDI-Daten versenden konnte...
vielleicht der alte Trick für spannende Fehlersuchen:
kein Vcc--> der µC versorgt sich notdürftig über eine Datenleitung und
verhält sich unauffällig--> Dmx sendet 0[break],255,0,....,0[*254]
(ca.70%low-Anteil) --> Notversorgung bricht trotz Abblockkondensatoren
etc. zusammen --> manchmal reicht es um die Lampe noch (richtig) zu
informieren; wie die Lampe 0 empfangen hat bleibt deren Geheimnis (oder
so ähnlich)
Dirk B. schrieb:> kein Vcc--> der µC versorgt sich notdürftig über eine Datenleitung
Ich hatte auch die Versorgung im Verdacht, weil ich den Prototypen über
den USB Port gespeist hatte. Auf dem Oszi war die Versorgung absolut
sauber und auch mit externer Versorgung über das Labornetzteil hat es
nicht funktioniert.
Dirk B. schrieb:> Wie die Lampe 0 empfangen hat bleibt deren Geheimnis (oder> so ähnlich)
Der Laie staunt, der Fachmann wundert sich. ;-)
Dirk B. schrieb:> if(dmx_channel_tx_count == 512)> -->if(dmx_channel_tx_count == 16)// nur Kanal 1-16 und> dmx_buffer[0]=16;
Das muss nicht klappen, denn bei DMX müssen mindestens 24 Kanäle
gesendet werden, damit die minimale Break-to-Break Time nicht
unterschritten wird.
Das stört viele Empfänger nicht, aber einige doch:
https://en.wikipedia.org/wiki/DMX512#Timing
Matthias S. schrieb:> Dirk B. schrieb:>Leseproblem(Mathias WS.):[Zur Fehlereingrenzung evtl. auch erstmal mit dem
Atmega32a die Lampe
prüfen:]
>> if(dmx_channel_tx_count == 512)>> -->if(dmx_channel_tx_count == 16)// nur Kanal 1-16 und>> dmx_buffer[0]=16;>> Das muss nicht klappen, ...
Da hast du dich etwas zu spät zugeschaltet: es klappte bereits vorher
nicht.
Beim einmaligen senden brauchst du auch keine Angst um die
Break-to-Break Time haben ;-)
Dirk B. schrieb:> Da hast du dich etwas zu spät zugeschaltet: es klappte bereits vorher> nicht.
Schön und gut, mit dem Vorschlag hätte man sich aber eine weitere
Baustelle eröffnet und mögl. den grundlegenden Fehler verschüttet. Muss
ja nicht sein.
Matthias S. schrieb:> Dirk B. schrieb:>> Da hast du dich etwas zu spät zugeschaltet: es klappte bereits vorher>> nicht.>>[Beim einmaligen senden...]>> Schön und gut, mit dem Vorschlag hätte man sich aber eine weitere> Baustelle eröffnet und mögl. den grundlegenden Fehler verschüttet.
Nein man hätte mit einem Test keine weitere Baustelle eröffnet. In
Systemen in denen Forentexte bereits nur teilweise empfangen werden
können mag das natürlich anders sein.
Wenn beim System von Matthias S. die Baudrate nicht richtig eingestellt
ist und er deswegen von einem sog. "grundlegenden" Fehler fabulieren
muss, dann hat das System einfach keinen barrierefreien Zugang zu den
Texten auf die das System von Matthias S. reagiert.
Wenn Mathias S. ohne fremde Hilfe den verlinkten Wikipediartikel lesen
könnte und von
Matthias S. schrieb im Beitrag
> Das stört viele Empfänger nicht, aber einige doch:
einen(1) Empfänger nennen könnte, dann müsste er nicht über mögliche
sog. "grundlegende" Fehler spekulieren ;-)
Einfach mal einen konkreten Anfang ausprobieren ... Viel Glück