Hallo,
inspiriert von diesem Thread, Solved: Servo Zittern in Verbindung mit anderen Librarys - Deutsch - Arduino Forum
war es ehrlich gesagt anfangs eine Machbarkeitsstudio, die jetzt tatsächlich funktioniert. Die loop wird nicht blockiert, die Servos werden exakt angesteuert, und während der Pulspause kann lustig kommuniziert werden. Ich stell es der Allgemeinheit zur Verfügung. Wer damit was anfangen kann oder möchte, nur zu. Hängt euer Oszi an die 4 Ausgänge. DigitalWrite wird man nicht finden, dass hat seinen Grund. Nur die Empfangsbehandlung habe ich hier rausgenommen bzw. wird übersprungen. Mir gehts mehr darum zu zeigen wie man es machen kann mit Timer und der seriellen. Der Code ist sowieso stark gekürzt und auf das wesentliche reduziert auch wegen den 9000 Zeichen. Noch weiter kürzen macht einen Sinn, deshalb hängt er dran.
Servo Steuerung mit Timer 2
- Timer 2 für Servopulse taktet nur wenn er zur Pulserzeugung benötigt wird
- loop wird nicht blockiert
- während der Servopulszeit wird nicht gesendet/empfangen
- gesendet wird nur während der Servopulspause, wenn Timer 2 gestoppt ist
- senden wird 2ms vorm nächsten Servopuls gestoppt, damit noch Zeit wäre für einen Empfang
- Timereinstellungen werden vorab berechnet
- man kann die Auflösung ° pro Schritt einstellen, 0,5° wären noch machbar, darunter nicht sinnvoll
- ausgehend von 1°/Schritt wird die T2 ISR aller 11µs aufgerufen
- zur Kommunikation wird Serial.1 verwendet, Serial.0 wäre für Debugging frei
Das wesentliche sind diese Funktionen:
int calc_pulscount (const int &grad)
{
int count = (int) (((((grad - WINKEL_R) * microSek_pro_Grad) + 1000) / ISR_refresh_Time) + 0.5);
return count;
}
void Timer2_Steuerung ()
{
static unsigned long last_ms = 0;
if (global_ms - last_ms > 19) { // ServoPuls Periodendauer
last_ms = global_ms;
P28_EIN;
P29_EIN;
P32_EIN;
run_Timer2();
}
if (global_ms - last_ms > 17) {
state_running_Timer2 = true;
}
}
ISR(TIMER2_COMPA_vect) // wird aller 11µs aufgerufen (Prescaler 8 und OCR2A 21)
{
P33_EIN; // Sichtbarkeit das Timer aktiv ist
static int pulsCounter = 0;
if (pulsCounter == pulsCountServo1) { // Impulsdauer Servo 1
P28_AUS;
}
if (pulsCounter == pulsCountServo2) { // Impulsdauer Servo 2
P29_AUS;
}
if (pulsCounter == pulsCountServo3) { // Impulsdauer Servo 3
P32_AUS;
}
pulsCounter++;
if (pulsCounter > COUNT_maxPULS) { // nach 2,4ms Timer stoppen
stop_Timer2();
pulsCounter = 0;
state_running_Timer2 = false;
}
P33_AUS;
}
void stop_Timer2 ()
{
TCCR2B &= ~( (1 << CS22) | (1 << CS21) | (1 << CS20) ); // Timer stoppen
}
void run_Timer2 ()
{
TCCR2B |= (1 << CS21); // Timer mit Prescaler 8 starten
}
void preSet_Timer2 ()
{
cli(); // Interrupts ausschalten
TCNT2 = 0; // Start 0
TCCR2A = 0;
TCCR2B = 0;
TIMSK2 = 0;
TIMSK2 = (1 << OCIE2A); // enable Compare Match A ISR
OCR2A = CompareMatch_TOP; // TOP Wert bestimmt mit Prescaler den Takt
TCCR2A = (1 << WGM21); // CTC
sei(); // Interrupts einschalten
}
verbesserte Version in #14
Servo_Timer2_Forum.ino (12.3 KB)
