Forum: Mikrocontroller und Digitale Elektronik Problem mit Variable in Interrupt (AVR)


von Mike (Gast)


Lesenswert?

Hallo ihr Spezialisten,

ich hänge an einem Problem. ich programmiere einen Atmel ATTiny 25 mit 
WINAVR in C.
Ich habe eine Variable in einer Interruptroutine, die hochgezählt wird 
wenn eine steigende Flanke kommt. Dies scheint mir nicht korrekt zu 
funktionieren. Nicht korrekt heißt: nicht so, wie ich das will.

Mein Plan:
Ich Frage einen Pin am µC auf steigende Flanke ab und nutze dazu INT0. 
In der ISR zähle ich eine Variable hoch, damit ich weiß, wie viele 
positive Flanken gekommen sind (brauche ich zur Auswertung).
Praktisch sieht es so aus:
Die Flanke kommt einmal, aber der Zähler steht auf 5.

Meine Einstellungen:
Die Variable, die gezählt wird habe ich als globale Variable als 
volatile deklariert:
1
volatile uint8_t Flankenzaehler;
Vormals habe ich es auch schon mit static volatile probiert.
Die Einstellungen in den Registern sind:
1
GIMSK |= (1<<INT0);     // Ext. Pin-Interrupt ist eingeschalten
2
MCUCR |= 0x03;          // Ext. Interrupt wird ausgelöst bei steigender Flanke
Die Variable wird in der Initialisierung auf 0 gesetzt.
Die Interrupts habe ich eingeschaltet
1
sei();

Im Programm wird nur per if abgefagt ob die Variable >= 3 ist.

Teilprogramm:
Das Programm beinhaltet eine Art Blinker. Eingang ist ein Rechteck (1:1 
jeweils 1 sek). Im Ausgang ist u.a. eine Kontrollampe.
Bei einem detektierten Fehler geht die Lampe aus.

Problem: Die Lampe geht kurz an und sofort wieder aus(Zeit ca. 100 - 200 
ms.), obwohl der positive Impuls noch gar nicht abgeschlossen ist. Durch 
Einfügen von Code und Speichern der Werte im EEPROM lese ich aus, dass 
die positive Flanke 5 mal angelegen haben soll.

Hinweis:
Der positive Impuls am Eingang kommt nicht von einem Taster, sondern von 
einem 555.

Habt Ihr eine Idee?

von 42 (Gast)


Lesenswert?

Zeile 42

von Mike (Gast)


Lesenswert?

Das Programm ist etwas größer. ich denke, ich habe die wesentlichen 
Punkte, die damit zu tun haben aufgeührt. Ich denke ich habe etwas im 
Umgang mit Interrupts übersehen.

von 42 (Gast)


Lesenswert?

wer sagt, dass du genau das programmiert hast, was du verbal geschrieben 
hast?

von Thomas E. (thomase)


Lesenswert?

Mike schrieb:
> ich denke, ich habe die wesentlichen
> Punkte, die damit zu tun haben aufgeührt.

So, wie der Interrupt initialisiert ist, sollte es funktionieren.

Mike schrieb:
> Ich denke ich habe etwas im Umgang mit Interrupts übersehen

Das wird wohl so sein. Aber da kann man natürlich nur raten.

42 schrieb:
> Zeile 42

Da schliesse ich mich an.

mfg.

von John (Gast)


Lesenswert?

Code auf das absolute Minimum reduzieren, und schauen ob der Fehler noch 
auftritt. Wenn nicht, Schritte langsam zurückgehen und schauen welcher 
Codeteil da reinpfuscht. Wenn der Fehler jedoch immer noch auftreten 
sollte, ruhig her mit dem Code.
> wer sagt, dass du genau das programmiert hast, was du verbal geschrieben
> hast?
Das frage ich mich auch, und das sollte auch die erste Frage sein, die 
sicher der TE stellen sollte.

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

Anbei ein Ausschnitt mit allen teilen, die für Interrupt und mit der 
Variable zusammenhängen.

von Mike (Gast)


Lesenswert?

Wäre schön, wenn ich einen Tipp bekommen könnte

von Purzel H. (hacky)


Lesenswert?

Die zu zaehlende flanke kommt von einem schalter? Der wird prellen. 
Entprell den erst mal.

von U.R. Schmitt (Gast)


Lesenswert?

Hex Oschi schrieb:
> Die zu zaehlende flanke kommt von einem schalter? Der wird prellen.
> Entprell den erst mal.

Mike schrieb:
> Der positive Impuls am Eingang kommt nicht von einem Taster, sondern von
> einem 555.

Zuerst mal sicherstellen, daß die Flanke wirklich sauber ist. Ggf einen 
Impulszähler dranhängen ob der nur die gewünschten Impulse zählt. Oder 
ein DSO.
Ist der µC und der 555 mit einem Kerko an der Versorgungsspannung 
abgeblockt?
Zählst du nur die gewünschten Impulse wenn du mal eine Schleife 
programmierst mit der du mit max. Geschwindigkeit nur den Eingang pollst 
(ohne Interrupt)?

von benni (Gast)


Lesenswert?

" DDRB = (1<<DDB0)|(1<<DDB1)|(0<<DDB2)|(0<<DDB3)|(0<<DDB4);    "

heißt es bei dir..

bin mir nich sicher ob man das so schreiben kann

DDRB = (0<<DDB2) als bsp. müsste eigtl rotz rauskommen..

im grunde heißt das ja schiebe 00000000 um DDB2 stellen nach links.. 
kommt wieder 00000000 raus.. zusammen mit der | verknüpfung kommt am 
ende dasselbe raus wie vorher drin stand.

probier ma ~(1<<DDB2)

von benni (Gast)


Lesenswert?

ich würde es insgesamt so schreiben

DDRB = (1<<DDB0)|(1<<DDB1)
DDRB &= ~((1<<DDB2)|(1<<DDB3)|(1<<DDB4))

von spess53 (Gast)


Lesenswert?

Hi

>ich würde es insgesamt so schreiben

>DDRB = (1<<DDB0)|(1<<DDB1)
>DDRB &= ~((1<<DDB2)|(1<<DDB3)|(1<<DDB4))

DDRB = (1<<DDB0)|(1<<DDB1) -> DDRB = 0b00000011

Was willst du da noch löschen?

MfG Spess

von benni (Gast)


Lesenswert?

naja hab ja keine ahung wie es vorher deklariert wurde.. kann ja sein, 
dass er vorher 0b11010101 oder sonstwas drin stehn hat.. aber ich denk 
man nich.. aber man sollte sich eh sowas wie (0<<bla) abgewöhnen.. da 
kommt glaub ich müll raus

von spess53 (Gast)


Lesenswert?

Hi

>naja hab ja keine ahung wie es vorher deklariert wurde.. kann ja sein,
>dass er vorher 0b11010101 oder sonstwas drin stehn hat.. aber ich denk
>man nich..

Bei DDRB *=*  wird der Inhalt gnadenlos überschrieben.

>aber ich denk
>man nich.. aber man sollte sich eh sowas wie (0<<bla) abgewöhnen.. da
>kommt glaub ich müll raus

Nein. nur wirkungslos.

MfG Spess

von Mike (Gast)


Lesenswert?

Das waren noch Altlasten mit (0<<bla). So programmiere ich mittlerweile 
nicht mehr. Aber danke für den Hinweis, habe es abgeändert, ändert aber 
nichts am Problem.
Werde versuchen mir ein Oszi zu besorgen. Kann den ein 555 prellen?

von Oo (Gast)


Lesenswert?

ihr dürft mich gern hauen, aber hat denn volatile den selben effekt wie 
static? dachte für (status) variablen von ISRs benutzt man eher static??

mfg

von Stefan E. (sternst)


Lesenswert?

Wie groß ist der RAM-Verbrauch des Programms?

von nicht Gast (Gast)


Lesenswert?

Static-Variablen sind wie der Name sagt statisch. Und zwar zwischen den 
Funktionsaufrufen der Funktion in der sie definiert sind. D.h. ihr Wert 
bleibt vorhanden. Sprich sie belasten zur Laufzeit wie globale Variablen 
immer den Speicher, sind aber i.D.R. nur lokal sichtbar.

Volatile-Variablen sind als veränderbar ausserhalb der aktuellen 
Funktion markiert für den Compiler. Das kann ein Interrupt oder auch die 
Hardware selber (i.e. ein Port) als Manipulator sein, daher muss der 
Wert der Variable immer direkt geprüft werden und darf nirgends 
zwischengespeichert werden, wie es der Compiler der Einfachheit halber 
und für Optimierungen für normale Variablen macht.

von Mike (Gast)


Angehängte Dateien:

Lesenswert?

So, habe mir mal ein Oszi besorgt.

