Hoi zäme, ich möchte einen Gedankengang mit der Schwarmintelligenz verifizieren: Ich möchte ein klassisches RC-Servo Signal mit einem Tiny85 ausmessen und auf ein PWM spiegeln. Der selbe Ansatz, der mir eingefallen ist habe ich auch mehrfach im Netz gefunden: Da der Tiny keinen InputCapture hat und nur 8 Bit breite Timer Register ist der Ansatz, eine TimerOverflow ISR zum inkrementieren eines Counters zu nutzten und eine PinChange ISR, um die Flanken zu erkennen, wo die Pulsdauer gebildet wird á la pulseDuration = overFlowCnt*256 + timerVal >Mein Eindruck ist, das Ergeniss jittert ordentlich, weil bei bestimmten >Timings Raiseconditions zwischen Overflow und Pinchange auftreten? Mir ist nun in den Sinn gekommen, einfach in Präinterrupt-Zeiten zurück zu gehen und den ganzen Programfluss zum Polling eines Signalpins zu nutzten. Bei Fsys = 8Mhz und z.B. einer Zielauflösung von 200Ticks/Millisekunde, bleiben 40 Zyklen. In diesem Fall kommt einem die ewige Inactivezeit des klassischen RC-Servo Signales zur Hilfe, in der man alles mögliche machen kann. Ich denke, man kann hier noch deutlich schneller als 40 tick breite Timeslote gehen. In Pseudocode stelle ich mir das so vor tickCntr = 0; while(pin == LOW); //wait for rising edge ResetAndStartTimer(); while(pin == HIGH)// wait for falling edge and meassure the time { while(Timer < 40);// create equidistance time slots tickCntr++; } DoSomethingWithTickCntr(); // is allowed to take "long" since signal is 18ms inactive.
:
Gesperrt durch Moderator
Zu Hause und ausprobiert - mit dem Polling-Ansatz habe ich gute Ergebnisse. Systemtakt ist 8Mhz, Timer 0 läuft mit Prescaler = 1. Um zum Polling zeitlich äquidistante Slots zu schaffen wird TCNT0 auf kleiner 16 geprüft. Das erzeugt 2µs lange Zeitslots und bei einer Auslenkung von 500µs entsprechend 250 "Ticks". Das Konzept ist, dass die Auslenkung etwas dirty eben ein bisschen größer gemacht werden muss als +-500µs, um die für das PWM 255 voll zu kriegen. Zu diesem Kern habe ich noch ein bisschen Logik gedichtet, die mit zwei Pins ein Forward und Backward Enable macht und bei Übergang eine Verzögerung erzeugt, um einer eventuellen H-Brücke etwas Zeit zu geben. Dazu gibt es um den Nullpunkt herum einen Totbereich, damit das ganze in "Neutral" nicht laufend zwischen vorwärts und rückwärts pendelt.
1 | #include <avr/io.h> |
2 | #include <stdint.h> |
3 | |
4 | #define NEUTRAL 663 // due to 2µs timebase => 1300µs
|
5 | #define DEAD_BAND 5
|
6 | |
7 | #define NEUTRAL_UPPER NEUTRAL+DEAD_BAND
|
8 | #define TOP NEUTRAL_UPPER+255
|
9 | |
10 | #define NEUTRAL_LOWER NEUTRAL-DEAD_BAND
|
11 | #define BOTTOM NEUTRAL_LOWER-255
|
12 | |
13 | volatile static uint16_t pulseLength = 0, state = 5; |
14 | |
15 | |
16 | /*
|
17 | PB1 PWM Out / OCR1A
|
18 | PB2 Backward Enable
|
19 | PB3 "InputCapture"
|
20 | PB 4 Forward Enable
|
21 | */
|
22 | |
23 | int main(void) |
24 | {
|
25 | DDRB = 0b00010110; |
26 | |
27 | TCCR0B = 1; |
28 | |
29 | TCCR1 = 0b01100001; |
30 | OCR1C = 255; |
31 | |
32 | while(1) |
33 | {
|
34 | while((PINB & 8) == 0); |
35 | TCNT0 = 0; |
36 | pulseLength = 0; |
37 | while((PINB & 8) == 8) |
38 | {
|
39 | while(TCNT0 < 16); // creates timeslots with 2µs length |
40 | TCNT0 = 0; |
41 | pulseLength++; |
42 | }
|
43 | |
44 | if(pulseLength > NEUTRAL_UPPER) // grater than |
45 | {
|
46 | if(state == 8) |
47 | {
|
48 | DDRB |= 0b00000010;//set Pin to output |
49 | if(pulseLength > TOP) pulseLength = TOP; |
50 | pulseLength -= NEUTRAL_UPPER; |
51 | OCR1A = pulseLength; |
52 | PORTB |= 0b00010000; |
53 | }
|
54 | else
|
55 | {
|
56 | OCR1A = 0; // set PWM to 0% dutycycle |
57 | DDRB &= 0b11111101;//set Pin to input |
58 | PORTB &= 0b11101011; // set fw/be enable low |
59 | state++; |
60 | }
|
61 | }
|
62 | else if(pulseLength < NEUTRAL_LOWER) |
63 | {
|
64 | if(state == 2) |
65 | {
|
66 | DDRB |= 0b00000010;//set Pin to output |
67 | if(pulseLength < BOTTOM)pulseLength = BOTTOM; |
68 | OCR1A = BOTTOM - pulseLength; |
69 | PORTB |= 0b00000100; |
70 | }
|
71 | else
|
72 | {
|
73 | OCR1A = 0; // set PWM to 0% dutycycle |
74 | DDRB &= 0b11111101;//set Pin to input |
75 | PORTB &= 0b11101011; // set fw/be enable low |
76 | state--; |
77 | }
|
78 | }
|
79 | else
|
80 | {
|
81 | OCR1A = 0; // set PWM to 0% dutycycle |
82 | DDRB &= 0b11111101;//set Pin to input |
83 | PORTB &= 0b11101011; // set fw/be enable low |
84 | |
85 | if(state > 5) state--; |
86 | if(state < 5) state++; |
87 | }
|
88 | }
|
89 | |
90 | }
|
Cool, nutzt es vielleicht tatsächlich jemandem - was hast du vor zu beuen? Bei mir ist´s ein einfacher Drehzahlsteller für kleinere Motoren.
Bin ich blind oder hast du einfach nur versucht den CTC-Mode (Clear Timer on Compare Match) mit Timer/Counter0 Output Compare Match A Interrupt durch eine while-Schleife nachzubilden? Warum verwendest du den Interrupt nicht und erzeugst deine Timeslots mit einer while-Schleife?
:
Bearbeitet durch User
>Bin ich blind oder hast du einfach nur versucht den CTC-Mode (Clear >Timer on Compare Match) mit Timer/Counter0 Output Compare Match A >Interrupt >durch eine while-Schleife nachzubilden? Stimmt, richtig gesehen >Warum verwendest du den Interrupt nicht und erzeugst deine Timeslots mit >einer while-Schleife? Weil ich nichts anderes machen will, als das PWM und Fw/Bw Pins. Da bin ich ohne springen zur ISR und dem was dabei sonst passiert eher schneller und kann falls gewollt die Slots kürzer machen.
Wobei es das Wert ist, dass zu untersuchen, ob sich der ISR-Overhead
unterbringen lässt, für das gewollte timing.
Bei meiner Lösung wird sich auch ein Jitter ergeben, da der Timer mit
Fsys läuft und die
>while(TCNT0 < 16);
am Ende auch einliest, vergleicht, conditioned-jumped - kann man gerne
bis >= 16 zählen
Hm... interessant, ich sehe, du hast eine
>ISR_NOBLOCK
Anweisung. Die sorgt sicher dafür, dass bei ISR-Entry das globale
Interrupt Enable wieder gesetzt wird.
:
Bearbeitet durch User
Jasson J. schrieb: > Die sorgt sicher dafür, dass bei ISR-Entry das globale > Interrupt Enable wieder gesetzt wird. So isses. Näheres über die verschiedenen Optionen für ISR gibts in der Hilfe für die avrlib.
Beitrag #6163635 wurde von einem Moderator gelöscht.
Beitrag #6260310 wurde von einem Moderator gelöscht.
Du könntest auch das Teil mit PLL auf 16MHz laufen lassen und hast mehr Zeit für andere Aufgaben...
Beitrag #6287325 wurde von einem Moderator gelöscht.
Beitrag #6288268 wurde von einem Moderator gelöscht.
Beitrag #6288270 wurde von einem Moderator gelöscht.
Dieser Beitrag ist gesperrt und kann nicht beantwortet werden.