Hallo!
Zuerstmal, ich hab mir schon einen Rechteck Generator mit Grafik LCD,
variabler Pulsweite und Frequenz gebaut.
Auch ne Stoppuhr im ms Sekunden bereich mit GLCD hab ich hin bekommen
aber ich bekomm es gerade nicht auf die Reihe ne simple Soft-PWM für nen
Servo zu ralisieren die so funktioniert wie man erwarten sollte.
ATMega16 bei 5V und 16Mhz
Fuse auf ext. Crystal / High Freq
Das ganze in C
Ziel ist, Frequenz 50Hz, das sind 20ms.
Pulsweite von 1,5ms bis 2,5ms
Takt nach Prescaler:
16000000 / 8 = 2000000
Sekunde je Takt:
1 / 2000000 = 0,0000005000
Ein überlauf bei einem OCR0 wert von 200:
0,0000005000 / 200 = 0.0001 Sekunden
Zählschleife im Interrupt macht daraus 20ms wenn "pwmcounter" einen Wert
von 200 hat:
0.0001 * 200 = 0,02 Sekunden
Jetzt wird "servo_pos[0]" mit "pwmcounter" vergliechen.
Eine Pulsweite von 1,5ms würde also einem "servo_pos[0]"-Wert von 150
entsprechen.
Eine Pulsweite von 2,5ms würde also einem "servo_pos[0]"-Wert von 250
entsprechen.
Da ist aber irgendwo ein Fehler drinn... Es geht nähmlich nicht, zum
nachmessen habe ich leider nichts da...
Ich hab aber rausgefunden das ein Wert von 5 bis 20 den Servo zum
bewegen bringt.
Habe drei verschiedene Servos:
Nummer1 geht mit werten von 5 bis 20
Nummer2 macht genau das gegenteil von Nummer1 mit werten von 5 bis 20
Nummer3 macht nur komische Sachen.
Wo hab ich den Fehler?
Aus dem Code:
1 | // soft-PWM loop counter
|
2 | uint8_t pwmcounter = 0;
|
3 |
|
4 | // servo positions
|
5 | volatile uint8_t servo_pos[10] = {15,16,16,16,16,7,22,40};
|
1 | // initialise servos and timer
|
2 | void init_servos(void) {
|
3 |
|
4 | // set servoport as output
|
5 | SERVODDR = 0xFF;
|
6 | SERVOPORT = 0xFF;
|
7 |
|
8 | // soft-PWM timer0 in ctc mode with prescaler 8
|
9 | TCCR0 = (1<<WGM01) | (1<<CS01);
|
10 |
|
11 | // enable timer0 compare match interrupt
|
12 | TIMSK = (1<<OCF0);
|
13 |
|
14 | // timer0 compare value
|
15 | OCR0 = 200;
|
16 | }
|
[c]
// timer0 soft-PWM interrupt
ISR(TIMER0_COMP_vect) {
// when counter value is servo value set pin low
if(pwmcounter == servo_pos[0]) {
SERVOPORT &= ~(1<<SERVO0);
}
// reset soft-PWM counter set all pins high
if( pwmcounter++ == 200) {
pwmcounter = 0;
SERVOPORT = 0xFF;
}
}
[c]