PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Messung des Servopules mit mega328/20MHz über Timer1 läuft nicht



oberallgeier
15.03.2016, 12:53
Bitte um Hilfe.

Stand:
Der Timer2 generiert mir den Heartbeat - einen 20 kHz-Interrupt bzw. 50µs, mit dem alle 20 000 Interrupts, also sekündlich, die Heartbeat-LED getoggelt wird. Dieser Timer (nicht jedes Mal Timer2) dient mir auch anderswo, z.B. bei Drehzahlen, für Zeitmessungen. Die Nutzung ist problemlos.
Zum Auslesen eines Servopulses ist eine Genauigkeit von 50µs ungenügend, die Auflösung der Pulse, 1ms bis 2ms beträgt ja grad mal 200 bis 400 Schritte. Daher wurde eine Zeiterfassung direkt mit dem 16bittigen Timer1 geplant.

Plan:
Es wird der Timer1 zum Messen der Pulszeit benutzt. Initialisierung auf normal operation, TOP 0xFFFF, clk/1 = kein Prescaling.
Die Pulse werden von einem PCINT0 am PIN PB5 eingelesen. Die entsprechend geschaltete LED zeigt mit Dimmgrad optisch die eingelesenen Servopulse eines potentiometergesteuerten Servotesters - funktioniert.
Die Zeit vom Pulsstart bis zum Pulsende, PB5=hig bis PB5=low wird in der ISR von PCINT0 ausgelesen: bei Pulsanfang <=> PB5=high, wird OCR1A auf Null gesetzt, bei Pulsende <=> PB5=low, wird der Stand von OCR1A in eine Variablen tPULS (volatile int16/int16_t/ tPULS;x) übernommen. Die Variable tPULS ist aus Kompatibilitätsgründen signed integer.
Zur Funktionskontrolle wird der Wert tPULS alle Sekunden über UART ausgegeben. Die betreffenden Codezeilen sind hier :


// ================================================== =========================== =
// === Initialisierung v Timer1 mega328/20 MHz zur Messung Impulsdauer Servo
// Dokumentation ATmega328P_8271I_10/2014.pdf, siehe Seitenangaben
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
void TC1TMR_init(void) // Init Tmr/Cntr 1, 8-Bit auf 20 kHz = 50 µs
{ //
TCCR1B |= (1<<CS10); // No Prescaler Clock <- CPU DOC 134
//TCCR1B |= (1<<WGM12); // WGM00:13=0=> normal operation, TOP 0xFFFF 132
TIMSK1 &= ~(1<<OCIE1A); // Tmr/Cntr2 CompareA interrupt disabled
TIMSK1 &= ~(1<<OCIE1B); // Tmr/Cntr2 CompareB interrupt disabled
//
} // Ende void TC1TMR_init(void)
// ================================================== =========================== =



// ================================================== =========================== =
ISR(PCINT0_vect) // PCINT0 triggert bei ANY edge => bei PB5=high
{ // Start der Messung, bei PB5=low Wert übernehmen
// - - - - - - - - - - - - - - - -
if ( (IsBitSet ( PINB, 5))) // WENN der ServoPULS beginnt, dann OCR1A nullen
{ //
OCR1A = 0; // Timer zurücksetzen
SetBit ( PBLED, LBb ); // blLED an, PORTB, blLED auf PB2
} // weiter mit if ( (IsBitSet ( PORTB, 5))
else //
{ //
tPULS = OCR1A; // Übernimm den Wert
ClrBit ( PBLED, LBb ); // blLED aus, PORTB, blLED auf PB2
} // Ende if/else ( (IsBitSet ( PINB, 5)))
//
} // Ende ISR(PCINT0_vect)
// ================================================== =========================== =



// ================================================== =========================== =
// . . . .
s16 wOCR1A; // Wert von OCR1A zum Ausgeben, 16 Bit
// . . . .
while ( 1 ) //
{ //
wms ( 1000); //
cli(); wOCR1A = tPULS; sei(); // Wert des Servopulses auslesen
uputs0 ("\r\tOCR1A ist aktuell "); uputs0i ( wOCR1A );
} // Ende while ( 1 )
// ================================================== =========================== =

Aktuell:
Der Stand von OCR1A/tPULS wird stets mit "0" ausgegeben, da funktioniert also keine Zeitmessung. Die LED zeigt durch die ISR(PCINT0_vect) die Potentiometerbewegung des Servotesters korrekt an (fade-in bzw. fade-out). Der Wert tPULS ist aus Kompatibilitätsgründen signed integer; ein Überlauf >32767 würde ja trotzdem per UART angezeigt

Problem:
Irgendwo steckt ein Programmierfehler, ich sehe den nicht. Oder stimmt die Timernutzung so nicht ?
Danke im Voraus für die Hilfe

Searcher
15.03.2016, 14:03
;) Wodurch wird denn OCR1A hochgezählt?

Man könnte TCNT1 bei Pulsbeginn speichern und bei Pulsende die Differenz des aktuellen TCNT1 zum gespeicherten ausgeben.

Gruß
Searcher

oberallgeier
15.03.2016, 15:47
.. Wodurch wird denn OCR1A hochgezählt? .. Man könnte TCNT1 bei Pulsbeginn speichern ..Danke. Hols der Geier, steht ja klar in der Dokumentation, S. 114:

/* Read TCNT1 into i */
i = TCNT1;Und ich D...ussel lese dauernd das OCR1A. Nun steht stattdessen TCNT1 . . und alles läuft bestens. Danke Searcher!

oberallgeier
16.03.2016, 08:48
Zu allem Übel kann ich jetzt aber den Weg nicht mehr finden, wie dieses Thema als [Erledigt] markiert wird :-/

Searcher
16.03.2016, 10:04
Hols der Geier ... :) nicht schlecht.

Wen es einmal trifft :| ... Ganz oben, zwischen der Threadüberschrift mit "Thema:" und Deinem ersten Text gibt es eine Menüleiste unter anderem mit "Themen-Optionen". Aufklappen und unten sollte es die Auswahl "Markiere dieses Thema als erledigt ..." geben.

Ob die Auswahl zur Verfügung steht scheint jedoch abhängig vom Forum zu sein, ob man eingeloggt ist oder nicht und eventuell weiteren Unbekannten.

Gruß
Searcher

oberallgeier
16.03.2016, 10:17
.. Wen es einmal trifft :| .. Ob die Auswahl zur Verfügung steht scheint jedoch abhängig vom Forum zu sein .. und eventuell weiteren Unbekannten ..Genau. Ich habs eingeloggt probiert, als Gast, nicht eingeloggt, mit oder ohne Adblock, bei mir kommt unter [Themen-Optionen] (da hatte ich auch alle möglichen Forums-log-on-Versionen getestet) immer nur das Flyout

Druckbare Version zeigen
Thema weiterempfehlen…
Thema abonnieren…
Egal, denn ansonsten ist diese Woche, diesen Monat, bei mir eher das Winner-Flag gesetzt *ggg*

Trotzdem danke ich Dir.