Hallo liebe Community,
ich habe ein Problem mit dem Empfang von DMX in C...
Quellcode im Anhang :)
Das Programm soll folgendes tun:
Wenn der USART den Break erkennt (allso das FE Bit setzt)
sollen die ersten 10 Kanäle in ein Array geschrieben werden.
Anschließend soll im Hauptprogramm der 4.Kanal ausgewertet werden und
eine LED entweder an oder ausgeschaltet werden.
Das Problem:
Das Programm empfängt die ersten 10 Bytes, erkennt auch den Break, aber,
nachdem es diese 10 Bytes empfangen hat werden diese nicht mehr
aktualisiert...
Ich bin relativer Neuling in C und auch erst 16 Jahre alt und würde
gerne an diesem Problem weitertüfteln....
Da ich hier nicht weiterkomme, bitte ich um Unterstützung,da ich glaube
das ich einen Denkfehler in meinem Programm habe.
Vielen Dank für Eure Bemühungen im Voraus,
Christian
ist natürlich Quatsch. Denn dieser WErt ist immer wahr.
Was du oin wirklichkeit wolltest. Du wolltest ein Register befragen, ob
dort drinnen das bewusste FE Bit auf 1 ist oder nicht.
D.h. in der Abfrage muss sowohl der Registername als auch der Bitname
vorkommen.
Im Grunde genommen ist das nicht anders, als wie wenn du einen
Eingangspin abfrägst. Da schreibst du auch nicht
1
if(1<<PB0)
sondern
1
if(PINB&(1<<PB0))
also die Kombination aus: Nimm das Register PINB her und betrachte nur
das Bit PB0 - ist das 0 oder 1?
Und hier bei dir ist das nicht anders. Das FE Bit ist in einem
bestimmten Register beheimatet. Daher selbes Schema: Nimm den Inhalt des
bewussten Registers her, maskiere mit einem & alles weg bis auf das FE
Bit und dann erhebt sich die Frage: bleibt 0 übrig (dann war auch das
Bit 0) oder nicht (dann war das Bit 1)
Das ist vom Prinzip her da (UART) wie dort (Input-Pins) genau das
gleiche. Immer das gleiche Schema.
erstens ist dein Array nur 10 Elemente lang, ein array[10] existiert
daher gar nicht.
zweitens: wozu?
Du hast es hier mit DMX Daten zu tun und nicht mit Strings. DMX Daten
sind einfach nur Werte. Die werden nicht als String behandelt.
Weil ich gerade darauf gestossen bin und mich gefragt habe, ob man das
FE Bit wirklich selbst löschen muss.
Das ist was im Datanblatt zum FE Bit steht
1
• Bit 4 – FE: Frame Error
2
This bit is set if the next character in the receive buffer had a
3
Frame Error when received. that is, when the first stop bit of the
4
next character in the receive buffer is zero. This bit is valid until
5
the receive buffer (UDR) is read. The FE bit is zero when the stop bit
6
of received data is one. Always set this bit to zero when writing to UCSRA.
richte dein spezielles Augenmerk auf den Abschnitt
1
... This bit is valid until the receive buffer (UDR) is read. ...
Das heißt: das Bit ist nur solange korrekt, bis du UDR ausliest. Danach
gilt es nichts mehr (wahrscheinlich wird es von der Hardware mit dem
Lesen aus UDR zurück gesetzt).
Darauf folgt aber auch: Du musst das FE Bit auslesen BEVOR du dir das
Byte aus dem UDR holst. Nicht wie hier
1
...
2
ISR(USART_RX_vect)
3
{
4
5
Temp=UDR;
6
7
8
9
if(1<<FE)
10
{
11
...
erst hinterher.
Mehr Sorgfalt und weniger exzessive Leerzeilen, dafür aber konsistentere
Einrückung und bessere Variablennamen und du hast schon mal 50% deiner
jetzigen Probleme hinter dir gelassen.
> array[9] = '\0';
Das behebt jetzt zwar das Problem des Array Zugriffs out of bounds.
Aber die zweite Frage steht immer noch im Raum. Wozu?
Du hast hier sowieso keine Strings! DMX-Daten sind keine Strings und
werden auch nie welche sein. Du brauchst daher diese Operation hier
nicht. Alles was du tust ist, du zerstörst dir hier mutwillig Daten.
Gut, das mag dir egal sein, weil du dieses Byte (den Kanal 10) sowieso
nie brauchst. Trotzdem erhebt sich die Frage: warum zerstörst du es
dann?
Du agierst hier wie jemand, der eine Bushaltestelle zerstört, weil er
sowieso immer mit der Bahn fährt.
Sind eigentlich die 8 Mhz gesichert?
Hast du das ausprobiert, ob der µC auch wirklich mit 8Mhz läuft? Zb
indem man eine LED blinken lässt, abhängig von der Taktfrequenz.
Denn im Grunde machst auch du schon wieder den Kardinalfehler nummer 1.
Du versuchst als Anfänger ein Programm zu schreiben ohne einigermassen
vernünftige Debugmöglichkeiten zu haben. Kein Mensch weiß, ob deine UART
auch wirklich korrekt funktioniert oder nicht. Ob die Zeichen da korrekt
rein kommen oder nicht.
Anfänger gehen immer davon aus, dass das alles ja nicht so schwer sein
kann und das man ja wohl so ein Programm schreiben kann, so dass es auf
Anhieb funktioniert. Tja, wie alle anderen das eigentlich erwartet
haben, das funktioniert nun mal nicht.
Aber egal.
Sind die 8Mhz gesichert?
Mach dir halt mal in die ISR eine Anzeige per LED rein ob
* die ISR überhaupt aufgerufen wird
* das FE Bit jemals gesetzt wird
* die 10 Bytes jemals erreicht werden
PS: du MUSST das UDR in der ISR auslesen! Auch wenn du dann mit dem Byte
nichts machst, aber auslesen MUSST du es. Du kannst nicht einfach das
auslesen überspringen, weil irgendwelche Vorbedingungen nicht stimmen.
Ansonsten präsentiert dir nämlich die USART dieses Byte wieder und immer
wieder indem es die ISR auslöst.
Ja, die 8 MHz sind gesichert und Fuses sind richtig gesetzt.
Mir geht es nicht darum mal so auf die Schnelle ein Programm zu
schreiben,
sondern zu verstehen wieso mein lange überdachtes Programm nicht
funktioniert...
Außerdem bin ich eigentlich echt stolz auf das was ich da schon
geschrieben habe...
Nur irgendwo muss ein Denkfehler sein...
Karl Heinz schrieb:> Sind eigentlich die 8 Mhz gesichert?
Das ist wichtig, dass die stimmen! Denn sonst stimmt kein einziges
Timing. Und gerade bei UART ist alles eine Timingfrage.
Probier mal folgendes Programm aus.
1
#define F_CPU 8000000UL
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
6
intmain(void)
7
{
8
DDRD=0b11111111;
9
10
while(1){
11
12
PORTD|=(1<<PD7);
13
PORTD&=~(1<<PD2);
14
_delay_ms(500);
15
16
PORTD&=~(1<<PD2);
17
PORTD|=(1<<PD7);
18
_delay_ms(500);
19
}
20
}
deine LED müssen im Halbsekundentakt wechselseitig blinken. Wenn sie das
nicht tun und zb nur alle 4 Sekunden blinken, dann läuft dein µC nicht
mit 8Mhz.
Ich trau der Sache nicht. Das haben wir hier schon zu oft erlebt, dass
jemand Stein und Bein geschworen hat, dass seine Taktfrequenz stimmt.
Christian Karle schrieb:> sondern zu verstehen wieso mein lange überdachtes Programm nicht> funktioniert...
Das mag ja alles sein. Trotzdem hast du darauf vergessen, dir Gedanken
darüber zu machen, wie du die Dinge kontrollieren kannst.
Eine einsame LED, die am Ende einer langen Kette von Ereignissen an oder
ausgeht, und bei der alle Zwischenstufen in dieser Kette korrekt
ablaufen müssen, ist nun mal zu wenig, wenn es nicht funktioniert. Du
musst in der Lage sein, die Kontrolle viel feiner zu machen, in dem du
jede einzelne dieser Zwischenstufen kontrollieren kannst.
Man kann dazu LED nehmen, so ist das nicht. Aber man muss dabei schon
wissen was man tut. Und da liegt eben das Problem. Speziell bei UART ist
das nämlich nicht so einfach. Denn da erheben sich 2 Fragestellungen:
wird die ISR überhaupt ausgelöst - sprich: arbeitet die UART. Und die
2-te lautet: arbeitet sie richtig. Die erste kann man mit einer LED
einfach verifizieren. Die 2.te Frage ist nur mit einer LED schon
schwerer zu beantworten.
Also...meine LED blinkt im 0.5 sec Takt -> Fuses richtig gesetzt :)
meine USART wurde richtig Initialisiert. Habe alles beachtet...
Ich glaube auch dass, das Problem an der Anweisung arraycomplete=0;
in der Hauptschleife liegt. Generell glaube ich das an diesem Punkt
hakt...
P.S: Benutze den ATmega8515.
Christian Karle schrieb:> Also...meine LED blinkt im 0.5 sec Takt -> Fuses richtig gesetzt :)
gut.
Das ist schon mal wichtig.
Warum ich da so rumreite - weil ich auf der anderen Seite deines
Monitors sitze und weder sehen kann noch die Hardware zur Hand nehmen
kann, die du vor dir hast. Ich muss mich hier über den Zustand deines
Projekts orientieren mit nichts anderem als das was du im Posting
erzählst. Und natürlich nehme ich da mal die häufigsten Fehlerfälle
zuerst. 99% aller UART probleme sind immer die gleichen: die
Taktfrequenz ist nicht die, die der Programmierer glaubt.
> Ich glaube auch dass, das Problem an der Anweisung arraycomplete=0;> in der Hauptschleife liegt.
Nö.
Deine Hauptschleife ist zwar maximal-kompliziert geschrieben, aber sie
ist nicht falsch.
Das Problem liegt in der ISR.
Frage: wie sind deine LED angeschlossen. (du hast doch 2 LED, eine an
PD2 eine an PD7). Muss der Portpin auf 0 oder auf 1 gestellt werden,
damit die LED leuchtet?
Da fällt mir noch was ein
Wer sendet eigentlich?
> Anschließend soll im Hauptprogramm der 4.Kanal ausgewertet werden
4. Kanal
Bei welcher Zählweise? Beginnend bei 0 oder beginnend bei 1
Um die LED anzuschalten muss der Pin auf "Low" gesetzt werden
Habe deshalb den von Ihnen gelieferten C-Code wie folgt abgeändert :
#define F_CPU 8000000UL
#include <avr/io.h>
#include <util/delay.h>
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
int main(void)
{
DDRD = 0b11111111;
while(1){
cbi(PORTD,PD7);
_delay_ms( 500 );
sbi(PORTD,PD7);
_delay_ms( 500 );
}
}
Karl Heinz schrieb:> Da fällt mir noch was ein>> Wer sendet eigentlich?>>> Anschließend soll im Hauptprogramm der 4.Kanal ausgewertet werden>> 4. Kanal> Bei welcher Zählweise? Beginnend bei 0 oder beginnend bei 1
Hmm. da stimmt sowieso in deiner Zählerei etwas nicht.
Denn in deinem Array hast du in der ISR abgelegt
1
Index Bedeutung
2
--------------------
3
0 Wert der beim Break kam
4
1 DMX Startbyte, immer 0
5
2 Kanal 1
6
3 Kanal 2
7
4 Kanal 3
8
5 Kanal 4
9
6 Kanal 5
10
...
d.h. mit array[4] greifst du sowieso schon mal auf das falsche Byte zu,
wenn du am Wert von Kanal 4 interssiert bist.
Ich wollte mein Problem noch einmal genauer schildern. Auch in
Zusammenhang mit dem gesamten Programm :)
Tut mir leid :( Wenn jemand weis wie man den anderen Beitrag löschen
kann dann schreibt bitte kurz wie :)
Christian Karle schrieb:> Um die LED anzuschalten muss der Pin auf "Low" gesetzt werden
Gut.
Ich überleg mir mal was, wie wir die ISR pimpen können.
> Habe deshalb den von Ihnen gelieferten C-Code wie folgt abgeändert :
Hättest du nicht ändern brauchen.
Denn ob man zuerst einschaltet und dann ausschaltet oder zuerst
aussschaltet und dann einschaltet, ändert ja nichts daran, dass sich ein
Blinken ergibt. Hauptsache abwechselnd ein/aus mit der Betonung auf
abwechselnd.
Kann es sein, dass du einen haufen Vorübungen gespritzt hast?
> Habe deshalb den von Ihnen
Wir sind hier automatisch per du.
Ja, richtig :) Diese Tabelle habe ich schon die ganze Zeit im Kopf.
Mir ist bewusst das ich Kanal "3" auswerte wenn ich array[4] schreibe :)
Senden tut ein DMX-Pult mit 24 Kanälen :) Habe dort auch den Regler
Nummer 3 Benutzt, welcher Kanal 3 entspricht. Habe das auch schon mit
einem gekauften DMX-Gerät getestet :)
24 Kanäle. Gut zu wissen, denn da muss ich jetzt mal ein bischen
rechnen.
Wenn du nichts dagegen hast, dann machen wir das ohne großartiger
Vorüberlegung, sondern wir gehen systematisch vor. Mit einem einfachen
Programm, welches fast nichts kann und erweitern das dann Schritt für
Schritt, wobei jeder Schritt mit der LED kontrolliert wird.
Aber erst muss ich ein bischen rumrechnen. Denn eine LED zum debuggen
ist nicht viel und das DMX Zeugs ist zu schnell, als das wir da mit
statischen Anzeigen weiter kommen würden. Wir werden also das Heil im
Blinken suchen, wobei die Blinkfrequenz vom DMX getrieben wird.
Hmm...schwer zu sagen... Das Pult hat Funktionen wie z.B. Chaser,
Strobo, Fadetime usw. Ich denke das Ganze macht wahrscheinlich dann nur
Sinn wenn es dauerhaft sendet, oder liege ich da falsch ?
Karl Heinz schrieb:> Ach, eines noch.> Weisst du das. Sendet dein Sender ständig oder nur wenn sich Werte> verändern?
Hintergrund: Ich versuch auszurechnen, mit wievieln Break pro Sekunde
überhaupt zu rechnen ist.
Hintergrund: die erste Version soll erst mal anzeigen, ob überhaupt
regelmässig breaks daher kommen. Ich will das aber nicht mit LED
einschalten realisieren, weil das sonst zu schnell geht. Im Prinzip soll
bei jedem Break die LED umgeschaltet werden. Nur geht das bei 250kBaud
und 24 Kanälen viel zu schnell (ca 1000 mal pro Sekunde), so dass man
erst recht nichts sieht. D.h. wir schalten die LED nur bei jedem 500.ten
Break um.
Das funktioniert aber nur, wenn der Sender ständig sendet und nicht nur
bei Bedarf.
@ Christian Karle (christiankarle)
>Hmm...schwer zu sagen... Das Pult hat Funktionen wie z.B. Chaser,
DMX sendet duaerhaft mit einer einstellbaren Wiederholrate.
@ Karl Heinz (kbuchegg) (Moderator)
>Hintergrund: Ich versuch auszurechnen, mit wievieln Break pro Sekunde>überhaupt zu rechnen ist.
<100. Die Wiederholrate bei DMX geht theortisch zwar bis in den kHz
Bereich, praktisch eher nicht.
>Das funktioniert aber nur, wenn der Sender ständig sendet
Tut er.
wenn der Sender tatsächlich ständig sendet (was ich nicht weiß, weil ich
noch nie mit DMX zu tun hatte), dann sollte die LED ca alle halbe
Sekunde umschalten.
Meine Rechnung:
Wir haben 250kBaud, d.h. 250000 Bits pro Sekunde. Pro Byte sind 11
fällig (1 Startbit, 8 Datenbits, 2 Stoppbits), d.h. das sind rund 22700
Bytes pro Sekunde. Der Sender hat 24 Kanäle, also ist davon auszugehen
dass er auch nur diese 24 sendet und nicht alle 512. mit dem Startbyte
(und unter ignorieren des Break) sind das rund 900 komplette
DMX-Nachrichten pro Sekunde. Zwischen jeder kommt ein Break, also auch
rund 900 Breaks pro Sekunde. Wird die LED also nach jedem 500.ten Break
umgeschaltet, dann ist das ungefähr eine halbe Sekunde.
Das ill ich erst mal sehen. Vielleicht funkelt die LED, das wär mir noch
egal. Vielleicht blinkt sie auch langsamerm ist mir auch noch egal
(könnte ja sein, dass der Sender tatsächlich alle 512 Kanäle überträgt
und nicht nur 24). Aber wenn sich gar nichts tut, dann wäre das ziemlich
schlimm.
Falk Brunner schrieb:> @ Karl Heinz (kbuchegg) (Moderator)>>>Hintergrund: Ich versuch auszurechnen, mit wievieln Break pro Sekunde>>überhaupt zu rechnen ist.>> <100. Die Wiederholrate bei DMX geht theortisch zwar bis in den kHz> Bereich, praktisch eher nicht.
Ah. Danke Falk.
Rein rechnerisch lande ich bei ihm bei ca 900 kompletten 24-Kanal Frames
unter der Annahme von 0-Pausen zwischen den Frames (break erst mal
ignoriert - du weisst was ich meine)
>>Das funktioniert aber nur, wenn der Sender ständig sendet>> Tut er.
Wichtige Information für mich!
Danke.
Christian Karle schrieb:> Währe das hier eine Möglichkeit für die Verwirklichung der Idee ?
Im Prinzip - ja
Aber sieh dir meinen Code an. Diese ganze Komplikation mit Zähler in die
Hauptschleife und dort einen delay braucht man gar nicht.
Entweder der break kommt regelmässig, dann reicht es die LEDum- zu
schalten. oder er tut das nicht. Dann rettet dich aber auch der delay
nicht mehr.
Die meisten DMX-Sender arbeiten mit ~30 Hz Update Rate.
Dieser Wert stammt nicht von irgendeiner "offiziellen" Seite sondern aus
Erfahrung und dem rumspielen mit verschiedenen Pulten und USB-Geräten.
Wenn man keine extra "intelligente" oder schnelle über-hw hat, dann sind
die 30 Hz ziemlich konsistent. Ich denke das hat damit zu tun, dass in
preiswerteren DMX-Slaves eher schwache Controller am werkeln sind und
die sonst überfordert sind.
Karl Heinz schrieb:> Christian Karle schrieb:>> Währe das hier eine Möglichkeit für die Verwirklichung der Idee ?>> Im Prinzip - ja
Fast.
Du MUSST UDR auslesen!
Da führt kein Weg drann vorbei :-)
Max D. schrieb:> Die meisten DMX-Sender arbeiten mit ~30 Hz Update Rate.
Danke Max.
(Wer sagts denn. Wenn man es braucht, dann funktioniert das Forum
erstklassig)
Also auch mal mit
1
...
2
if(cnt==15)
3
...
probieren.
> Dieser Wert stammt nicht von irgendeiner "offiziellen" Seite sondern aus> Erfahrung und dem rumspielen mit verschiedenen Pulten und USB-Geräten.
Dann traue ich dieser Angabe mehr als dem was ich da unter optimal
Bedingungen worst case errechnet habe.
30 macht auch irgendwo Sinn. Der Empfänger muss ja mit den Daten auch
was machen und soooo schnell ändern sich Werte ja nicht, die ein Zuseher
ja auch noch aufnehmen können muss.
Christian, nimm aber bitte trotzdem mein Programm.
Hintergrund: Ich hab das bei mir parallel im AVR-Studio geladen und
werde das mit dir jetzt immer weiter ausbauen. Das ist einfacher, als
wenn ich von einer Version zur nächsten jedesmal deinen Code absuchen
muss, was du verändert hast.
Also, folgendes passiert:
Das Programm wird per ISP auf den uC übertragen.
Direkt nachdem es übertragen wurde fängt die LED im 0.5 sec. Takt an zu
blinken, ohne das der Controller mit dem DMX Pult verbunden wurde....
Nach dem Verbinden mit dem DMX-Pult passiert genau das Selbe...
Christian Karle schrieb:> Außerdem bin ich eigentlich echt stolz auf das was ich da schon> geschrieben habe...
Wenn du in deinem Leben mal richtig gut sein willst, dann sollte das die
letzte Aussage sein die du in dieser Richtung von dir gibst. Sonnst
kannst du dich gleich in die Reihen der Spinner einordnen, die von sich
selbst glauben die besten Programmieren auf Erden zu sein...
Christian Karle schrieb:> Also, folgendes passiert:>> Das Programm wird per ISP auf den uC übertragen.> Direkt nachdem es übertragen wurde fängt die LED im 0.5 sec. Takt an zu> blinken, ohne das der Controller mit dem DMX Pult verbunden wurde....> Nach dem Verbinden mit dem DMX-Pult passiert genau das Selbe...
welches Programm?
Deines oder meines
Wenn nichts angeschlossen ist, sollte da eigentlich nichts blinken.
Folgende Frage wenn der RS485 Konverter empfangen soll, muss dann nicht
nach Schaltplan PD2 auf "Low" sein? Oder liege ich in dieser Annahme
falsch?
-> Deine Programm
Äh, warte mal.
Habe ich zumindest übersehen.
PD2 muss aktiv auf 0 geszogen werden, damit der Treiber auf Empfang
gestellt wird. Keine Ahnung was der macht, wenn der Pin im Tri-State
ist.
1
#define F_CPU 8000000
2
3
#include<avr/io.h>
4
#include<avr/interrupt.h>
5
6
#define LED PD7
7
#define DATA_DIR PD2
8
9
voidUART_Initialisieren()
10
{
11
UBRRL=1;
12
UBRRH=0;
13
UCSRC=(1<<URSEL)|(3<<UCSZ0);
14
UCSRB=(1<<RXCIE)|(1<<RXEN);
15
}
16
17
18
intmain(void)
19
{
20
DDRD|=(1<<LED)|(1<<DATA_DIR);
21
22
PORTD&=~(1<<DATA_DIR);// Treiber auf Empfang stellen
Christian Karle schrieb:> Folgende Frage wenn der RS485 Konverter empfangen soll, muss dann nicht> nach Schaltplan PD2 auf "Low" sein?
Habs auch grade gemerkt, als ich den Schaltplan noch mal studiert habe
Christian Karle schrieb:> Hmm...Trotzdem blinkt sie immer noch mit 2 Hz...> Ohne das etwas angeschlossen ist...
Hmm.
Hast du noch eine freie LED (mit 220 Ohm Vorwiderstand), die du mal am
RxD Eingang vom Prozessor halten kannst. Wenn nichts angeschlossen ist,
sollte da eigentlich Ruhe herrschen.
Probehalber auch mal Pin 2 und 3 vom DMX Eingangsstecker verbinden.
Ich habe gerade noch ein ganz anderes Problem... Ich habe bemerkt das
sich mein Controller auf einmal nicht mehr über ISP programmieren
lässt...deswegen blinkt auch die LED...
Ich werde das beheben und mich dann sofort wieder melden :)
Max D. schrieb:> Sind es vlt 1,66 Hz ?> Dann hast du dir nämlich 50 Hz einstreuungen die die FEs triggern ....
Hmm.
Wo könnten die her kommen? Er hat ja 75176 und damit differentielle
Eingänge.
Spannungsversorgung?
Karl Heinz schrieb:> Max D. schrieb:>> Sind es vlt 1,66 Hz ?>> Dann hast du dir nämlich 50 Hz einstreuungen die die FEs triggern ....>> Hmm.> Wo könnten die her kommen? Er hat ja 75176 und damit differentielle> Eingänge.>> Spannungsversorgung?
Wenn er die Eingänge offen hat, dann können da auch differentielle
Einstrahlungen passieren (und die Treiber sind ja rel. empfindlich auf
differentielle spannungen, beim 75176 z.b. 200 mV). Das schafft man
locker wenn ein längeres Stück Kabel rumbaumelt.....
Also ich verstehe gerade die Welt nicht mehr... mein uC lässt sich nun
gar nicht mehr per ISP programmieren... egal was ich aufspiele-> Die LED
blinkt...
Liegt das an AVR Studio ?
@ Christian Karle (christiankarle)
>Also ich verstehe gerade die Welt nicht mehr... mein uC lässt sich nun>gar nicht mehr per ISP programmieren... egal was ich aufspiele-> Die LED>blinkt...
Falsches HEX-File ausgewählt?
>Liegt das an AVR Studio ?
Das Problem "liegt" meistens vor der Tastatur.
Nein, ich habe jetzt mehrere Male darauf geachtet das es das richtige
File ist und habe auch versch. Programme aufgespielt... Aber immer
blinkt die LED... Ich habe das ja bestimmt schon 500 mal gemacht und
blöd bin ich ja auch nicht...
Hmm.
Schon mal alles runtergefahren und neu gestartet?
Wenn gar nichts mehr hilft: Lötkolben auspacken und dem AVR zeigen (dem
PC zeigen schadet auch nicht). Dann spuren die wieder. Sozusagen mit
vorgehaltener Waffe sanft zur Mitarbeit überreden :-)
Im Ernst: irgendwo ein Kabel gerissen. Wackelkontakt, schlecht
Verbindung im Pfostenstecker?
Also habe es jetzt hinbekommen. Es lag tatsächlich an AVR Studio es muss
sich ein Softwarefehler eingeschlichen haben... nach der Neuinstallation
funktioniert nun wieder alles :)
Das Programm funktioniert auch :)
1.Die LED ist an.
2.Einstecken in das Pult -> LED fängt an zu blinken:)
Sie blinkt etwas langsamer als 2Hz aber sonst ist alles perfekt :)
Noch eine Detailfrage:
Wenn ich das UDR nicht auslese, würde es dann zu einem DATA OVERRUN
kommen ?
Christian Karle schrieb:> Also habe es jetzt hinbekommen. Es lag tatsächlich an AVR Studio es muss> sich ein Softwarefehler eingeschlichen haben... nach der Neuinstallation> funktioniert nun wieder alles :)>> Das Programm funktioniert auch :)>> 1.Die LED ist an.> 2.Einstecken in das Pult -> LED fängt an zu blinken:)>> Sie blinkt etwas langsamer als 2Hz aber sonst ist alles perfekt :)
Ah gut.
We have lift off
Jetzt wirds spannend. Bis jetzt wissen wir ja nur, dass laufend breaks
daher kommen. Die Frequenz 2Hz könnte passen. Auf jeden Fall langsam
genug, dass nicht jedes empfangene Byte einen Frame Error verursacht
haben kann, denn dann würde das viel schneller blinken. Das stimmt schon
mal zuversichtlich.
So, wie gehts jetzt weiter?
Jetzt holen wir uns mal die nächsten 10 Bytes nach einem Break in ein
Array und überprüfen, ob das erste davon 0 ist.
Leider haben wir keine andere Möglichkeit als von dem Wissen gebrauch zu
machen, dass das erste Byte 0 sein muss. Eine Ausgabe auf LCD wäre mir
persönlich lieber, aber es wird auch so gehen.
Mein Vorschlag.
Die Intention ist folgende:
Es werden nach einem break die nächsten Bytes in ein Array geschrieben.
Wenn geschrieben wird, wir auch geprüft, ob das erste Byte nach dem
Break ein 0 Byte ist. Das Problem das wir nämlich haben ist, dass wir
zwar momentan feststellen können, dass zwar Breaks da sind, aber wir
wissen nicht, ob wir mit der Baudrate daneben liegen, so dass der
Empfang gestört ist.
Aber wir wissen, dass das erste Byte nach einem Break 0 sein muss. Das
ist von DMX so vorgeschrieben und das ist etwas das man testen kann.
Die Erwartungshaltung im Programm ist folgende:
Da in der Hauptschleife die LED immer wieder abgeschaltet wird, gibt es
nur eine Möglichkeit, wie die LED leuchten kann. Nämlich wenn in der ISR
das erste Zeichen nach einem Break eine 0 ist. Nur dann wird die LED
eingeschaltet. Liegt die 0 nicht vor, oder fällt die Verbdinung aus,
dann sorgt die Hauptschleife dafür, dass die LED wieder ausgeht.
Testszenario ist daher:
DMX Stecker ziehen. Programm laufen lassen. Die LED muss aus sein.
Stecker einstecken. die LED muss leuchten.
Stecker wieder abziehen, die LED muss ausgehen.
theoretisch könnte es sein, dass bei eingestecktem DMX Stecker die LED
leicht flackert. Ich denke allerdings nicht, dass man das grossartig
sehen wird. Vielleicht ein ganz kurzer Flackerer hie und da.
1
#define F_CPU 8000000
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
#include<avr/interrupt.h>
6
7
#define LED PD7
8
#define DATA_DIR PD2
9
10
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
11
12
volatileuint8_tdmxData[10];
13
14
voidUART_Initialisieren()
15
{
16
UBRRL=1;
17
UBRRH=0;
18
UCSRC=(1<<URSEL)|(3<<UCSZ0);
19
UCSRB=(1<<RXCIE)|(1<<RXEN);
20
}
21
22
intmain(void)
23
{
24
DDRD|=(1<<LED)|(1<<DATA_DIR);
25
26
PORTD&=~(1<<DATA_DIR);// Treiber auf Empfang stellen
27
28
UART_Initialisieren();
29
30
sei();
31
while(1){
32
// Testled immer wieder abschalten, die ISR wird sie wieder einschalten
autsch:
Fehler.
Die LED ist genau anders rum.
Deine LED leuchtet ja bei einer 0 am Pin.
(Da war ich jetzt in Gedanken bei einem anderen Post)
Also. Erwartungshaltung ist:
Stecker abgezogen: LED brennt
Stecker eingesteckt: LED brennt nicht
Also praktischer Ablauf ist etwas anders :)
1: Stecker ist nicht eingesteckt-> LED ist an
2: Stecker ist eingesteckt-> LED flackert/Blinkt
Ich werde jetzt auch erst einmal versuchen den Programmtext
nachzuvollziehen :)
Christian Karle schrieb:> Also praktischer Ablauf ist etwas anders :)>> 1: Stecker ist nicht eingesteckt-> LED ist an
das ist ok. (Siehe mein letztes POsting)
> 2: Stecker ist eingesteckt-> LED flackert/Blinkt
hmm, wie stark ist das Flackern?
Ein bischen flackern ist ok. Mehr so ein Aufblitzen der LED als ein
regelmässiges Blinken.
Das die LED überhaupt ausgeht, ist schon mal ein gutes Zeichen, denn das
bedeutet, dass da 0-Bytes nach dem Break reinkommen.
Wenn du den delay_ms in der Hauptschleife vergrößerst, wird dann das
Flackern weniger?
PORTD&=~(1<<DATA_DIR);// Treiber auf Empfang stellen
27
28
UART_Initialisieren();
29
30
PORTD|=(1<<LED);
31
32
sei();
33
while(1){
34
}
35
}
36
37
ISR(USART_RX_vect)
38
{
39
staticuint8_tbyteCnt=0;
40
41
uint8_tframeError=(UCSRA&(1<<FE));
42
uint8_tnextByte=UDR;
43
44
if(frameError)
45
byteCnt=0;
46
47
else
48
{
49
if(byteCnt<ARRAY_SIZE(dmxData))
50
{
51
dmxData[byteCnt++]=nextByte;
52
53
if(dmxData[0]==0)
54
PORTD&=~(1<<LED);
55
else
56
PORTD|=(1<<LED);
57
}
58
}
59
}
ist eine andere Variante.
Die LED muss die ganze Zeit eingeschaltet bleiben. Keine Flackerer,
keine Helligkeitsschwankungen.
Allerdings ändert sich nichts, wenn du den Stecker abziehst, daher hab
ich das auch nicht für den ersten Test benutzt.
Ein Test könnte höchstens sein:
Alles abschalten, DMX Stecker abziehen. µC einschalten. Die LED muss aus
sein.
Dann den DMX Stecker anstecken. Die LED muss "sofort" leuchten. Ohne
Flackern.
Ziehst du den Stecker danach ab, dann ändert sich am LED Zustand nichts
mehr. Sie leuchtet weiter.
Wenn ich _delay_ms vergrößere dann nimmt die Frequenz des Blinkens der
LED ab. Ich würde behaupten es ist ein relativ regelmäßiges Blinken...
Ich würde es als regelmäßiges Aufblitzen bezeichnen (Das wäre ja auch in
Ordnung)
Den BREAK sollte man besser so detektieren. Anderenfalls kann man sich
durch einen Fehler im normalen Datenstrom kurzzeitig die Synchronisation
abschießen.
Ich habe das Programm noch erweitert um sicherzustellen dass, das Array
auch aktualisiert wird wenn mehr als 1000 Datenpakete empfangen wurden
wird
die LED ausgeschaltet :) Nur zur Überprüfung :)
1
#define F_CPU 8000000
2
3
#include<avr/io.h>
4
#include<util/delay.h>
5
#include<avr/interrupt.h>
6
7
#define LED PD7
8
#define DATA_DIR PD2
9
10
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
11
12
volatileuint8_tdmxData[10];
13
volatileintx=0;
14
15
voidUART_Initialisieren()
16
{
17
UBRRL=1;
18
UBRRH=0;
19
UCSRC=(1<<URSEL)|(3<<UCSZ0);
20
UCSRB=(1<<RXCIE)|(1<<RXEN);
21
}
22
23
intmain(void)
24
{
25
DDRD|=(1<<LED)|(1<<DATA_DIR);
26
27
PORTD&=~(1<<DATA_DIR);// Treiber auf Empfang stellen
Ok, Ich denke wir sind soweit, in die Vollen zu gehen.
Sieht wohl so aus, als ob die Synchronisierung klappt und auch die
empfangenen Daten korrekt sind.
Kanal 3 abfragen und die LED damit schalten
1
#define F_CPU 8000000
2
3
#include<avr/io.h>
4
#include<avr/interrupt.h>
5
6
#define LED PD7
7
#define DATA_DIR PD2
8
9
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
10
11
volatileuint8_tdmxData[10];
12
13
voidUART_Initialisieren()
14
{
15
UBRRL=1;
16
UBRRH=0;
17
UCSRC=(1<<URSEL)|(3<<UCSZ0);
18
UCSRB=(1<<RXCIE)|(1<<RXEN);
19
}
20
21
intmain(void)
22
{
23
DDRD|=(1<<LED)|(1<<DATA_DIR);
24
25
PORTD&=~(1<<DATA_DIR);// Treiber auf Empfang stellen
Christian Karle schrieb:> die LED ausgeschaltet :) Nur zur Überprüfung :)
:-)
Das ist IMHO die richtige Einstellung.
Wir angeln uns von einem Ziel zum nächsten vor. Auch wenn das manchmal
etwas umständlich sein mag. Aber: dadurch haben wir die Gewissheit, dass
die Dinge funktionieren, ehe wir die nächste Schicht drauf setzen.
In Summe geht das nämlich schneller, als einen Codehaufen hinzusetzen,
der dann nicht funktioniert und dann müssen wir erst recht wieder ganz
unten anfangen mit Debuggen.
Und, auch ganz wichtig. Wir überlegen uns, wie jede Erweiterung getestet
werden kann. Dazu ist es auch wichtig, vorab eine Erwartung zu haben.
D.h. ehe das Programm läuft, sollte man sich darüber im klaren sein, was
eigentlich passieren müsste.
Das Programm funktionier super :) Jetzt wurde ein Switch realisiert,
genau dass, das ich erreichen wollte :)
Die einzige Stelle im Programmtext die ich nicht verstehe ist
#define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
Ich würde mich noch über eine kleine Erklärung hierzu freuen :)
Mein Problem würde ich somit als gelöst ansehen, ab hier denke ich, kann
ich mir selbst über weitere Details und Funktionen Gedanken machen. Das
Tolle ist: Ich habe jetzt verstanden wie der DMX-Empfang abläuft und
kann endlich die Schritte bis zum fertigen Programm nachvollziehen :)
Vielen, vielen Dank Karl Heinz :)
Du hast mir sehr weitergeholfen. Ich bin Dir sehr dankbar das Du deine
Zeit opferst um mir Dein Wissen zu vermitteln. In der heutigen Zeit sind
Menschen wie du nur noch sehr selten, da normalerweise keiner mehr Zeit
und Lust hat sich mit Problemen anderer zu beschäftigen.
Ich schätze das wirklich sehr!
Und noch einmal ein fettes Dankeschön von mir :)
Christian Karle schrieb:> Das Programm funktionier super :) Jetzt wurde ein Switch realisiert,> genau dass, das ich erreichen wollte :)
Gut.
> Die einzige Stelle im Programmtext die ich nicht verstehe ist>> #define ARRAY_SIZE(x) (sizeof(x)/sizeof(*x))
sizeof liefert die Größe eines 'Objektes' in Bytes.
1
intdata[5];
sizeof(data) würde also die Größe des Arrays in Bytes liefern. da ein
int aus 2 Bytes besteht, wären das hier daher 10.
Ich will aber nicht wissen, wieviele Bytes das Array hat, sondern aus
wievielen Einträgen es besteht. Dazu muss ich im Prinzip die Größe des
Arrays durch die Größe eines Elements des Arrays dividieren. ein int hat
2 Bytes, also ist ein int Array, das 10 Bytes groß ist 10/2 gleich 5
Arrayelemente groß.
Wenn x ein Array bezeichnet, dann ist ein einzelnes element davon zb
x[0]. Oder kürzer geschrieben *x (wegen der Pointer/Array Dualität)
1
sizeof(data)/sizeof(data[0])
liefert daher, die Anzahl an Array Elementen, wenn data als Array
vorliegt. denn sizeof(data[0]) würde ja 2 ergeben, weil data[0] ja ein
einzelner int aus dem Array ist.
Oder eben, unter Ausnutzung der Pointer/Array Dualität
1
sizeof(data)/sizeof(*data)
(Du kannst aber auch die Array-Schreibweise benutzen. Ich bin eben
tippfaul :-)
> Mein Problem würde ich somit als gelöst ansehen, ab hier denke ich, kann> ich mir selbst über weitere Details und Funktionen Gedanken machen. Das> Tolle ist: Ich habe jetzt verstanden wie der DMX-Empfang abläuft und> kann endlich die Schritte bis zum fertigen Programm nachvollziehen :)
Super.
Dann würde ich sagen: Ziel erreicht.
Sowohl bei dir als auch bei mir.
Denn für mich ist das wichtigste, dass du verstehst, wie es
funktioniert. Das funktioniert bei weitem nicht so gut, wenn man einfach
nur fertigen Code hinklatscht.
Gib einem Mann einen Fisch und er hat einen Tag lang zu essen. Gib ihm
eine Angel und lehre ihn fischen und er hat sein Leben lang etwas zu
essen.
Ist es für Dich in Ordnung wenn ich das hier erreichte Ergebnis
veröffentlichen würde?
Das Ziel ist Menschen wie mir den Einstieg zu erleichtern.
Ich möchte mit dem hier erreichten eine einfache
Erklärung/Zusammenfassung für Anfänger schreiben und evtl. auf einer
Website veröffentlichen :)
Christian Karle schrieb:> Ist es für Dich in Ordnung wenn ich das hier erreichte Ergebnis> veröffentlichen würde?
Hab ich kein Problem damit.
Sonst wäre ich nicht hier :-)
Karl-Heinz schrub:
>Gib ihm eine Angel und lehre ihn fischen und er hat sein Leben lang etwas >zu
essen.
Gib ihm ein Buch über C und er ist nach 2 Wochen reif für die
Heilanstalt.
;-)
schnell fort hier
MfG Paul