mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik if Abfrage in main() ignoriert?


Autor: Nn Nn (jaytharevo)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo alle zusammen :)!

Also ich steh hier einfach total am Schlauch.
Bin gerade dabei ein Programm häppchenweiße zu debuggen.
Aus reinen Testzwecken schaltet man mal da mal da ein LED ein oder aus.
Funktioniert auch alles so weit.

Es geht um die Anweisung. Ich weiß ein wenig aus dem Zusammenhang 
gerissen, der restl. Code befindet sich im Anhang.

Es handelt sich um die Zeile.
if(Second==5) PORTC ^= (1<<PC1);

Das komische ist wenn ich es in der ISR ausführe alles funktioniert.
ISR (TIMER1_OVF_vect)
{static uint8_t _20_ms=0;
 _20_ms++;

if (_20_ms == 50)
  {
   Second++;
   _20_ms = 0;
   if(Second==5) PORTC ^= (1<<PC1);
  }
}

Also so funktioniert es.
Jemand eine Idee?

Mfg JTR

Autor: ozo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Volatile?

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
LOL?! Warum hab ich das gelöscht? ...
volatile uint8_t Second=0;

Ist nun so global definiert, leider keine Veränderung.

MfG

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hab wohl mal wieder ein C- Mysterium programmiert^^.

Autor: Henry (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
if(Second==5) PORTC ^= (1<<PC1);

Weil du diese Abfrage in deine Main machst.... und wenn deine ISR 
schneller ist und die Sekunden schon auf 6 hat bevor die bedinung 
getestet wird , kanns halt nicht funktionieren....also mach lieber

if(Second>4) PORTC ^= (1<<PC1);

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du den Portzustand sowohl in der ISR als auch in der Main toggelst 
soltest du dich auch nicht wundern ;)

Autor: Bernhard Spitzer (b_spitzer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn die Abfrage in main() steht, wird eine ganze Sekunde lang 
getoggelt. Erst ab der Sekunde 6 wird nicht mehr getoggelt. Wenn nur 1x 
getoggelt werden soll (das macht ja die ISR), dass musst Du in der ISR 
ein globales Flag setzen und dieses in main() nach Bearbeitung wieder 
löschen.

in der ISR:
if(Sekunde==5) tuwas=1;

in main():
if(tuwas){
  tuwas=0;
  PORTC ^= (1<<PC1);
}

tschuessle
Bernhard

Autor: timer (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Sehe ich das richtig, dass _20_ms in der ISR jedes mal wieder neu 
angelegt wird und somit immer 1 ist. D.h. die IF-Abfrage wäre sinnlos

Autor: Läubi .. (laeubi) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
timer schrieb:
> Sehe ich das richtig, dass ...
nein. Es handelt sich um eine static lokale Variable die behält ihren 
Wert das ist schon richtig so.

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Danke für eure Antworten!

Ich denke, dass da irgendwo das richtige dabei sein wird :)!
Leider komm ich erst wieder am Montag zum testen, werde berichten.

@Läubi:
Hab wohl den upload der .c Datei vermasselt. Beim testen wurde natürlich 
nur an einer Stelle getoggelt.

@Henry:
Der Controller läuft mit 8Mhz. Ich glaub nicht, dass er bei so einem 
popeligen Programm nicht ein mal die main() durchrattern kann.

@Bernhard:
Das hört sich schon sehr vielversprechend an. Aber, dass jedes Mal eine 
gerade Zahl getoggelt wird?

Danke! Allen ein schönes WE :)!

MfG

Autor: Peter (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was denkst Du wie oft dass
if(Second==5) PORTC ^= (1<<PC1);
 im main ausgeführt wird, bis Second endlich gleich 6 ist? Vielleicht 
1000 mal?

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Oft.

Aber immer eine gerade Anzahl? Unwahrscheinlich....

Autor: Nn Nn (jaytharevo)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Leider gab es keinen Unterschied.

Was zur Hölle kann, dass sein?
Hab auch die LED einzeln probiert, sie kann also blinken^^.

MfG

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Diese Berechnung

        OCR1A_tmp = Tick_P_el_tmp / Divisor_P_el + P_Offset;

ergibt 1000

d.h. diese while Schleife hier

        while(!(OCR1A==OCR1A_tmp))
        {
          if(OCR1A < OCR1A_tmp) OCR1A++;
          if(OCR1A > OCR1A_tmp) OCR1A--;
          set_sleep_mode(SLEEP_MODE_IDLE);
                sleep_mode();
        } // While end

(wenn überhaupt der Timer interrupt den µC aus dem Sleep Mode rausholt 
was ich nicht kontrolliert habe), dauert bei 20 ms INterrup Frequenz wie 
lange, damit sie den Wert von OCR1A von Initial 1999 auf 1000 reduziert 
hat?

Dann kommen hinten nach noch mal 20 ms Wartezeit

->
Es ist ziemlich unwahrscheinlich, dass du hier

  if(Second==5)

die Variable Second genau mit dem Wert 5 erwischt. Die wird da schon 
wesentlich weiter sein. (DIe müsste da schon so im Bereich um die 20 
haben)


Was soll das ganze eigentlich sein? Was hat es da mit dem Sleep Mode auf 
sich, wozu die ganzen Wartereien?

Ich kann mir nicht helfen. Das ganze sieht für mich nach "von hinten 
durch die Brust ins Auge" Programmierung aus.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und second ist immer noch nicht volatile.

Autor: Hans W. (hans_w30)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ISR (TIMER1_OVF_vect)  // ISR for counting the time with 16-Bit Timer1; Overflow every 20ms
{static uint8_t _20_ms=0;

 _20_ms++;

if (_20_ms == 50)
  {
   Second++;
   _20_ms = 0;
   PORTC ^= (1<<PC0);
  }
}

Du setzt jedes mal wenn du in die ISR kommst deinen Wert von _20_ms auf 
Null. Dann geht er ja schon nie in die if Abfrage in deiner ISR.
Wie sollte dann Second jemals 5 werden?

Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Hans W.

Lieber Hans,

Static Variablen werden nur einmal initialisiert. Das steht in einem 
C-Buch.

Autor: Hans W. (hans_w30)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
ups stimmt sorry 1tes Semester....
Nehm alles zurück und behaupte das gegenteil

Kann das aber sein das du 2 mal deinen Timer initialisierst? Bzw. dir 
deine Funktion implizit deklarierst?
Ein Prototyp gehört nicht unbedingt in die main
.....
// Prototypen

// Timer1 Initialization (ICP & PWM)
void Timer1_init(void);

// Timer1 Initialization
Timer1_init();


Autor: Guru (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Hans W.

Lieber Hans,

das soll jetzt so ein kleiner Scherz unter Informatikern sein.

Du schriebst:

>Nehm alles zurück und behaupte das gegenteil

Das stimmt leider auch nicht so ganz.
Denn das Gegenteil von "jedesmal" ist eines von "niemals", "einmal" und 
"einige Male".
Eine static Variable wird aber genau "einmal" initialisiert.

Ich hoffe, Du findest das so lustig wie ich.

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Karl Heinz Buchegger schrieb:
> (wenn überhaupt der Timer interrupt den µC aus dem Sleep Mode rausholt
> was ich nicht kontrolliert habe)

kommt raus :)

> dauert bei 20 ms INterrup Frequenz wie
> lange, damit sie den Wert von OCR1A von Initial 1999 auf 1000 reduziert
> hat? DIe müsste da schon so im Bereich um die 20 haben)
>
Jo, 20s dürfte es dauern. Also alle 20ms ein Schritt weiter. 20ms*1000 = 
20 000ms = 20s. Daran hab ich wie immer nicht gedacht und wird auch des 
Rätslslösung sein. Ich verneige mich :)!


