Polling

Gast #365338
Lesenswert?

wie kann ich denn da die genauigkeit raufschrauben? wenn das gleiche
signal über eine gewisse zeit reinkommt schwankt der zählerstand enorm!
woran liegt das und wie kann man das beheben??

gruß
Gast #365340
Lesenswert?

Wenn Du zählen willst, dann musst Du die Signalflanken zählen. Ich
vermute mal, dass Du gar nicht wartest, bis Dein Signaleingang wieder
auf null ist und deshalb jeden High-Pegel ein paar tausend mal
erfasst...
#365342
Lesenswert?

Konfigurier den Port am Beginn des Programms und ändere
den dan nicht mehr. Wenn du den Pullup dazuschaltest, kannst
du abhängig davon wie die äussere Beschaltung aussieht ein
paar Schwingungen oder durch ein RC-Glied eine Verzögerung kriegen.
Wie auch immer: Wenn das Pgm hochfährt -> Ports und Pullups
konfigurieren. In der Interrupt-Funktion wertest du dann nur mehr
die Ereignisse aus und lässt die Konfiguration in Ruhe.

Zum Rest: Im Prinzip kannst du das so machen.
Ich wuerde es allerdings so schreiben:

   char neu = PINB & 0x01;

   /* Uebergang von 0 nach 1 ? Ja: Zaehlen */
   if( ( alt == 0 ) && ( neu != 0 ) )
     counter++;

   alt = neu;

Ich finde das kommt besser zum Ausdruck, welches Ereignis die
Zählung auslöst. Ist aber Geschmackssache.
#365347
Lesenswert?

@Ulrich

Abgesehen vom offensichtlichen Tippfehler.
Wenn schon, dann:

if( ( alt != neu ) && ( alt == 0 ) && ( neu != 0 ) )
     counter++;

Viel Spass beim rausknobeln warum.
Tip: Es hat was mit der 'Short-Cut-Evaluation' zu tun
(Sorry, ich kenn das deutsche Wort dafür nicht).
Gast #365349
Lesenswert?

ich kann die ports aber von anfang an nicht konfigurieren und so lassen
weil das lcd alle ports belegt! ich muss sie also anschalten, gucken
und zählen und wieder abschalten! oder gibt es da doch eine elegantere
lösung? vielleicht die ports bei dem display deaktivieren?!

gruß
Gast #365350
Lesenswert?

if( ( alt == 0 ) && ( neu != 0 ) && alt = neu ) funktioniert auch nicht
sonderlich. Es wird versucht dem lvalue

(alt == 0) && (neu != 0) && alt

den Wert von neu zuzuweisen (Der = Operator hat hier die geringste
Priorität). Dazu müßte man den Ausdruck alt = neu in Klammern setzen.
Dann würde das logische && von links nach rechts ausgewertet und die
Zuweisung alt = neu nur erfolgen, wenn zuvor alt == 0 und neu != 0
logisch richtig waren. Damit spart man sich nicht nur eine Zeile ein,
sondern erzeugt auch ein ganz anderes Verhalten.
#365351
Lesenswert?

> ich kann die ports aber von anfang an nicht konfigurieren

Dann machs wenigstens so:
Port konfigurieren
Timer initialisieren
Interrupts starten

und innerhalb der Interrupt Routine wertest du nur mehr
den Pin-Zustand aus. Aber lass um Gottes Willen während
der kompletten eigentlichen Messung die Portkonfiguration
in Ruhe.

> und so lassen weil das lcd alle ports belegt!

Keine gute Idee.
#365353
Lesenswert?

Reden wir jetzt aneinander vorbei?
Was hat das eine mit dem anderen zu tun, ausser das das LCD
Port-Pins belegt und du aber einen Pin als Eingang zum
Abfragen brauchst.

Du hast dir doch einen Timer aufgesetzt, der in regelmaessigen
Zeitabständen einen Interrupt ausloest. Vom Auftreten eines
Interrupts bis zum Auftreten des nächsten Interrupts zählst
du mit wieviele 0-1 Übergänge an besagtem Eingangspin
auftreten.
#365355
Lesenswert?

Damit ich das richtig sehe:
  Den Timer, mit dem du eine stabile Zeitbasis hinkriegen
  könntest, nimmst du um damit Daten auf ein LCD zu schaufeln.

  Auf der anderen Seite benutzt du dort wo du eigentlich
  ein genaues Timing brauchen würdest eine Wald und Wiesen
  Schleife, die durch jeden dahergelaufenen Interrupt ab
  und an mal unterbrochen werden kann.

Und da wunderst du dich, dass die Zählerstände schwanken?
#365357
Lesenswert?

Vielleicht hab ich dich auch nur falsch verstanden.

Die Struktur sollte so aussehen:

In der Mainloop detektierst du ständig, ob am Eingang
ein 0-1 Übergang erkennbar ist.

Im Timer-Interrupt (der regelmässig aufgerufen wird), wird
der Zaehlerstand ausgewertet und wieder auf 0 gesetzt.
Natuerlich sollte die Timer-Interrupt-Funktion nicht allzu
lange dauern. Auf keinen Fall darf sie laenger als ein kompletter
0-1-0 Übergang sein. Die Ausgabe auf das LCD ist also nicht so toll
da drinnen. Die wuerde ich da komplett rausschmeissen.

main wuerde dann in etwa so aussehen (Achtung: Pseudo Code der
so ähnlich wie C aussieht).

  init_lcd()

  while( 1 )

    if( mode == 0 ) {
      counter = 0;
      mode = 1;
      Konfiguriere Eingang zum Aufnehmen der Pulse;
      starte_timer();
    }

    if( mode == 2 ) {     // mode ist vom Timer Interrupt auf 2
                          // gestellt worden, damit wird signalisiert
                          // das eine bestimmte Zeiteinheit abgelaufen
                          // ist.

      stoppe_timer();
      mode = 0;
      Konfiguriere Eingang wieder zurueck;
      counter auswerten und anzeigen;
    }

    if( mode == 1 ) {  // mode == 1 bedeutet dass zur Zeit gemessen
                       // wird.
      neu = ....
      ....
      if( ....
        counter++;
      alt = neu;
    }
  }

Und die Timer-Overflow Funktion hat nur noch eine Aufgabe:
Die globale Variable mode von 1 auf 2 zu setzen um der main-loop
anzuzeigen, dass die Zeit abgelaufen ist.
#365358
Lesenswert?

Oops. Jetzt hab ich im letzten Posting während des Schreibens
2 Ideen zu einer einzigen vermanscht.
Ich würde es so machen, wie im 2.-ten Teil beschrieben.
Wenn du Frequenzen misst, dann ist die Zeitbasis der Messung
eines der wichtigsten Dinger. Ob das LCD nach 10 ms oder 11 ms
upgedatet wird, interessiert keine S.. .
Gast #365359
Lesenswert?

ich habe aber keine schwankungen mehr! der zähler in der mainloop läuft
stabil! alle eine sekunde kommt ab und zu mal eine schwankung von 1!
aber das ist akzeptabel!
das senden im timer funktioniert auch problemlos!

danke für eure hilfe!

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren