
Zitat von
Destrono
... bräuchte den Timer zur Drehzahlbestimmung am Motor ...
Ich weiß nicht, wieviele Lösungsmöglichkeiten es an Atmel-Megas bzw. in C gibt. Meine Lösung ist nur eine davon, sie läuft. Das Konzept stammt aus einer Zeit, in der meine C-Kenntnisse noch bescheidener als heute waren; es ist also sicher KEIN Optimum. Mir ist klar, dass die Zeitmessung mit Auslesen des aktuellen Counterstandes genauer wäre - wäre aber eben ein anderer Lösungsweg, den ich in der Konzeptphase nicht schaffte.
Diese Zeitmessung hat als Zeitsignal einen 50 µs-Takt mit dem Timer2 am mega168/328 - damit brauche ich bei 20 MHz (wenn ichs grad richtig im Kopf habe) unter 5 % CPU-Zeit bzw. knapp 60 Maschinenbefehle (*.lls). In der ISR wird ein 2Byte-Counter hochgesetzt - theoretisch geht das also über 3 sec gut, praktisch zählt diese Uhr eine Sekunde bis der Counter zurückgesetzt wird. Ausgelesen wird diese Boardzeit in einer ISR, die vom extINT ausgelöst wird, der auf die steigende Flanke einer Gabellichtschranke mit vier Schlitzen an der Motorwelle anspricht. Max. Drehzahl des Motors unter 800 Hz, dh. weniger als 2400 Hz Interrupts an der Gabellichtschranke. Derzeit wird nur jeder zweite Interrupt gezählt, so als hätte die Encoderscheibe nur zwei Schlitze *ggg*. Die Timerinitialisierung setze ich als geläufig voraus. Die ISR für die Boardzeit sieht so aus:
Code:
/* ============================================================================== */
/* === Nicht unterbrechbare ISR für timer2 ===================================== */
/* Routine zählt hoch im Takt 20 kHz = 50 µs. Der Zählerwert wird von den ISR für
EXT_INT0 und -INT1 ausgelesen und den Werten Iz_yseci zugewiesen ...... */
ISR(TIMER2_COMPA_vect) // Vektor 7
{
if (Izeit_1 < Izthrznt) //Interrupt-Timer = 0 ... 19 999 ... (1 sec blink)
{
Izeit_1 ++; // ###>>> Izeit_1 ist aktuell int16_t ==>>
} // Izeit_1 bleibt bis 32000 in der int16-Grenze
else
{
PORTC ^= (1<<PC5); // LED auf Port PC5/I2C/SCL toggeln
Izeit_1 = 0; // ansonsten: Rückstellen auf Null
icntdwn = icntdwn + 1; // Countdownzähler hoch(!!)zählen
if (icntdwn < 0) // Countdownzähler geht maximal 9 Std.
icntdwn = 0;
if (Iencdr0 == Ienc0alt) { Iz_diff0 = 0; }
}
}
/* ============================================================================== */
Nachteil: Bei hohen Drehzahlen habe ich Werte um 13 tupsi (Timer Units Per Sensor Interrupt) - das ist also recht grob für die Regelaufgabe. Eine Drehrichtungserkennung ist nicht möglich - das liegt aber nicht an der Zeitmessung. Eine Stillstandserkennung ist nicht so ohne weiteres möglich, derzeit wird ein hoher Zählerstand als Stillstand definiert.
Vorteil: Es geht kein Zeitbruchstück verloren, übrige "Zeitbruchteile" werden der folgenden Messung zugeschlagen. Das dadurch auftretende Flattern des Zeitsignals durch diese Zeitbruchteile um den tatsächlichen Wert wird vom Regler ausgebügelt. Ausserdem wird dieser 50µs-Takt für andere Aktionen als Zeitsignal genutzt. Die toggelnde LED auf PC5 ist ein praktisches Signal für die Timerfunktion. Der ebenfalls mitlaufende Countdown icntdwn wird (ebenfalls) für Zeitmessungen benutzt, er geht theoretisch für Zeitmessungen bis 18 Stunden mit Sekundengenauigkeit.
Lesezeichen