> Was soll das ganze eigentlich sein? Was hat es da mit dem Sleep Mode auf
> sich, wozu die ganzen Wartereien?
> Ich kann mir nicht helfen. Das ganze sieht für mich nach "von hinten
> durch die Brust ins Auge" Programmierung aus.

Ja, mag wohl so ausschauen. Wie bereits erwähnt handelt es sich um einen 
kleinen Ausschnit eines Programms. Quasi um gewisse Funktionen zu 
testen. Wenn man sein ganzes Prog. testen will und iwas nicht 
funktioniert wird, das eine endlose Sucherei.

Es geht darum die Position eines Servos langsam zu verändern.

Kennst du eine besser Methode (garantiert sogar) :D ;)!

Danke soweit!

MfG


ps: @guru: Ich habe gelacht :D! freaky

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Julian Schild schrieb:

> Es geht darum die Position eines Servos langsam zu verändern.
>
> Kennst du eine besser Methode (garantiert sogar) :D ;)!

1 Timer macht die Servoansteuerung. Ich hab jetzt nicht auf deine 
Taktfrequenz geachtet, aber der Timer 1 müsste normalerweise hinkommen.

Ein 2.ter Timer gibt einen Basistakt vor. In dessen ISR wird der OCR 
Wert für den Servo-Timer verändert, so dass er sich seiner Zielvorgabe 
annähert.
Sleep Mode braucht da kein Mensch dazu.

Hauptschleife
   while( 1 )
   {
     ServoSoll = 0;               // Zielvorgabe: Servo ganz nach links

     _delay_ms( 10000 );          // etwas warten (währenddessen verfährt
                                  // die Timer ISR das Servo

     ServoSoll = ServoMaximum;    // Zielvorgabe: Servo ganz nach rechts

     _delay_ms( 10000 );          // und wieder: das Servo fahren lassen
   }

Die Verfahr-ISR
Aufgabe: Wenn die Servo Istposition nicht mit der ServoSollposition 
übereinstimmt, dann für den Servo-Timer den OCR Wert nachstellen
ISR( .... )    // zb Overflow vom Timer 2
{
  if( OCR1A < ServoSoll )
    OCR1A++;

  else if( OCR1A > ServoSoll )
    OCR1A--;
}

Und dann natürlich noch den Timer 1, der so konfiguriert wird, dass er 
ganz alleine das Servosignal erzeugt, welches mit OCR1A beeinflusst 
werden kann.


Voila: Die komplette Servoansteuerung und Nachführung erledigen die 
Timer ganz von alleine bzw. mit einer ISR. In der Hauptschleife muss man 
nur noch die ServoSoll-Position zuweisen und das Servo fährt dann diese 
Position langsam an.

Hmm. Gerade noch mal drüber nachgedacht. Man könnte wahrscheinlich das 
ganze auch so regeln, dass der Timer 1 beides übernimmt. Er generiert 
sowohl die Servosignale (per Hardware) als er sich auch darum kümmert, 
dass die Servo Istposition an die Soll Position herangeführt wird (in 
einer ISR)

Autor: Nn Nn (jaytharevo)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das ist, wie immer, eine gute Idee.

Dafür muss ich aber sogar den 3. Timer verwenden :D!

Denn der 1. 8 Bit Timer (Timer 0) zählt Pulse (fmax = 4kHz).
Das Ergebnis nach 50s ist dann ausschalggebend für die Servoposition.

Das der Timer1 (16Bit) bereits die Servoansteuerung übernimmt sieht man 
eh, außerdem übernimmt er auch noch die Funktion einer "Uhr".

Gefällt mir sehr gut, den Code schlanker zu machen und dafür auf die 
Hardware auslagern :)!

Danke Karl!! :)

MfG

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.