Umbau eines handelsüblichen Modellbau-Servos als Antriebseinheit
(EN google-translate)
(PL google-translate)
Es ist möglich einen Servo als Antiebseinheit umzurüsten. Dazu wird die Stoppnase des Antriebszahnrades entfernt. Außerdem wird der Mitnehmer des Potentiometers entfernt, es exakt auf Mittelstellung gebracht (Messung beider Widerstandsanteile) und mit Sekundenkleber fixiert.
Während sonst ein Regelkreis bei einer Differenz von PWM-Breite und aktuell durch das Potentiometer angezeigtem Winkel zum Ausregeln der Differenz zwischen Soll- und Ist-Winkel genutzt wird, ist nun die Drehgeschwindigkeit des Servos PWM-abhängig, da es bei der nun konstanten Sollstellung unterschiedlich große Regelabweichungen "vorgaukelt".
Es wird ein preiswerter Standard-Typ mit Kunststoffgetriebe verwendet (Modelcraft RS-2).
Bild 0-1: Öffnen der Unterplatte eines Servos mit der Elektronik und vorsichtiges Heraushebeln dieser. Rechts unten sind die Anschlüsse des Potentiometers zu sehen.
Bild 0-2: Die Stoppnase des Antriebszahnrades kann mit Hilfe eines Elektronikschneiders entfernt werden. Es kostet einige Mühe alle Reste an der Oberfläche gründlich zu entfernen. Unbedingt ist darauf zu achten, niemals mit dem Schneider an die Ritzel des Zahnrades zu kommen!
Bild 0-3: Hier wird die Mittelstellung des Potentiometers gesucht. ACHTUNG: Es ist nicht nötig das Potentiometer wie hier herauszuschneiden und dann wirder anzulöten. Das Herauslösen von Platine mit Servo ist auch mit intakter Verbindung möglich!
Bild 0-4: Herausgelöste Platine mit intaktem Potentiometer.
Bild 0-5: Aufweiten der Bohrungen der Verbindungsscheibe auf 3mm, Durchbohren von Modellbauradfelgen. Es können 3mm Schrauben mit 20mm Länge zur Radbefestigung verwendet werden.
Bild 0-6: Fertiger Testaufbau.
#include <avr/io.h> int main(void) { uint8_t akku; uint16_t position = 108; DDRB = 0b00000000; DDRC = 0b11111111; TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (1<<WGM11) | (1<<WGM10); TCCR1B = (0<<ICNC1) | (0<<ICES1) | (0<<WGM13) | (0<<WGM12) | (0<<CS12) | (1<<CS11) | (1<<CS10); DDRD |= (1<<PB5) | (1<<PB4); //auf Ausgang setzen. OCR1A = position; //PWM-Breite setzen (entspricht für Servo auf 0 Grad). OCR1B = position; //PWM-Breite setzen (entspricht für Servo auf 0 Grad). PORTC = position; while(true) { akku = PINB; if( position<144 && (akku & 0b00000011) == 1) //Taster PB0 gedrückt { position++; PORTC = position; OCR1A=position; OCR1B=position; while( (akku & 0b00000011) == 1) akku = PINB; } else if( position>72 && (akku & 0b00000011) == 2) //Taster PB1 gedrückt { position--; PORTC = position; OCR1A=position; OCR1B=position; while( (akku & 0b00000011) == 2) akku = PINB; } } return 0; }
Code 0-1: Testprogramm für den Servoantrieb.
Übung
|
|
Bild 0-7: Timer-Mode-Tabelle für Timer 1 des ATmega32, Quelle: Datenblatt Atmel, Seite 107.
|
Musterlösung
Modus 10 erlaubt es, die Zählobergrenze durch Belegung des Registers ICR1 festzulegen. Da dieser Modus volle 16 Bit Verwendet, gibt es hier eine grosse Bandbreite an Einstellungsmöglichkeiten. Die Festlegung der passenden Einstellungen zur Servo-Ansteuerung mit hoher Auflösung entnehmen Sie bitte den Kommentaren des folgenden Quelltextes, bzw. den Erläuterungen in der Vorlesung:
Servo hin und her schwenken lassen, wenn Taster gedrückt wird
|
Anschluß eines Servos:
|
Bild 0-8: servo Steckbrett.
|
#include <avr/io.h> //N CS12 CS11 CS10 //1 0 0 1 //8 0 1 0 //64 0 1 1 //256 1 0 0 //1024 1 0 1 //Datenblatt S. 107: //PWM-Modus Nr. 10: //TOP = ICR1 //16 Bit //Phasenkorrekt //WGM13..10: 1010 //fpwm = fclk/(2*N*TOP) // //10..20ms == 100Hz .. 50Hz // //fpwm = 2457600/(2*1*15360) = 80Hz == T=0,0125s //1 Schritt == 0,0125/15360 = 0,000000814 //1..2ms == 1228,5 .. 2457 // Mitte: 1842 #define POSMAX 2457 #define POSMIN 1229 #define POSMITTE 1842 int main(void) { DDRD |= 0b10000000; DDRB &= 0b11111110; PORTB |= 0b00000001; int richtung = 1; uint16_t position = POSMITTE; long pause; ICR1 = 15360; TCCR1A = (1<<COM1A1) | (0<<COM1A0) | (1<<COM1B1) | (0<<COM1B0) | (0<<FOC1A) | (0<<FOC1B) | (1<<WGM11) | (0<<WGM10); TCCR1B = (0<<ICNC1) | (0<<ICES1) | (1<<WGM13) | (0<<WGM12) | (0<<CS12) | (0<<CS11) | (1<<CS10); DDRD |= (1<<PB5) | (1<<PB4); //auf Ausgang setzen. OCR1A = position; //PWM-Breite setzen (entspricht für Servo auf 0 Grad). OCR1B = position; //PWM-Breite setzen (entspricht für Servo auf 0 Grad). while(1) { OCR1A=position; OCR1B=position; if(position > POSMAX || position<POSMIN) richtung = -richtung; if( (PINB & 0b00000001)==0 ) position+=richtung; else position=POSMITTE; for(pause=0;pause<500;pause++) DDRC = 0; } }
Code 0-2: servo.c