Hallo,
im Moment sitze ich an einem kleinen DMX-Switchpack. Es besteht im
Wesentlichen aus einem Attiny2313, einem 75176 und deine
16MHz-Quarztoszillator. Die Startadresse habe ich im Quellcode fest auf
1 einstellt.
Den DMX-Code habe ich von Hendrik Hölscher übernommen.
Als DMX-Sender verwende ich ein JMS-USB-Interface und DMXControl.
Grundsätzlich funktioniert die Schaltung. Allerdings ist mir folgendes
aufgefallen.
Obwohl ich im Code eine 1 als Startadresse definiert habe, wird der
"erste Ausgang" des Attiny durch den zweiten Kanal im DMXControl
angesprochen.
Wird im DMXControl der Wert des ersten Kanals auf einen Wert > 0
geändert, reagiert der Attiny auf Änderungen der anderen Kanäle nicht
mehr. Erst wieder, wenn im DMXControl der Wert des ersten Kanals auf 0
gestellt wird.
Kennt jemand so ein Verhalten?
Im Netz habe ich bislang noch nichts gefunden.
Danke
matt
Matt B. schrieb:> Wird im DMXControl der Wert des ersten Kanals auf einen Wert > 0> geändert, reagiert der Attiny auf Änderungen der anderen Kanäle nicht> mehr. Erst wieder, wenn im DMXControl der Wert des ersten Kanals auf 0> gestellt wird.
Dann würde ich doch mal einen Blick in den Quellcode werfen und mit dem
Simulator ansehen, wo es denn hakt.
Matt B. schrieb:> DMX-Code habe ich von Hendrik Hölscher
Den kennt ja auch jeder und der hat auch nur einen veröffentlicht ...
:-(
> Die Startadresse habe ich im Quellcode fest auf 1 einstellt.
Ist das die interne Adresse oder die DMX Adresse?
Hintergrund:
Die DMX Adressierung beginnt grundsätzlich bei 1.
C Programmierer beginnen allerdings bei 0 zu zählen.
D.h. für einen C Programmierer trägt das erste Datenbyte einer Sequenz
die Nummer 0. Aus DMX Sicht ist das aber das Byte mit der Nummer 1.
Also ganz einfach im Code nachsehen, was mit dieser Einstellung gemacht
wird. Dann ist man schlauer.
Die von mir einstellte Startadresse ist tatsächlich '1'. Der Wert des
ersten Kanals wird im ersten Element des Arrays 'DmxRxField' abgelegt (
DmxRxField[0]).
Es ist so, dass der als Startkanal eingestellte Kanal als Startbyte
verwendet wird. Besitzt der einen Wert ungleich 0, erkennt der Empfänger
kein Startbyte und setzt "gDmxState = IDLE". Es werden kann keine
weiteren Kanäle eingelesen.
Aber im Code konnte ich bislang nichts finden, das so eine Funktion
erklärt.
Matt B. schrieb:> Hier noch die Codes zum DMX-Empfang.
Hmm.
Der Code sieht gut aus.
Wenn ich mich im Kopf nicht vertan habe, dann entspricht er der DMX
Spezifikation, in dem er die über die UART reinkommenden Bytes korrekt
verteilt.
> Es ist so, dass der als Startkanal eingestellte Kanal als Startbyte> verwendet wird.
Das entspricht dann aber nicht der DMX Spezifikation. Die verlangt
zwingend, dass nach dem langen Puls (der über den Frame Error
ausgewertet wird) erst mal ein Byte mit dem Wert 0 kommen muss.
> Besitzt der einen Wert ungleich 0, erkennt der Empfänger> kein Startbyte und setzt "gDmxState = IDLE". Es werden kann keine> weiteren Kanäle eingelesen.
Logisch. So ist das im Empfänger programmiert.
Im Moment deutet für mich vieles darauf hin, dass sich zwar dieser
Empfangscode an den DMX Standard hält, aber anscheinend dieses
DMXControl nicht.
Hast du eine Möglichkeit, dir die übergebenen Werte anzusehen (LCD,
Terminal?)
>> Aber im Code konnte ich bislang nichts finden, das so eine Funktion> erklärt.
Ich glaube nicht, dass der Fehler beim DMXControl liegt. Dann wäre ich
bestimmt nicht der einzige, der damit Probleme hat. Die aktuelle Version
von dem Programm habe ich übrigens installiert.
Wenn ich die Startadresse im Attiny z.B. auf 10 umstelle, dann wird der
10. Kanal als Startbyte und der 11. Kanal als tatsächlicher Startkanal
verwendet. Die Kanäle 1 bis 9 haben dann keinen Einfluss auf den
Attiny...
Ein Gerät um die vom Interface ausgegebenen Werte anzuzeigen kann ich
auf die Schnelle nicht auftreiben.
Für die Darstellung von Werte am Attiny habe ich insgesamt 10 LEDs zur
Verfügung. Darüber kann also auch 8-Bit-Werte (oder auch 10-Bit-Werte)
darstellen
Matt B. schrieb:> Ich glaube nicht, dass der Fehler beim DMXControl liegt. Dann wäre ich> bestimmt nicht der einzige, der damit Probleme hat. Die aktuelle Version> von dem Programm habe ich übrigens installiert.>> Wenn ich die Startadresse im Attiny z.B. auf 10 umstelle, dann wird der> 10. Kanal als Startbyte und der 11. Kanal als tatsächlicher Startkanal> verwendet. Die Kanäle 1 bis 9 haben dann keinen Einfluss auf den> Attiny...>> Ein Gerät um die vom Interface ausgegebenen Werte anzuzeigen kann ich> auf die Schnelle nicht auftreiben.
Dann sehe ich eigentlich nur noch die Möglichkeit, dass der Code für 2
hintereinander folgende Byte einen Frame Error bekommt. Er also das
0-Startbyte als weiteres 'Synchronisationsbyte'-Break ansieht, welches
über den generierten Frame Error alles weitere ins Rollen bringt,
wodurch sich die ganze Zählung verschiebt.
Nach dem "langen Puls bzw. Frame-Error" kommt laut DMX-Specs ein
Type-Byte, danach folgen die Daten. Type=0x00 bedeutet "Dimmer", der
verwendete code ist vermutlich dafür ausgelegt auch andere Typen
weiterzuverarbeiten:
Also: Frame Error - 1 Byte 0x00 für Dimmer - 1 bis 512 Bytes für die
Kanäle 1 bis 512.
Hoffe die Info hilft weiter!
PS.: und DMX-Control ist als Fehlerrquelle zu 99,9% auszuschließen ;-)
Karl Heinz schrieb:> Dann sehe ich eigentlich nur noch die Möglichkeit, dass der Code für 2> hintereinander folgende Byte einen Frame Error bekommt. Er also das> 0-Startbyte als weiteres 'Synchronisationsbyte'-Break ansieht, welches> über den generierten Frame Error alles weitere ins Rollen bringt,> wodurch sich die ganze Zählung verschiebt.
Sowas in der Art stelle ich mir auch vor...
Aber wie gehe das Problem an?
@Klaus:
Das von dir erwähnte Type-Byte ist doch das allgemeine Startbyte, das
immer den Wert 0 besitzt!?
Was mit gerade noch einfällt:
Ist es möglich, dass das DMXControl davon ausgeht, dass das Interface
selbstständig ein Startbyte vor die Datenbytes stellt, das JMS Interface
aber davon ausgeht, dass die vom DMX-Programm erhaltenen Bytes mit einem
Startbyte beginnen und die Datenbytes diesem folgen?
Dann wäre zumindest das Verhalten bei mir plausibel. Leider habe ich
momentan keine anderen DMX-Geräte da um das prüfen zu können...
Hallo matt!
In den Standards DMX512, DMX512/1990 und dem deutschen Standard nach DIN
56930-2 wird noch von Startbyte (=0x00) gesprochen.
Seit DMX512A, bzw. E1.11-2008, USITT DMX512-A gibt es zwei gravierende
Änderungen:
Mark-After-Break von 4 auf 8µs verlängert.
Start-Byte (=0x00) zu Start-Code erklärt:
0x00 dimmers and lighting fixtures
0x17 text packets
0xCF system information packets
0xCC RDM extension
grüße leo
@Klaus:
danke für die Info.
Gerade konnte ich den Attiny an einem ArtNet und einer anderen Software
betreiben. Der Fehler lag weiterhin vor. Deswegen gehe ich jetzt
tatsächlich von einem Fehler im Programm aus...
Edit:
Ich habe die ISR etwas angepasst. Die Abfrage auf das Startbyte habe ich
komplett weggelassen. Seither funktioniert es. Das Startbyte/Type-Byte
kommt bei mir irgendwie gar nicht an.
Hier die ISR:
1
ISR(USART_RX_vect)
2
{
3
staticuint16_tDmxCount;
4
uint8_tUSARTstate=UCSRA;//get state before data!
5
uint8_tDmxByte=UDR;//get data
6
uint8_tDmxState=gDmxState;//just load once from SRAM to increase speed
7
8
if(USARTstate&(1<<FE))//check for break
9
{
10
UCSRA&=~(1<<FE);//reset flag (necessary for simulation in AVR Studio)
11
DmxCount=0;//reset channel counter (count channels before start address)
Hallo matt,
liest du für Kanal 1 DmxRxField[0] oder DmxRxField[1] aus?
wenn ich die ISR richtig lese steht mit DmxAddress = 1 in
DmxRxField[0] .. DMX Slot 0 (=0x00 für Licht und Dimmer)
DmxRxField[1] .. DMX Slot 1 = Kanal 1
usw.
bei der letzten if-Abfrage sollte wohl
gDmxState = IDLE;
stehen?
Slot 0 nicht auszulesen halte ich für mutig, über kurz oder lang
wird sich RDM durchsetzen und dann blinkt dein Empfänger lustig vor
sich hin.
Grüße leo
Hallo Klaus,
deine Bedenken bezüglich RDM verstehe ich.
Bislang bin ich immer davon ausgegangen, dass in DmxRxField[0] der Wert
des ersten Datenbytes (1. Kanal) liegt. Das habe ich gerade auch nochmal
nachvollzogen. Das ist wirklich so. In DmxRxField[2] liegt
dementsprechend der Wert des zweiten Datenbytes (2. Kanal), usw.
Der Originalcode betrachtet aber tatsächlich das 1. Datenbyte als
Startbyte. Das ist das Symptom. Aber wie schon erwähnt, kann ich nicht
nachvollziehen, warum das so ist. Es scheint, als ob kein Startbyte
ausgesendet wird. Aber das kann ich mitlerweile ausschließen!
Braucht der UART eventuell nach einem Frame Error eine gewisse Zeit, bis
er wieder Daten einlesen kann und das Startbyte eventuell "zu schnell"
kommt?
In der letzten If-Abfrage muss tatsächlich
Hier mal noch die restlichen Informationen die eventuell interessant
sein könnten:
- externer 16MHz-Oszillator: laut Datenblatt bei 250k ein Fehler von
0,0%
- Fuse CKDIV8: deaktiviert
- Fuse SUT_CKSEL: EXTCLK_14CK_65MS
Edit:
Wird wenn ein Frame Error erkannt wurde ein Interrupt ausgelöst? Im
Datenblatt konnte ich nichts konkretes finden...
> Braucht der UART eventuell nach einem Frame Error eine gewisse Zeit,> bis er wieder Daten einlesen kann und das Startbyte eventuell> "zu schnell" kommt?
Das frage ich mich auch schon die ganze Zeit.
Kannst du mal verifizieren, ob tatsächlich 2 Bytes hintereinander mit
einem Frame-Error klassifiziert werden?
D.h. hier
1
if(USARTstate&(1<<FE))//check for break
2
{
3
UCSRA&=~(1<<FE);//reset flag (necessary for simulation in AVR Studio)
4
DmxCount=DmxAddress;//reset channel counter (count channels before start address)
5
gDmxState=BREAK;
6
}
mitzählen, bzw.
1
if(USARTstate&(1<<FE))//check for break
2
{
3
UCSRA&=~(1<<FE);//reset flag (necessary for simulation in AVR Studio)
4
DmxCount=DmxAddress;//reset channel counter (count channels before start address)
5
6
// .............
7
8
if(gDMXState==BREAK)
9
machwas
10
else
11
nimmszurück,allesok
12
13
// ..............
14
15
gDmxState=BREAK;
16
}
irgendeine Form von Kennung /zb. Fehler-LED einschalten
dazwischenhängen.
Bis lang ist das ja nur eine Hypothese, dass das Startbyte
fälschlicherweise als Break angesehen wird, auch wenn es IMHO sehr
plausibel ist und auch zum Fehlerbild passen würde.
UCSRA&=~(1<<FE);//reset flag (necessary for simulation in AVR Studio)
7
DmxCount=DmxAddress;//reset channel counter (count channels before start address)
8
gDmxState=BREAK;
9
}
Die Ansteuerung der "roten LED" habe ich in eine Funktion gepackt. Ist
der Parameter 1, wird die LED eingeschaltet, bei 0 entsprechend
ausgeschaltet.
Im Falle von zwei aufeinanderfolgenden Breaks wird die LED eingeschaltet
und bleibt dann dauerhaft an.
Aber die LED bleibt aus. Das heisst keine zwei aufeinanderfolgenden
Breaks.
Nochmal zu meiner vorherigen Frage (etwas ausführlicher):
Über die UART wird dem Controller ein Break gesendet. Wird durch den
damit verbundenen Frame Error der RX-Interrupt ausgelöst? Im Datenblatt
konnte ich nichts konkretes finden.
Falls nicht, dann wird der Break erst beim nächsten korrekt empfangenen
Byte vom Programm erkannt. Dieses korrekt empfangene Byte wäre in
unserem Fall das Start-/Type-Byte. In der If-Abfrage zur Prüfung des
Breaks wird dieses aber nicht ausgewertet. Erst das nächste empfangene
Byte wird als Start-/Type-Byte ausgewertet...
Könnte da was dran sein?
Matt B. schrieb:> Nochmal zu meiner vorherigen Frage (etwas ausführlicher):> Über die UART wird dem Controller ein Break gesendet. Wird durch den> damit verbundenen Frame Error der RX-Interrupt ausgelöst?
Müsste eigentlich.
Wenn dem nicht so wäre, wäre das extrem unlogisch.
> Könnte da was dran sein?
Ich kanns mir nicht recht vorstellen, dass in so einem Fall ein Receive
Interrupt nicht ausgelöst werden würde. Das würde Interrupts de facto
unbrauchbar machen, wenn da nur einwandfrei empfangene Bytes durchkommen
würden.
@ Matt B. (mattb)
>- externer 16MHz-Oszillator: laut Datenblatt bei 250k ein Fehler von>0,0%
Aber nur, wenn dein RC-Oszillator 0,0% Fehler hat. Die 0,0% beziehen
sich auf dein systemtisch Fehler durch Frequenzteilung. Bei einem
ganzzahligen Teiler ist der logischerweise 0 ;-)
Ich wäre da vorsichtig. Ein 8 oder 16 MHz Quarz(oszillator) bringt hier
auf jeden Fall Sicherheit.
>Wird wenn ein Frame Error erkannt wurde ein Interrupt ausgelöst?
Sicher.
>Falls nicht, dann wird der Break erst beim nächsten korrekt empfangenen>Byte vom Programm erkannt.
Nein. Der wird im fehlerhaft empfangenen BYte sofort erkannt.
>Breaks wird dieses aber nicht ausgewertet. Erst das nächste empfangene>Byte wird als Start-/Type-Byte ausgewertet...
DMX ist doch eigentlich nicht so schwer.
Schau dir mal das Beispiel an, das funktioniert sogar ohne explizite
statemachine.
Beitrag "DMX512 Empfänger mit Relaisansteuerung für 20 Kanäle"
@ Karl Heinz (kbuchegg) (Moderator)
>> Über die UART wird dem Controller ein Break gesendet. Wird durch den>> damit verbundenen Frame Error der RX-Interrupt ausgelöst?>Müsste eigentlich.
Wird auch.
>Wenn dem nicht so wäre, wäre das extrem unlogisch.
Eben.
Es ist ein Quarzoszillator verbaut, kein RC-Oszillator.
Den Quellcode von deinem DMX-Empfänger habe ich gerade vor mir:
Hier ein Ausschnitt aus der ISR:
1
if(status&(1<<FE)){// frame error
2
if(data==0){// break -> DMX Reset
3
dmx_channel=0;
4
dmx_base=(~PINB&0xFF)+1;// read dip switches which define DMX base address
5
if(~PIND&(1<<PD6))dmx_base+=256;
6
flag=1;// trigger update
7
}
8
else// rx error
9
dmx_channel++;
10
}
Verstehe ich das richtig, dass wenn ein Frame Error erkannt wurde, du
mit der Zeile
Hi,
ich hatte mal ein ähnliches Problem, welcher hier im Forum gelöst wurde.
War allerdings ASM. Vielleicht hilft es trotzdem weiter.
Beitrag "DMX Empfang mit Assembler Problem"
Gruß
Benedikt
Matt B. schrieb:> Verstehe ich das richtig, dass wenn ein Frame Error erkannt wurde, du> mit der Zeile>
1
>if(data==0)
2
>
> das Startbyte prüfst?
Die ganze Sequenz sieht ja so aus
1
if(status&(1<<FE)){// frame error
2
if(data==0){// break -> DMX Reset
3
dmx_channel=0;
4
dmx_base=(~PINB&0xFF)+1;// read dip switches which define DMX base address
5
if(~PIND&(1<<PD6))dmx_base+=256;
6
flag=1;// trigger update
7
}
8
else// rx error
9
dmx_channel++;
10
}
11
else{
12
index=dmx_channel-dmx_base;
13
if(index>=0&&index<dmx_size)
14
dmx_array[index]=data;
15
dmx_channel++;
16
}
Das übergehen des Startbytes ist implizit hier
1
index=dmx_channel-dmx_base;
2
if(index>=0&&index<dmx_size)
mit enthalten. Beim ersten Startbyte nach dem Break hat dmx_channel den
Wert 0, während dmx_base zb 1 ist. index wird zu -1 und damit wird das
Byte übersprungen.
Das hier
1
if(status&(1<<FE)){// frame error
2
if(data==0){// break -> DMX Reset
ist eigentlich der Normalfall. Denn so wie der Break erzeugt wird,
mündet er automatisch darin, dass sich an der UART ein Byte-Wert von 0
ergibt.
DmxAddress ist volatile definiert.
Kurze Frage zwischendurch:
Wenn ich RXD vom Attiny2313 hart auf Masse lege, dann sollte doch ein
Frame Error eintreten!?
Matt B. (mattb)
>Verstehe ich das richtig, dass wenn ein Frame Error erkannt wurde, du>mit der Zeile>if (data==0)>das Startbyte prüfst?
Nein. Schon mal den Kommentar angeschaut?
BREAK = FE && data==0
Das Startbyte interssiert diesen Empfänger gar nicht, es wird wie jedes
andere DMX-Byte einfach im Array abgelegt und fertig.
Hallo Matt,
Wenn du es mit Bascom versuchen möchtest schau mal hier "COOL-DMX.DE" in
der Bastelecke.
Dort veröffenliche ich so nach und nach meine Bauselprojekte.
MfG Dirk