Grüß euch alle,
mit einem ATmega8 lese ich über USART R232 eine Zahl aus einen String
ein, und übergebe diesen Wert an einen lokalen uint8_t- speicher, der
den Wert dann zu den OCR2 Register übergibt.
Die Übergabe zu den Speicher funktioniert, jedoch liegt am gewünschten
Ausgang für mein PWM Signal keine Spannung an.
Der Timer kommt auch nie in das Timer interrupt (habs getestet, mit der
usart_putc- methode)
Vermutlich habe ich die Zuweisung OCR2= aktueller_PWM_Wert; an der
falschen Stelle gemacht.
hardwaretechnisch ist die Zuweisung im IDLE- Modus.
Bei meiner funktionierenden Dimm-PWM- Schaltung habe ich die Zuweisung
im interrupt nach den ADC- Wandler gemacht, und es hat da wunderbar
funktioniert.
Hätte jemand einen Denkanstoß für mich?
EDIT_1: Über ein SPezielles FTDI Kabel bekommt der µC Spannung über USB.
Maximal kann er über das Kabel 450mA ziehen.
Glaubt ihr, dass das Leuchten von 3 LED's zzgl. der Stromverbrauch des
µC selber über diesen Wert kommt? (Netzspannungsquelle zurzeit nicht
verfügbar)
mfg,
TommyProg
Tho Wes schrieb:> Hätte jemand einen Denkanstoß für mich?
Wie immer.
Poste dein Programm, sonst kann keiner was sagen.
Generell: Bevor du dich aufmachst, dein Programm zu beschreiben und
darüber zu fachsimpeln, was du deiner Meinung nach alles programmiert
hast oder nicht programmiert hast, zeig den Code! Das ist für dich
einfacher und für uns auch.
Grüß Dich, Karl Heinz,
bereits bei anderen Projekten habe ich meinen Code gepostet, jedoch nur
hier nicht.
Dennoch ist es einfacher, das stimmt. Somit ist der Code im Anhang.
Die Zeile, wo ich einen Wert dem OCR2 zuweise, ist kritisch.
->Die BAUD- Berechnung ist die aus dem Tutorial.
Mfg,
tommyProg
Tho Wes schrieb:> ->Die BAUD- Berechnung ist die aus dem Tutorial.
Na. ja.
Wenn die Baudrate nicht korrekt wäre, dann würde gar nichts gehen.
Aber:
Du hast ja eine UART!
Es ist nicht verboten, dass der Mega während der Entwicklungszeit auch
so Dinge wie Statusmeldungen an den PC schickt, in denen er mitteilt was
er tut und warum er es tut. Als Programmierer sitzt du dann am PC vor
deinem Terminalprogramm und analysierst diese Statusmeldungen und ziehst
daraus deine Schlüsse.
Zb. ist es nicht verboten, dass der Mega gleich mal jedes Zeichen, das
über die Serielle reinkommt wieder zurückschickt oder dass er in den
einzelnen States der Statemaschine eine entsprechende (kurze!) Meldung
per UART rausgibt (ausser vielleicht im Idle State 'TueNichts')
PS:
So was
1
if((usart_empfangspuffer[2]>47)&&(usart_empfangspuffer[2]<58))//wenn an der zweiten Stelle eine Zahl vorkommt
ist unklug. Wenn du wissen willst, ob das Zeichen ein Ziffernzeichen
ist, dann ist das wirklich dümmste was du tun kannst, den ASCII Code als
Dezimalzahl hinzuschreiben. Als Hex-Zahl würde es gerade noch so lala
gehen, aber viel einfacher ist
1
if(usart_empfangspuffer[2]>='0'&&
2
usart_empfangspuffer[2]<='9')
Da kann jetzt auch ein Blinder greifen, worum es hier geht.
Oder überhaupt gleich
1
if(isdigit(usart_empfangspuffer[2]))
dann brauchst du auch deine Kommentare nicht mehr, weil im Code sichtabr
ist, was da passieren soll. Wenn irgendwie möglich, willst du deinen
Code so formulieren, dass der Code sein eigener Kommentar ist. Du WILLST
nach Möglichkeit alles im Code selber ausdrücken und nicht noch
zusätzllich einen Kommentar haben, der einem eine Codezeile erklären
muss.
Nichts gegen sprechende Variablen- und Funktionsnamen. Aber deine sind
schon ein bischen zu lang. Da siehst du vor lauter 'Zeichen-Rauschen'
das Wesentliche nicht mehr.
Karl Heinz schrieb:> dann brauchst du auch deine Kommentare nicht mehr, weil im Code sichtabr> ist, was da passieren soll. Wenn irgendwie möglich, willst du deinen> Code so formulieren, dass der Code sein eigener Kommentar ist. Du WILLST> nach Möglichkeit alles im Code selber ausdrücken und nicht noch> zusätzllich einen Kommentar haben, der einem eine Codezeile erklären> muss.
Das zum Beispiel
1
caseTUE_NICHTS:// Im fall tue nichts (IDLE- Modus)
2
_delay_ms(1);
3
if(++counter==250)
4
{//toggle die Gelbe LED fuer 250ms
5
PORTB^=GRUENE_LED_AN;
6
counter=0;
7
}
sind völlig sinnlose Kommentare.
Da steht 'Im Fall tue nichts'.
Ah geh. Das hätte ich jetzt nicht gedacht! Und ich hab mich schon
gewundert, warum der case 'TUE_NICHTS' heisst.
Sinnloser Kommetar. Der erzählt mir nichts, was ich nicht auch im Code
sehen würde.
Der hier
1
{//toggle die Gelbe LED fuer 250ms
ist sogar falsch. Denn wie im Code sichtbar ist
1
PORTB^=GRUENE_LED_AN;
wird eben nicht die gelbe LED getoggelt, sondern die grüne. Und das das
alle 250ms passiert, kann man auch in 5 Sekunden aus dem Konstrukt
1
_delay_ms(1);
2
if(++counter==250)
3
{
4
..
5
counter=0;
6
}
ablesen.
Legst du die Zeit dann irgendwann mal in ein #define
1
#define BLINK_TIME_MS 200
2
3
....
4
5
caseTUE_NICHTS:// Im fall tue nichts (IDLE- Modus)
6
_delay_ms(1);
7
if(++counter==BLINK_TIME_MS)
8
{//toggle die Gelbe LED fuer 250ms
9
PORTB^=GRUENE_LED_AN;
10
counter=0;
11
}
dann stimmt noch nicht mal die Zeitnangabe im Kommentar.
Auch das: ein sinnloser Kommentar, der mir nichts erzählt, was ich nicht
auch im Code sehen würde und in diesem Fall sogar falsch ist. So einen
Kommentar ignoriert man am besten, wobei sich dann natürlich die Frage
stellt: Warum steht er dann überhaupt dort?
> Aber:> Du hast ja eine UART!> Es ist nicht verboten, dass der Mega während der Entwicklungszeit auch> so Dinge wie Statusmeldungen an den PC schickt, in denen er mitteilt was> er tut und warum er es tut. Als Programmierer sitzt du dann am PC vor> deinem Terminalprogramm und analysierst diese Statusmeldungen und ziehst> daraus deine Schlüsse.
Stimmt, deshalb habe ich zu Testzwecken auch immer einen beliebigen
Buchstaben zurücksenden lassen.
> PS:> So was>
> ist unklug. Wenn du wissen willst, ob das Zeichen ein Ziffernzeichen> ist, dann ist das wirklich dümmste was du tun kannst, den ASCII Code als> Dezimalzahl hinzuschreiben. Als Hex-Zahl würde es gerade noch so lala> gehen, aber viel einfacher ist>
1
>if(usart_empfangspuffer[2]>='0'&&
2
>usart_empfangspuffer[2]<='9')
3
>
> Da kann jetzt auch ein Blinder greifen, worum es hier geht.> Oder überhaupt gleich>
1
>if(isdigit(usart_empfangspuffer[2]))
2
>
Oh, danke dir, wusste nicht, dass es sowas schon fertig gibt.
Wie ist das eigentlich mit dem Register, die PWM (phase-correct) will da
garnicht hinhauen. Ist die Zuweisung an der richtigen stelle?
//die restlichen Zustände auch hier mit einfügen, weil sonst der Compieler meckert! Die Funktionen werden aber generell im Mainprogramm abgearbeitet
2
casePRUEFE_COMMAND:
3
break;
meckert denn der Compiler?
Mir scheint, du weißt nicht, dass es in einem switch-case auf ein
'default' gibt, welches alle nicht von einem case angenommenen Fälle
abdeckt.
Tho Wes schrieb:> Wie ist das eigentlich mit dem Register, die PWM (phase-correct) will da> garnicht hinhauen. Ist die Zuweisung an der richtigen stelle?
Der Mega wird sich sicher nicht wehren, wenn du einen Wert ins OCR
Register schreibst.
Die Frage ist: kommt das Programm überhaupt an diese Stelle?
Das kann ich aber nicht sagen, weil ich nicht sehe bzw. nachvollziehen
kann, was eigentlich über die Serielle SChnittstelle reinkommt.
Und an dieser Stelle kommt wieder deine Debug-Möglichkeit durch Ausgabe
von 'STatus-Meldungen' über die UART ins Spiel. Damit könnte man das
feststellen.
> meckert denn der Compiler?
Tut er, wenn nicht alle Cases abgedeckt sind.
> Mir scheint, du weißt nicht, dass es in einem switch-case auf ein> 'default' gibt, welches alle nicht von einem case angenommenen Fälle> abdeckt.
Echt? Mir nicht, sonst hätte ich es bei der Buchstaben- Überprüfung auch
nicht eingebaut.
> Womit wir wieder bei einem recht zentralen Punkt sind: Kenne deine> Programmiersprache und welche Möglichkeiten es gibt!
Klingt vernünftig, wenn du mir noch einige monate bis jahre gibst, bis
ich mehr Erfahrung gesammelt habe.
--> Statusmeldungen: Auf jeden Fall kann der "aktuelle_pwm_wert" mit
einen Wert beschrieben, als auch ausgelesen werden. Er Springt aber
nicht in das Timer- Interrupt rein.
Mfg,
tommyProg
Karl Heinz schrieb:> Und an dieser Stelle kommt wieder deine Debug-Möglichkeit durch Ausgabe> von 'STatus-Meldungen' über die UART ins Spiel. Damit könnte man das> feststellen.
Ich würde mir halt mal hier
1
caseUEBERSETZE_BEFEHL://Beim Uebersetzen des Befehls
2
{//
3
charsign=usart_empfangspuffer[1];
4
5
uart_putc('*');
6
uart_putc(sign);
7
8
switch(sign)
9
...
eine Rückmeldung einbauen um zu sehen, welches Kommando der Mega
eigentlich 'sieht' (und die sinnlosen Kommentare wieder rauswefen)
Und dann eben genauso in den anderen Zuständen mit einem anderen
Sonderzeichen, damit ich im Terminal sehe, wie die Statemaschine von
einem Zustand in den nächsten geht. Kostet ja nichts, da erst mal ein
1
caseZWISCHENZUSTAND_PWM_1:
2
3
usart_putc('#');
4
usart_putc(usart_empfangspuffer[2]);
5
6
if(isdigit(usart_empfangspuffer[2]))
7
{
8
zwischenzustand_array[0]=usart_empfangspuffer[2];
9
PROGRAMM_ZUSTAND=ZWISCHENZUSTAND_PWM_2;
10
}
11
else
12
PROGRAMM_ZUSTAND=SENDE_AKTUELLEN_PWM_WERT_AN_PC;
13
break;
einzubauen.
Eventuell mit einem #ifdef gesichert
1
...
2
#define DEBUG_PWM
3
...
4
5
caseZWISCHENZUSTAND_PWM_1:
6
7
#ifdef DEBUG_PWM
8
usart_putc('#');
9
usart_putc(usart_empfangspuffer[2]);
10
#endif
11
if(isdigit(usart_empfangspuffer[2]))
12
{
13
zwischenzustand_array[0]=usart_empfangspuffer[2];
14
PROGRAMM_ZUSTAND=ZWISCHENZUSTAND_PWM_2;
15
}
16
else
17
PROGRAMM_ZUSTAND=SENDE_AKTUELLEN_PWM_WERT_AN_PC;
18
break;
dann setzt man, wenn alles fertig ist, die Zeile
1
...
2
// #define DEBUG_PWM
3
...
unter Kommentar und die beiden usart_putc werden dann nicht mehr
mitcompiliert.
Kommt mir was spanisch vor, dann entferne ich den Kommentar wieder, die
beiden usart_putc werden wieder mitcompiliert und ich kann erneut am
Terminal mitlesen, was da im µC passiert.
Tho Wes schrieb:>> meckert denn der Compiler?>> Tut er, wenn nicht alle Cases abgedeckt sind.
Das glaub ich nicht. Denn der Compiler kann prinzipiell überhaupt nicht
wissen, welche Werte die Variable hier
1
switch(a)
überhaupt annehmen kann.
> einen Wert beschrieben, als auch ausgelesen werden. Er Springt aber> nicht in das Timer- Interrupt rein.
dann muss man sich die Konfiguration vom Timer ansehen.
Dazu ist es zb hilfreich, das Komplettprogramm mal zur Seite zu legen,
mit all seinen unübersichtlichen Verwicklungen, und sich zb ein
Testprojekt anzulegen, in dem man nur diesen einen Punkt testet.
vom Prinzip her fertig. Mehr brauchts dazu nicht. Und an diesem
einfachen überschaubarem Programm findet man dann raus, wie die Register
des Timers initialisiert werden müssen, damit die ISR aufgerufen wird.
Und da da nichts anderes vorkommt, kann man dann auch sicher sein, dass
man nur mit dem Timer kämpft und mit nichts anderem.
Hat man das dann soweit alles ausbaldovert, dann überträgt man dieses
Wissen ins echte Programm - das Testprojekt hat ausgedient.
> Hat man das dann soweit alles ausbaldovert, dann überträgt man dieses> Wissen ins echte Programm - das Testprojekt hat ausgedient.
Habe bereits ein fertiges PWM Programm, das einwandfrei funktioniert,
mit genau diesen Prozessor in genau diesem Prozessortakt.
Dieses habe ich auch größtenteils für das Projekt "mega" übernommen.
Warte mal, ich prüf mal was ab, glaub, da stimmt was nicht..
Im übrigen:
Deine Programmlogik scheint da etwas arg verquert zu sein.
Was willst du überhaut erreichen?
Das toggeln der LED in der ISR geht ja noch.
Aber
1
ISR(TIMER2_COMP_vect)
2
{
3
switch(PROGRAMM_ZUSTAND)
4
{
5
caseTRIGGERE_ROTE_LED_MIT_WERT:
6
PORTB^=ROTE_LED_AN;
7
PROGRAMM_ZUSTAND=TUE_NICHTS;
8
break;
9
10
default:
11
}
12
}
was soll das werden?
Es ist mehr als zweifelhaft, ob du den PROGRAMM_ZUSTAND im Status
TRIGGERE_ROTE_LED_MIT_WERT jemals erwischt, wenn du hier in main
1
caseTRIGGERE_ROTE_LED_MIT_WERT:
2
aktueller_PWM_wert=atoi(zwischenzustand_array);
3
OCR2=aktueller_PWM_wert;
4
PROGRAMM_ZUSTAND=TUE_NICHTS;
Den Zustand selbst auf TUE_NICHTS änderst, wenn die Statmachine diesen
Zustand erreicht.
Abgesehen davon: wozu dann die phase correct PWM?
Das ganze sieht alles sehr konfus aus. Sinn macht das nicht wirklich.
Ich denke, du hast dich wieder mal selber mit deiner Programmlogik ins
Knie geschossen.
> Was willst du überhaut erreichen?
Das Programm dient (wenn es größer ist) für eine kleine Anlagensteuerung
> Das toggeln der LED in der ISR geht ja noch.> Aber>
1
>ISR(TIMER2_COMP_vect)
2
>{
3
>switch(PROGRAMM_ZUSTAND)
4
>{
5
>caseTRIGGERE_ROTE_LED_MIT_WERT:
6
>PORTB^=ROTE_LED_AN;
7
>PROGRAMM_ZUSTAND=TUE_NICHTS;
8
>break;
9
>
10
>default:
11
>}
12
>}
13
>
>> was soll das werden?
hab mir gedacht, dass ich wieder in den Ausgangszustand wechseln muss,
wenn ich einmal im Zustand bin, dass ich wieder zurück komm.
> Es ist mehr als zweifelhaft, ob du den PROGRAMM_ZUSTAND im Status> TRIGGERE_ROTE_LED_MIT_WERT jemals erwischt, wenn du hier in main>
1
>caseTRIGGERE_ROTE_LED_MIT_WERT:
2
>aktueller_PWM_wert=atoi(zwischenzustand_array);
3
>OCR2=aktueller_PWM_wert;
4
>PROGRAMM_ZUSTAND=TUE_NICHTS;
5
>
>> Den Zustand selbst auf TUE_NICHTS änderst, wenn die Statmachine diesen> Zustand erreicht.
Wie meinst du das?
> Abgesehen davon: wozu dann die phase correct PWM?
Das ist nur so eine Übungssache, denke, dass die phase correct pwm
präziser ist.
>> Das ganze sieht alles sehr konfus aus. Sinn macht das nicht wirklich.> Ich denke, du hast dich wieder mal selber mit deiner Programmlogik ins> Knie geschossen.
möglich. Heute ist es aber schlimmer, habe nämlich bemerkt, dass er
garnicht in den Zustand Zwischenzustand_PWM_2 kommt.
(Teste noch aus, und veruch weiter)
mfg,
tommyProg
Du Karl,
also habs grad nochmals überprüft, und konnte keinen status
zurückgeben lassen. Gestern ging es aber interessanterweise noch.
Die Version konnte ich noch auslesen, aber ich bekomme nichts vom
MIkrocontroller auf meinen PC per HTerm :/.
Versuche jetzt noch rauszufinden, warum das so ist.
Mfg,
tommyProg
So Karl,
hab Zeichen ausgegeben, und den Zustandsautomaten in meinem Timer-
Interrupt gelöscht(nachdem ich ihn überprüft habe), nun leuchtet die
rote LED Wie folgt (teils falsch)
RESET: rote: leuchtet hell_1; grüne: blinkt;
1. Eingabe P; rote leuchtet hell_1; grüne blinkt, wert 0 Ausgabe
(initialwert)
2. Eingabe P15; rote leuchtet noch heller_1, grüne blinkt;
3. Eingabe P; rote leuchtet noch heller_1, grüne blinkt, wert 15 Ausgabe
4. Eingabe P168; rote leuchtet noch dunkler_1, grüne blinkt,
5. Eingabe P, rote leuchtet noch dunkler_1, grüne blinkt, wert 168
Ausgabe
6. Eingabe P15, rote leuchtet noch heller_1, grüne blinkt ABER NUN
*wird die LED nach einiger Zeit, nach ca. 2 Sekunden dunkler und
leuchtet sehr schwach* (untersuche noch die Stelle) Was glaubst du,
woran das liegt?
//Ab diesem komischen verhalten verhält sich das System, wie es
eigentlich sein soll//
7. Eingabe P168; rote leuchtet noch heller_1, grüne blinkt
8. Eingabe P15; rote leuchtet extrem schwach, grüne blinkt (wird nach
der Zeit von alleine nichtmehr heller)
9. Eingabe P; rote leuchtet extrem schwach, grüne blinkt, Ausgabe Wert
15
Mfg,
tommyProg
Hab beim Timer noch mein COM21 aktiviert, damit beim phase- correct- pwm
das signal nicht invertiert wird. (hier habe ich natürlich einen anderen
PIN für meine LED benutzen müssen, aber scheinbar war das der Grund, da
nun 1) die LED feinfühliger leuchtet, und 2) es gibt keine Probleme mehr
mit der Anfangsinitialisierung.
Mfg,
tommyProg