mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Timing Problem


Autor: Hias (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!

Ich habe ein Timing Problem.
Aber zuerst eine kleine Vorgeschichte:

Ich erzeuge für PC-Lüfter ein PWM - Signal, dass zur Regelung
dergleichen benutzt werden soll. Da ich 6 verschiedene Kanäle haben
möchte, erzeuge ich PWM per Software. Die Frequenz der PWM ist ungefähr
(50Hz). Diese Frequenz wird für alle Kanäle in Timer0 erzeugt. (8bit)
Dabei ist die Timerfrequenz etwa 5kHz. Die Timer-Interrupt-Schleife
dauert ungefähr 30 Taktzyklen.

Jetzt möchte ich noch die Drehzahl der 6 Lüfter auslesen.
Da denke viel PWM und Drehzahlauslesung macht Probleme. Ich denke ich
habe aber das PWM Signal ausreichend geglättet. Ich habe vom
DREHZAHL-Signal (Pullup und Kondensator gegen Masse an
Open-Kollektor-Ausgang des Lüfters) am Oszi a Bild gemacht (siehe
Anhang). Ich kann zumindest keine Verunreinigung des Signals
verstellen. Ihr etwa?

Um die Drehzahl zu bestimmen möchte ich die Zeit zwischen zwei Impulsen
messen.
Dazu warte ich auf ein „high“ und starte dann den Timer1(16bit). Teste
dann auf „low“ und stoppe schließlich den Timer bei einem erneuten
high.
Zur Info: Impulslängen des Drehzahlsignals zwischen 5ms und 100ms.

Hier ein kleiner Codeausschnitt den ich zum Testen meiner Idee
verwendet habe…
main:    
step1:    sbis pinb,1      ;Test ob pinb 1 (Kanal1) high
    rjmp step1      
    ldi r16,0x00
    out tcnt1l,r16      ;Timer löschen (Timer starten)
    out tcnt1h,r16

step2:    sbic pinb,1      ;low-Test
    rjmp step2
        
step3:    sbis pinb,1      ;high-Test
    rjmp step3
    
    in cl,tcnt1l      ;Timer stoppen
    in ch,tcnt1h
    sts canal1l,cl      ;speichern
    sts canal1h,ch      ;speichern
    
    ;Hier kommt später noch eine umwandlung von steps in rpm
    
step4:    rjmp main

Anmerkungen: cl und ch sind Register,  die später zur Umrechnung von
steps in rpm benötigt wird. Diese werden zum Testen einfach im RAM
gespeichert um per UART ausgelesen werden können.

Nun ja genau da liegt mein Problem. Ich erhalte jedes Mal wenn ich die
steps Auslese extrem unterschiedliche Werte.
Warum nur? Ich komm einfach nicht weiter.
Wo liegt mein Fehler?

Danke schon mal…

MfG Hias

P.S.: Kompletter Code im Anhang des nächsten Beitrags.

Autor: Hias (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hier der Code

Autor: Santa Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Um die Drehzahl zu bestimmen möchte ich die Zeit zwischen zwei
Impulsen
>messen.
>Dazu warte ich auf ein „high“ und starte dann den Timer1(16bit).
Teste
>dann auf „low“ und stoppe schließlich den Timer bei einem erneuten
>high.

Was ist, wenn Du im laufenden Betrieb den Drehzahlsensor-Kabel-Stecker
abziehst?  Dann tritt das Ereignis, auf das Du in der "step2"- bzw.
"step3"-Schleife des Hauptprogramms wartest, niemals auf.  Bleibt
dann Dein Programm (bis auf die interruptgesteuerten Sachen) stehen?
Ist dieses Verhalten erwünscht?  Wenn nicht, wie könntest Du die
Zeitmessung anders durchführen?  Ginge es möglicherweise auch ohne
Warteschleife (!) im Hauptprogramm?  Und wenn ja, wie?

Autor: Hias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich hab das nur zwecks der Einfachheit halber geändert. Wenn du in
komplett-code nachschaust das siehst du das des auch weiterläuft.
Ich könnte auch die ganze Zeit den Zustand der Pins einlesen und
schauen ob sich was geändert hat, ja. Aber das ändert nichts mit dem
Problem des 2.Timers!? Der Funkt da anscheinend immer dazwischen.

Was ich mir inzwischen angeschaut habe is ICP. Mal probieren ob des
besser geht. Könnte ja dann einen Multiplexer verwenden und könnte
somit auch alle 6 Kanäle abfragen.

Aber vielleicht gehts ja auch ohne. Ich verlass mich da ganz auf
euch... : )

MfG Hias

Autor: Santa Klaus (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn du in komplett-code nachschaust das siehst du das des auch
>weiterläuft.

Ich will nicht rechthaberisch sein, aber ich sehe das überhaupt nicht.
Ich lese dort:

step2:  sbic pinb,1        ;low-Test
        rjmp step2

Wenn die Bedingung "Bit 1 von pinb ist gesetzt" ab einem bestimmten
Zeitpunkt niemals mehr auftritt (Sensorkabel abgezogen), dann kommt der
Controller doch niemals mehr aus dieser "step2"-Schleife raus (wie
sollte er denn?), oder sehe ich das falsch?

>Ich könnte auch die ganze Zeit den Zustand der Pins einlesen und
>schauen ob sich was geändert hat, ja.

Was bedeutet "die ganze Zeit"?  Hätte es einen Vorteil, wenn Du den
Zustand der Pins in einem genau definierten Zeitintervall (z. B. 0.2
ms) einlesen könntest?  Wie könntest Du Dir ein solches "periodisches
Ereignis" in genau definierten Zeitabständen "beschaffen"?  Oder
vielleicht gibt es ein solches sogar schon in Deinem Progamm?
Vielleicht brauchst Du gar keinen 2. (3., 4., 5. ...) Timer, sondern
nur einen einzigen?

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Moin...

Dein Programm ist mehr als nur die ISR, daher solltest du unbedingt den
Stackpointer sichern.

Es gibt noch eine schnellere Möglichkeit, in der ISR eine Mehrkanal-PWM
zu generieren, da werden die durch die Vergleiche beeinflussten
Carry-Flags in ein Register geschoben (eingesammelt) und dieses per OUT
ausgegeben, worauf die "abgelaufenen" Kanäle mit nur einem I/O-Zugriff
abgeschaltet werden. Das geht natürlich nur, wenn alle PWMs in einer
Reihe an einem Port hängen. Für andere Zwecke benutzte Pins dieses
Ports sind zu maskieren (vorher einlesen).

Die Drehzahlen kannst du auch in der ISR ermitteln:

- Erstmal in der ISR einen Zähler hochzählen.

- Dann einfach Port einlesen und mit dem zuletzt eingelesenen Wert
(bitweise) vergleichen (das dürfte ganz gut mit einer abgespeckten
Variante von Peter Danneggers Tastenentprellung gehen, Einlesen und
Bitmanipulation in der ISR, Auswertung von keypress bzw. tfl im
Hauptprogramm).

- Bei Bitänderungen (nur eine Richtung auswerten, damit eine volle
Umdrehung gemessen wird) Differenz  zur letzten Änderung übernehmen
(das ist dann der Istwert einer Umdrehung in der Zeiteinheit
"Timer-Interrupts") und aktuellen Zählerstand für nächste
Differenzermittlung speichern (für jeden Lüfter eine Speicherstelle).

- Möglichst mit Periodendauer ("Zeitdauer einer Umdrehung") rechnen,
das erpart zeitaufwendige Divisionen im AVR. Dafür lieber in der
PC-Software Drehzahl in Periodendauer umrechnen.

- Du nennst im ersten Beitrag die Timer-ISR-Frequenz von 5kHz (0,2ms
Int-Abstand), und die Lüfterperiode von 5ms...100ms. Das wäre ein
Zahlenbereich (für die Zeitmessung) von 25 ISRs/Umdrehung (ganz
schnell) bis 500 ISRs/Umdrehung (ganz langsam). Da wirst du dann wohl
in 16-Bit rechnen müssen.

Nun lass dir diese Gedankengänge mal auf der Zunge zergehen und
berichte dann mal, was daraus geworden ist.

...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Quatsch... Stackpointer sichern... - Das SREG natürlich... (Ich kann
einen Blödsinn schreiben...)

...

Autor: Hias (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo!
Hab heute wieder ein wenig gebastelt:

Ergebnis: ich bekomme endlich eine Drehzahl die in etwa stimmen
könnte.

Ich habe wie gesagt den ICP verwendet.
Um auf 8 Kanäle zu kommen verwende ich einen Mulitplexer (74HCT151).
Das funktioniert soweit ganz gut.

Nur ein Problem habe ich:

Ich bekomme komischerweise bei 5 Messungen hintereinander nie die
gleichen Werte. Und immer wieder ist ein extremer Ausreißer dabei.

z.B. (hex)
661, 668, 6A7, 651, 3AC, 66A,....

natürlich sieht das blöd auf einem LCD aus, wenn die Werte so stark
springen...

an was liegt das?
Ideen zur Löung des Problems?

Den Teil des Codes zur Messung findet ihr im Anhang.
drehzahl wird als icp-isr aufgerufen...

MfG Hias

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.