Hallo Forum,
ich habe ein Problem mit meiner Schaltung/meinem Code.
Eigentlich möchte ich von einem Potentiometer analog lesen um die
Blinkgeschwindigkeit einer LED zu beeinflussen.
Das funktioniert nicht, da die Variable "speed" nie geändert wird.
Nach dem ersten Durchlauf der "while" in der Funktion "loop()" hängt
sich mein Atmega auf. Wenn ich den Funktionsaufruf von "sei()" entferne,
läuft der Loop erwartungsgemäß durch.
Der Poti funktioniert einwandfrei (getestet mit Multimeter).
Falls es hilft, kann ich auf ein Foto meiner Schaltung hochladen, aber
ich vermute den Fehler eher im Code selbst.
Habt ihr eine Idee?
Grüße, Chris
Hier mein Code:
> hängt sich mein Atmega auf
Wie äußert sich das?
> da die Variable "speed" nie geändert wird
Und wie das? Ich sehe nur eine Zuweisung an speed, aber sonst nichts,
keine Abfrage darauf bzw. Weiterverarbeitung.
Du vermischt hier Arduino Code mit normalen C-Code.
Im main wird alles nur einmal aufgerufen, da gibt es kein return, dann
kommt eine for oder while Schleife, je nach belieben.
Da wir das gerade erst hatten:
Hast du eventuell beim linken die MCU Angabe vergessen? In diesem Fall
würde unter anderem die Sprungtabelle für die ISR Routinen fehlen.
> Du vermischt hier Arduino Code mit normalen C-Code.
Der Arduino Style ist deutlich zu sehen, aber er hat keine Arduino
Library eingebunden und keine Arduino Funktion verwendet.
Das "return 0" am Ende der main() Funktion ist fachlich korrekt, wenn
auch beim avr-gcc ausnahmsweise unnötig.
>> hängt sich mein Atmega auf> Wie äußert sich das?
Ist das nicht offensichtlich? Er wird wohl an PD2 eine LED angeschlossen
haben, die aufhört, zu blinken.
Thomas E. schrieb:> Er stürzt ab, wenn der Interrupt ausgeführt wird. Da die richtige ISR> vorhanden ist, tippe ich mal auf einen falsch eingestellten Controller.
Das hilft mit leider nicht weiter. Was genau kann da falsch eingestellt
sein?
S. Landolt schrieb:> Wie äußert sich das?
Der Inhalt der "while"-Schleife in der Funktion "loop()" wird nur einmal
ausgeführt und nicht wie durch die "while(1)" zu erwarten unendlich oft.
Sprich: die LED schaltet sich an, nach 100 Millisekunden aus, nach
weiteren 100ms wieder an und danach bleibt sie angeschalten.
S. Landolt schrieb:> Und wie das? Ich sehe nur eine Zuweisung an speed, aber sonst nichts,> keine Abfrage darauf bzw. Weiterverarbeitung.
Ich würde die Variable "speed" gerne verwenden. Den lesenden Zugriff
baue ich ein sobald es funktioniert. Man könnte zB. sowas machen:
1
while(1){
2
PORTD|=(1<<PORTD2);
3
delay_ms_own(speed);
4
PORTD&=~(1<<PORTD2);
5
delay_ms_own(speed);
6
}
Das bringt mir allerdings aktuell nichts, weil sich der Controller wie
gesagt aufhängt. Dass die Variable derzeit nur geschrieben, aber nicht
gelesen wird, ist mir klar.
Stefan U. schrieb:> Da wir das gerade erst hatten:>> Hast du eventuell beim linken die MCU Angabe vergessen? In diesem Fall> würde unter anderem die Sprungtabelle für die ISR Routinen fehlen.
Ich bin ziemlich unerfahren. Kannst du mir sagen wie ich das in Atmel
Studio 7 erreichen kann?
Stefan U. schrieb:> Ist das nicht offensichtlich? Er wird wohl an PD2 eine LED angeschlossen> haben...
Korrekt. An PD2 ist eine LED.
> LED ... an, nach 100 Millisekunden aus, nach> weiteren 100ms wieder an
Das ist doch aussagekräftiger als "friert ein" und "hängt sich auf".
Auch wenn ich mir darauf keinen Reim machen kann; sollte die ADC-ISR
wirklich, wie von zweien vermutet, in einen Reset münden, so kann doch
der ADC nicht so lange benötigen.
>> Hast du eventuell beim linken die MCU Angabe vergessen?> Ich bin ziemlich unerfahren. Kannst du mir sagen wie ich das in> Atmel Studio 7 erreichen kann?
Gar nicht. Das kann Dir nur passieren, wenn du "manuell" auf der
Kommandozeile compilierst oder ein fehlerhaftes Makefile verwendest.
Atmel Studio benutzt normalerweise kein Makefile.
Und du hast ganz sicher den richtigen Mikrocontroller-Typ für den
Compiler eingestellt? Gibt der Compiler irgendwelche Hinweise dazu aus,
oder gar Warnmeldungen?
Hast du AVCC angeschlossen? Hast du vielleicht Abblock-Kondensatoren
(nahe zum Mikrocontroller) vergessen?
Chris K. schrieb:> Das hilft mit leider nicht weiter. Was genau kann da falsch eingestellt> sein?
Hast du das schon kontrolliert?
Wenn du für einen anderen Controller kompilierst, und da wärest du
wahrlich nicht der erste, wird eine für deinen Controller nicht passende
Interrupt-Vektor-Tabelle angelegt. Dann springt das Programm sonstwo
hin, nur nicht in die ADC-ISR.
Ich habe einen Teil des Codes falsch kopiert:
Der Inhalt der "while" sieht eigentlich so aus:
1
if(speed){
2
PORTD|=(1<<PORTD2);
3
delay_ms_own(speed);
4
PORTD&=~(1<<PORTD2);
5
delay_ms_own(speed);
6
}
Ich habe das "if" absichtlich nicht mit kopiert, weil ich es für
bedeutungslos hielt. Der Ausdruck wird sowieso immer "true" sein, war
meine Annahme.
Nach wiederholtem Programmieren des Controllers blinkt jetzt gar nichts
mehr.
Wenn ich allerdings die "if" zu
1
if(1)//always true
ändere und alles andere gleich lasse, funktioniert alles wie erwartet.
Die LED blinkt und durch das Verstellen des Potentiometer schneller oder
langsamer.
Wieso löst die "if" nicht auf "true" auf wenn ich nur "speed" als
Condition angebe?
> löst das Problem.>> Kann mir das jemand genauer erläutern?> Ich verstehe nicht wieso hier ein Unterschied entsteht.
Ohne volatile bekommt der Code in loop nichts davon mit das der Wert
in einer ISR geändert wurde. Mit volatile wird der Wert jedesmal von
der entsprechenden Speicherstelle neu geholt.
Sascha
Chris K. schrieb:> Ich habe einen Teil des Codes falsch kopiert:> Der Inhalt der "while" sieht eigentlich so aus:
Also haben wir hier die ganze Zeit auf falschem Code rumgeraten?
Kopf - Tisch. Dreimal.
Der Compiler weiß nicht, dass speed in der ISR geändert wird, denn er
kann nicht erkennen, wann oder ob die ISR überhaupt ausgeführt wird.
Für den Compiler steht da also nur:
1
intspeed=0;
2
...
3
4
if(speed){
5
...
Das kann er auch gleich wegoptimieren.
Das "volatile" sagt ihm, dass speed auch außerhalb von main geändert
werden kann.
Schon, aber wie passt das zu:
Chris K. schrieb:> Wenn ich allerdings die "if" zu> if(1) //always true> ändere und alles andere gleich lasse, funktioniert alles wie erwartet.> Die LED blinkt und durch das Verstellen des Potentiometer schneller oder> langsamer.
Hier kommt doch speed angeblich irgendwie rüber, ganz ohne volatile.
Thomas E. schrieb:> Chris K. schrieb:>> Ich habe einen Teil des Codes falsch kopiert:>> Der Inhalt der "while" sieht eigentlich so aus:>> Also haben wir hier die ganze Zeit auf falschem Code rumgeraten?>> Kopf - Tisch. Dreimal.S. Landolt schrieb:>> Kopf - Tisch. Dreimal.> Soviel zum Thema "offensichtlich".
Entschuldigt. Das war klar fehlendes Wissen meinerseits.
Aber dafür fragt man schließlich in einem Forum.
Auch wenn mein initialer Post das Problem nicht dargestellt hat.
np r. schrieb:> Der Compiler weiß nicht, dass speed in der ISR geändert wird, denn> er> kann nicht erkennen, wann oder ob die ISR überhaupt ausgeführt wird.>> Für den Compiler steht da also nur:int speed = 0;> ...>> if(speed) {> ...>> Das kann er auch gleich wegoptimieren.>> Das "volatile" sagt ihm, dass speed auch außerhalb von main geändert> werden kann.
Danke für die Klärung. Das macht natürlich Sinn.
S. Landolt schrieb:> Schon, aber wie passt das zu:
...
Bei if (speed) kann der Compiler, wenn seiner Ansicht nach speed = 0
ist, das gesamte if-Statement wegwerfen - es wird ja sowieso nie
ausgeführt.
Bei if(1) muss er das If-Statement und den Code darin behalten.
Darin wird speed verwendet. Und in der ISR geändert. In diesem Falle:
Glück gehabt.
Chris K. könnte ja mal die Größe des kompilierten Programms vergleichen,
eimmal mit if(speed) (ohne volatile), einmal mit if(1) und einmal mit
if(speed) und volatile.
Chris K. schrieb:> Aber dafür fragt man schließlich in einem Forum.
Ja, aber mit dem kompletten Code.
Zu den typischen Anfängerfehlern gehört das Weglassen/Vergessen von
"volatile" und, das allerdings nicht nur bei Anfängern, das generelle
Ausschließen von Fehlern: "Nein, daran kann es gar nicht liegen." Oder:
"Daß da ein Fehler liegt, hätte ich niemals gedacht."
Fatal ist es, wenn beides auch noch zusammenkommt.