Der Pin am µC bekommt definitv nur eine positive Flanke. Aber die 
Abbruchbedingung erfolgt bereits lange bevor eine zweite Flanke kommt.

Abbruchbedingung war:
1
if (Flankenzaehler >= 3)
Und der Flankenzaehler wird hier hochgezählt:
1
ISR(INT0_vect)    // Interrupt Vector INT0 an PB2 ->für ZBR_in
2
{
3
    x.Blinker = ein;  // Information: High-Signal vom ZBR liegt an
4
    x.timer_start = 1;// timer Starterlaubnis
5
    Flankenzaehler++;
6
}
wobei diese Einstellungen am Register eingestellt sind:
1
/* Initialisierung Interrupt */
2
  GIMSK |= (1<<INT0);     // Ext. Pin-Interrupt ist eingeschalten
3
  MCUCR |= 0x03;          // Ext. Interrupt wird ausgelöst bei steigender Flanke
Vielleicht noch ein Hinweis!

Ich habe zwei Eingänge parallel geschaltet (PB2 und PB3)
PB2 ist der INT0 Eingang, der die Flanken zählen soll
PB3 (direkt verbunden) arbeitet als AD-Wandler um zu messen wie groß die 
Spannung ist.
R2 ist ein Teil eines Spannungsteilers. parallel hierzu hängt noch ein 
100nF Kerko.

von Mike (Gast)


Lesenswert?

Die Flanke habe ich mit einem Oszi direkt an dem Widerstand R2 gemessen.

von Walter S. (avatar)


Lesenswert?

John schrieb:
> Code auf das absolute Minimum reduzieren, und schauen ob der Fehler noch
> auftritt. Wenn nicht, Schritte langsam zurückgehen und schauen welcher
> Codeteil da reinpfuscht. Wenn der Fehler jedoch immer noch auftreten
> sollte, ruhig her mit dem Code.

Mike schrieb:
> Wäre schön, wenn ich einen Tipp bekommen könnte

von Stefan E. (sternst)


Lesenswert?

Und auch meine Frage ist noch unbeantwortet:

Stefan Ernst schrieb:
> Wie groß ist der RAM-Verbrauch des Programms?

Ein ATTiny 25 ist ja schließlich nicht gerade üppig mit RAM 
ausgestattet.

von John (Gast)


Lesenswert?

Und auch von mir noch einmal zur Wiederholung:
Reduziere den Code auf das Wesentliche! Nicht hier deinen Code posten 
und Teile weglassen. Weder du, noch wir wissen ob nicht irgendein 
anderer Teil deines Programmes diesen Effekt auslöst. Ebenso steht die 
Frage mit dem RAM-Verbrauch noch offen. Alles Sachen die man wunderbar 
ausschließen kann wenn man das Programm wirklich nur auf das nötigste 
reduziert. Wer versucht Probleme zu lösen indem er immer nur das Ganze 
anschaut und vor sich hin murmelt "Aber es müsste funktionieren" kommt 
nicht weiter. Ein solches Vorgehen ist nicht nur in der Elektronik 
äußerst unproduktiv. Gehe immer davon aus, das irgendwas was deiner 
Meinung nach so funktionieren müsste nicht so funktioniert, weil dein 
Wissen falsch oder unvollständig ist. Nochmal: Du bist der Meinung das 
ein bestimmter Codeteil keine Auswirkung haben kann -> schmeiss ihn 
trotzdem raus, oder reduziere ihn auf das absolute Minimum wenn er für 
die Reproduktion des Fehlers (nicht für die Funktion des Programmes) 
gebraucht wird.

Also in deinem Fall bedeutet das:
1) Projekt kopieren
2) Alles, und ich meine wirklich ALLES was nichts mit dem Problem an 
sich zu tun hat herausschmeißen und das minimalistischste Programm 
erstellen, dass den Fehler erzeugt. In deinem konkreten Fall sollte das 
komplette Programm nicht mehr als 16 Zeilen Code haben. Vergiss auf der 
Ebene der Fehlersuche das wegspeichern einer Variable ins EEPROM. Du 
hast einen Ausgang den du nach einem Vergleich schalten kannst. Das 
reicht!
3) Wenn der Fehler noch auftritt -> Hardware checken. Abblockkondensator 
defekt? Wie siehts mit der Versorgungsspannung aus? Bleibt sie stabil? 
Fängt sie an zu schwingen? Die Signale hast du ja gemessen und selbst 
beurteilt, wenn du dir sicher bist das das passt -> ok.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.