Horst A. schrieb:
> Ich habe absolut keine Idee warum und woher die kommen.
Du kommen daher, weil
> wenn er vielleicht etwas umständlich
So ganz kann ich noch nicht erkennen, was eigentlich die Idee bei dieser
Pulsgenerierung ist. Aber egal was die Idee ist, sie ist deutlich zu
kompliziert und umständlich.
Viel einfacher.
Dein Timer erreicht ...
1 | 8000000 / 8 // wegen Vorteiler
|
2 | 1000000 / 256 // wegen 8 Bit Timer und Overflow Interrupt
|
3 | = 3906.25
|
... mal pro Sekunde den Overflow. In Zeiteinheiten sind das
1 | 1/3906 = 0.000256 Sekunden oder 0.256 Millisekunden
|
gut. Um damit 20 Millisekunden abzuzählen, muss also eine Variable in
diesem Takt bis 78 zählen. Der Zeitbereich 1 bis 2 Millisekunden wird
dabei durch Zählerwerte von ca 4 bis ca. 7 abgedeckt (was für eine
Servolösung deutlich zuwenig sein wird. Aber seis drumm, wenn du das
Servo nur so ungefähr von einer Endstellung zur anderen fahrn lassen
willst, dann reicht das erst mal. Ausserdem gehts ums Prinzip)
Damit haben wir mal die relevanten Zahlen.
d.h. du lässt im Timer Interrupt eine Variable hochzählen. Wenn die den
Wert 78 erreicht hat, dann lässt du sie wieder bei 0 anfangen. Wenn du
bei einem Wert von 0 in dieser Variablen den Pin auf 1 setzt und bei
einem Wert von 4 wieder auf 0, dann hast du damit am Pin einen Puls
erzeugt, der ca 1 Millisekunde lang ist und der sich (weil die Variable
alle ca 20ms wieder auf 0 gesetzt wird und von dort wieder hochzählt)
alle ca 20ms wiederholt.
(Ich nenne die Variable mal timeCnt)
1 | uint8_t timeCnt;
|
2 |
|
3 | ISR(TIMER0_OVF_vect)
|
4 | {
|
5 |
|
6 | timeCnt++;
|
7 | if( timeCnt == 78 )
|
8 | timeCnt = 0;
|
9 |
|
10 | if( timeCnt <= 4 )
|
11 | PORTD |= ( 1 << PD1 );
|
12 | else
|
13 | PORTD &= ~( 1 << PD1 );
|
14 | }
|
Ich hab absichtlich hier die Sache nicht ganz zeiteffizient gemacht. Das
Prinzip ist einfach. Ich teile die 20ms (repräsentiert durch timeCnt,
das bis 78 zählt) einfach auf. jedesmal wenn timeCnt verändert wird,
sehe ich nach, in welchem 'Bereich' sich die aktuelle Zeit befindet.
Muss der Pin auf 1 gesetzt werden oder auf 0, abhängig davon, ob wir
noch im 'Pulsteil' des Signals sind, oder ob wir schon im Pausenteil
sind.
Die Pulslänge wird durch die '4' eingestellt. Wenn die noch variabel
sind, dann kann man von 'ausserhalb' der ISR mitteilen, wie lange diese
Pulslänge sein soll.
1 | volatile uint8_t pulsLaenge = 4;
|
2 | uint8_t timeCnt;
|
3 |
|
4 | ISR(TIMER0_OVF_vect)
|
5 | {
|
6 |
|
7 | timeCnt++;
|
8 | if( timeCnt == 78 )
|
9 | timeCnt = 0;
|
10 |
|
11 | if( timeCnt <= pulsLaenge )
|
12 | PORTD |= ( 1 << PD1 );
|
13 | else
|
14 | PORTD &= ~( 1 << PD1 );
|
15 | }
|
Verändere die Variable pulsLänge (mit Werten zwischen 4 und 7) und die
ISR generiert dir entsprechende Servopulse.
1 | ...
|
2 |
|
3 | // Testprogramm: lässt das Servo alle 5 Sekunden in die
|
4 | // jeweils andere Endstellung fahren
|
5 |
|
6 | int main()
|
7 | {
|
8 | DDRD |= ( 1 << PD1 ); // Pin auf Output
|
9 |
|
10 | ....
|
11 |
|
12 | while( 1 ) {
|
13 |
|
14 | pulsLaenge = 4; // Endstellung links
|
15 | delay_ms( 5000 );
|
16 |
|
17 | pulsLaenge = 7; // Endstellung rechts
|
18 | delay_ms( 5000 );
|
19 | }
|
20 | }
|