Lieber Besucher, herzlich willkommen bei: RCLine Forum. Falls dies Ihr erster Besuch auf dieser Seite ist, lesen Sie sich bitte die Hilfe durch. Dort wird Ihnen die Bedienung dieser Seite näher erläutert. Darüber hinaus sollten Sie sich registrieren, um alle Funktionen dieser Seite nutzen zu können. Benutzen Sie das Registrierungsformular, um sich zu registrieren oder informieren Sie sich ausführlich über den Registrierungsvorgang. Falls Sie sich bereits zu einem früheren Zeitpunkt registriert haben, können Sie sich hier anmelden.

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

1

Dienstag, 11. Januar 2011, 15:32

Servoreverser mit ATtiny

Hallo zusammen,

angeregt durch den Thread Projekt: Servoreverser im Pic - Bereich möchte ich einen Servoreverser auf Basis des ATtiny 24 basteln.

Zunächst soll nur die Laufrichtung eines Servos geändert werden sowie die Mittenposition einstellbar gemacht werden. Ein zweites Servo wird durchgeschleift.

Die Auswertung des PPM Signals soll via Input Capture geschehen, die Ausgabe des modifizierten Impulses an OC1B.

Der Schaltplan ist fertig, die Software werde ich mir im laufe der Woche vornehmen.

Könnt Ihr bitte mal über den angehängten Schaltplan schauen ob ich da grobe Schnitzer gemacht habe?

Danke und Gruß,
Stefan
»swessels« hat folgendes Bild angehängt:
  • Servoreverser.png

2

Dienstag, 11. Januar 2011, 17:04

RE: Servoreverser mit ATtiny

Hey Stefan,

was ich mir denke:
- die Widerstände R3 und R4 kannst du einfach weglassen
- R2 hätte ich auch weggelassen, pull-up oder pull-down ist IMHO wurst
- bei der Versorgung des uC hätte ich ein klein bisserl mehr Aufwand getrieben und noch nen Widerstand oder Bead eingefügt
- den Quarz brauchst du auch nicht, man kann ja die PPM Framelänge als Referenzzeit nehmen, braucht also nur eine ein klein bisserl geschicktere Programmierung (wurde im Beispiel von Thomas nicht gemacht, würde ich aber so machen)
- ohne Quarz würde man dann auch mit nem 8piner auskommen

Olli

hsh

RCLine User

Wohnort: Österreich

  • Nachricht senden

3

Dienstag, 11. Januar 2011, 17:04

Die internen Pull-up Widerstände haben ca. 30k Ohm. Mit deinen 10k an den Tastern schaffst du da keine sauberen low-Pegel. Wenn du Angst vor falscher Portkonfiguration hast, reichen 100Ohm als Schutzwiderstand vollkommen aus. Brauchen tut es die Widerstände aber nicht.
Umgekehrt fehlt ein Schutzwiderstand am Ausgangspin deines Servosignals. Wenn du einmal etwas verkehrt zusammenstecken solltest, fließt hier der maximale Strom den der Portpin liefern kann. Soweit ich weiß halten die Atmels das nicht dauerhaft aus. Hier wäre also ein Widerstand im Bereich 100-1k Ohm sehr zu empfehlen.
Den 10k Pull-down an der Impulsleitung würde ich mir sparen. Eher auch hier einen Schutzswiderstand zwischen den Portpin und die Impulsleitung.

Ob es den Quarz (Gewicht, Platz, Stoßempfindlichkeit) wirklich braucht, würde ich noch einmal durchrechnen. Bei BEC-Betrieb hat man es ja mit einer konstanten Spannung zu tun. Ein Temperaturbereich von 0-40° lässt im schlimmsten Fall 10% Abweichung erwarten. Vermutlich könnte man über die 20ms Framezeit oder die Mittelposition sogar nachkalibrieren.
mfg Harald

Space

RCLine User

Wohnort: Hasloh b. Hamburg

  • Nachricht senden

4

Dienstag, 11. Januar 2011, 22:54

Zitat

Original von hsh
Ob es den Quarz (Gewicht, Platz, Stoßempfindlichkeit) wirklich braucht, würde ich noch einmal durchrechnen. Bei BEC-Betrieb hat man es ja mit einer konstanten Spannung zu tun. Ein Temperaturbereich von 0-40° lässt im schlimmsten Fall 10% Abweichung erwarten. Vermutlich könnte man über die 20ms Framezeit oder die Mittelposition sogar nachkalibrieren.

Ein Quarz wird wirklich nicht benötigt, da Frequenzfehler im Takt sowohl auf den ICP Wert als auch auf den PWM Wert wirken und sich somit ausgleichen.

An Widerständen können alle eingezeichneten eingespart und wie bereits geschrieben am Ausgang ~100 Ohm als Schutzwiderstand. Ebenso würde ich vor dem ICP 1KOhm in Reihe vorsehen, da die Eingangsamplitude nicht als bekannt angenommen werden kann, da hier die Empfänger unterschiedlich sind.
Gruß

Thomas

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

5

Dienstag, 11. Januar 2011, 23:23

Hallo zusammen,

vielen Dank für Eure Antworten. Das R2 unnötig ist sehe ich ein, da sorgt ja schon der Empfänger für saubere Pegel. R3 und R4 sollten 1k sein, habe nur nach dem Kopieren vergessen den Wert zu ändern. Die habe ich bisher immer eingebaut wenn ich mit Tastern gearbeitet habe. Sind die wirklich nicht sinnvoll?

Die Widerstände an ICP und am Ausgang werde ich vorsehen.

Zitat

man kann ja die PPM Framelänge als Referenzzeit nehmen


Die ist aber nicht zwangsläufig konstant. Da wüsste ich nicht wie ich das machen sollte.
Ich möchte aber auch keine fertige Lösung, da lerne ich ja nichts....

Zitat

Bei BEC-Betrieb hat man es ja mit einer konstanten Spannung zu tun


Stimmt. Aber die Schaltung darf auch gerne an nem E-Akku funktionieren. Ok, da muß dann die Eingangsspannung auf 5V begrenzt werden, da fehlt also noch was.... Also entweder Z-Diode oder LP2950CZ3.3, wobei wir beim letzteren wieder bei der konstanten Spannung wären.....

Ich sehe schon, nochmal alles überdenken.

Gruß,
Stefan

6

Mittwoch, 12. Januar 2011, 00:17

Zitat

R3 und R4 ... Die habe ich bisher immer eingebaut wenn ich mit Tastern gearbeitet habe. Sind die wirklich nicht sinnvoll?
ich habe die noch nie eingebaut, und auch noch nie eingebaut gesehen.

Zitat

Die ist aber nicht zwangsläufig konstant. Da wüsste ich nicht wie ich das machen sollte.
jein. Ich kenne nur zwei Fälle: (a) sie ist konstant, (b) der Abstand des letzten PPM Signals des aktuellen Frames zum ersten PPM Signals des nächsten Frames ist konstant

Zitat

da Frequenzfehler im Takt sowohl auf den ICP Wert als auch auf den PWM Wert wirken und sich somit ausgleichen.
ist zwar richtig, nützt aber gar nichts, da irgendwo an irgendeiner Stelle trotzdem ein Absolutwert vorkommen muss, und der stimmt entweder oder man muss ihn implizit kalibrieren

Zitat

oder die Mittelposition sogar nachkalibrieren.
ginge verlässlich nur beim Start, berücksichtigt daher nicht Temperaturunterschiede während des Betriebs

der interne RC Oszillator ist sowohl Spannungs als auch Temperatur abhängig in einem Masse dass es erhebliche (%) Fehler geben wird, kommt IMHO also (ohne implizite Kalibrierung) nicht in Frage (ausser Stellgenauigkeit ist wurst)

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

7

Mittwoch, 12. Januar 2011, 09:52

Hallo,

anbei der revidierte Schaltplan. Bei R1 mit 100 Ohm bin ich mir nicht ganz sicher, sollte aber bei einer Maximalen Eingangsspannung bis 8,4V funktionieren. Die Z-Diode ist eine mit 5,1V.

Auf den Quarz möchte ich zunächst mal nicht verzichten.

Gruß,
Stefan
»swessels« hat folgendes Bild angehängt:
  • Servoreverser.png

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »swessels« (12. Januar 2011, 09:52)


haschenk

RCLine User

Beruf: Dipl. Ing.

  • Nachricht senden

8

Mittwoch, 12. Januar 2011, 13:33

Hallo Stefan,

du könntest noch überlegen, ob du statt einem 1 MHz-Quarz besser 8 MHz verwendest. Vermutlich willst du auf 1µs Timerauflösung kommen; die erreichst du dann auch mit dem Prescaler 8:1 statt 1:1. Aber alle andern Operationen/Befehle laufen dann 8x so schnell ab, was nur vorteilhaft ist (evtl. Jitter). Genauer könnte man das erst sagen, wenn man das Programm im Detail kennt.

Gruß,
Helmut

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

9

Mittwoch, 12. Januar 2011, 13:59

Hallo Helmut,

danke für den Input. Das Programm entwickle ich gerade. Vermutlich werde ich auch zumindest zum Testen 8MHz nehmen, da ich die Quarze auch liegen habe.

Ich bin jedenfalls gespannt ob ich das hinkriege....

Die Überlegung geht auch dahin 2 Servos einstellbar zu machen und die Impulslänge anstatt mit ICP via INT0 zu messen. Aber eins nach dem Anderen.

Gruß,
Stefan

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

10

Donnerstag, 13. Januar 2011, 07:32

Anbei mal die erste, sicherlich stark verbesserungswürdige, Version des Programms. Das verschieben der Mittelstellung ist noch nicht realisiert. Ich konnte es nur nicht testen, da ich mein Programmierkabel zu Hause vergessen habe..... ==[] ==[]
Es wird aber fehlerfrei übersetzt.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
/*
Servoreverser mit einstellbarer Mittelstellung
MCU ATtiny 24
Takt: 1MHz
RC-In: ICP (PA7)
RC-Out: OC1B (PA5)
Taster an PA3 und PA4
*/

#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>

volatile uint16_t start;        //Startwert Impulsmessung
volatile uint16_t stop;         //Endwert Impulsmessung
volatile uint16_t pulse;        //Impulslänge

int main(void) {
    
    uint16_t center;
    uint16_t pulse;
    
    //PB2 als Eingang, Pull-Up an
    DDRB &= ~(1 << PB2);
    PORTB |= 1 << PB2;
    
    //PORTA bis auf PA5 als Eingang, Pull-Up an
    DDRA &= ~( 1 << PA0 | 1 << PA2 | 1 << PA3 | 1 << PA4 |  1 << PA6 | 1 << PA7);
    PORTA |= 1 << PA0 | 1 << PA2 | 1 << PA3 | 1 << PA4 |  1 << PA6;
    
    //OC1B als Ausgang
    DDRA |= 1 << PA5;
    
    //Timer 1, Fast PWM, Mode 15, OC1B Non Inverting, Prescaler 1, IC Rising edge
    TCCR1A |= 1 << COM1A1 | 1 << WGM11 | 1 << WGM10;
    TCCR1B |= 1 << WGM13 | 1 << WGM12 | 1 << ICES1;
    
    //ICP Interrupt ein    
    TIMSK1 |= 1 << ICIE1;
    
    //Timer1 ein
    TCCR1B |= 1 << CS10;
    
    sei();
    
    while(1) {
    }
    
    return(1);
}

ISR(TIM1_CAPT_vect) {
    
    timestamp = ICR1;       //capturewert sichern
    
    if(TCCR1B & (1 << ICES1)) {
        start = timestamp;
    }
    else {
        stop = timestamp;
    }
    
    TCCR1B ^= 1 << ICES1;
    TIFR1 |= 1 << ICF1;
    
    if (stop < start) {
        pulse = stop + 19999 -start;
    }
    else {
        pulse = stop - start;
    }
}


Gruß,
Stefan

11

Donnerstag, 13. Januar 2011, 23:05

Hallo Stefan,

Zitat

Original von swessels
... und die Impulslänge anstatt mit ICP via INT0 zu messen.


Welches wäre der Grund?

12

Freitag, 14. Januar 2011, 01:12

PPM Framelänge auswerten statt Quarz

Servus,

habe mir mal ein paar Gedanken zu dem Thema gemacht und denke, man kann die PPM Framelänge zum Abgleich des internen Oszillators hernehmen. Allerdings werden die Impulse nicht immer den exakt gleichen Abstand haben, sondern man muß zur Auswertung den Mittelwert bilden. Der "Jitter" bei der Framelänge wird durch Steuerbewegungen bei den vorher übertragenen Kanälen verursacht.
Z.B., wenn auf Kanal 1 eine Bewegung über den vollen Ruderbereich (1 -> 2 ms) innerhalb 1/10 Sekunde erfolgt, verlängert sich dessen Impulslänge bei jedem Impulsdiagramm (also alle 20ms) um 200 Mikrosekunden. Um diesen Betrag wandern dann alle nachfolgenden Impulse nach hinten - für Kanäle >1 sieht es während dieser 1/10 Sekunde so aus, als wäre die Framerate nun 20,2 ms.
Für langsame Änderungen, z.B. durch Temperaturdrift, kann man die Framelänge über eine längere Zeit mitteln und so den Einfluß der Steuerbewegungen minimieren. Schnellere Änderungen der Oszillatorfrequenz durch eine nicht stabilisierte Versorgungsspannung wird man so aber nicht in den Griff bekommen.

Grüße,

Thomas

13

Freitag, 14. Januar 2011, 01:30

RE: PPM Framelänge auswerten statt Quarz

@Thomas:
Wenn man denn die Framerate als Synchronfrequenz nehmen will, dann geht das nur über den Start von Kanal 1. Alles andere wäre doch recht unpraktikabel. So wie den Schaltplan verstanden habe, soll ja auch das Summensignal ausgewertet werden, da muss ja dann eh eine Starterkennung her.

Zu Bedenken gebe ich, dass nicht alle Sender mit festen Framelängen arbeiten. Insofern würde ich eher eine Kalibrierung des Tinys vornehmen, oder eben einen Quarz verwenden. Ich finde ja den Aufwand hierfür vertretbar.

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

14

Freitag, 14. Januar 2011, 06:20

Zitat

Original von amm
Hallo Stefan,

Zitat

Original von swessels
... und die Impulslänge anstatt mit ICP via INT0 zu messen.


Welches wäre der Grund?


Hallo,

der Grund wäre die Impulslänge der beiden Servos mit OCR1A und OCR1B zu erzeugen. ICR1 benötige ich dann zum einstellen des Timers auf die Periodendauer von 20ms.

Die Servoimpulse erzeuge ich gerne in Hardware.

Gruß,
Stefan

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

15

Freitag, 14. Januar 2011, 06:23

RE: PPM Framelänge auswerten statt Quarz

Zitat

Original von amm
So wie den Schaltplan verstanden habe, soll ja auch das Summensignal ausgewertet werden, da muss ja dann eh eine Starterkennung her.


Nein, da soll nicht passieren. Es soll nur ein Kanal eingelesen und umgedreht werden. Z.B für LK mit ner 6 Kanal Funke.

Gruß,
Stefan

swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

16

Dienstag, 18. Januar 2011, 06:36

Servoreverser mit ATtiny

Hallo,

irgendwo hab ich da nen dicken Bock drin...... der erste ist beseitigt, ich hatte softwareseitig OCR1A und OCR1B vertauscht :wall:

Zum ausprobieren arbeite ich jetzt mit dem internen Oszillator auf 8MHz, CKDIV8 Fuse ist gelöscht, der Timer läuft jetzt mit prescaler 8. Grundsätzlich funktioniert es, allerdings mit extremen Jitter. :(

Wenn ich OCR1B mit einem festen Wert versehe tritt das Problem nicht auf und die Servoposition stimmtm, also liegt es an der Impulsmessung bzw. Impulsaufbereitung.

Könnt Ihr bitte noch einmal über den Code schauen ob ich da etwas grundsätzlich falsch mache?

Mein Gedanke wäre die komplette Messung und Aufbereitung anstatt in der Hauptschleife im Captureinterrupt zu erledigen.

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/*
Servoreverser mit einstellbarer Mittelstellung
MCU ATtiny 24
Takt: 8MHz
RC-In: ICP (PA7)
RC-Out: OC1B (PA5)
Taster an PA3 und PA4
*/
#ifndef F_CPU
    #define F_CPU 8000000UL
#endif

#include <avr/io.h>
#include <avr/eeprom.h>
#include <avr/interrupt.h>

volatile uint16_t pulse;        //Impulslänge
volatile uint8_t flag;

int main(void) {
    
    uint16_t center;
    uint16_t tmp;
    center = 1499;
    flag = 0;
        
    //PB2 als Eingang, Pull-Up an
    DDRB &= ~(1 << PB2);
    PORTB |= 1 << PB2;
    
    //PORTA bis auf PA5 als Eingang, Pull-Up an
    DDRA &= ~( 1 << PA0 | 1 << PA2 | 1 << PA3 | 1 << PA4 |  1 << PA6 | 1 << PA7);
    PORTA |= 1 << PA0 | 1 << PA2 | 1 << PA3 | 1 << PA4 |  1 << PA6;
    
    //OC1B als Ausgang
    DDRA |= 1 << PA5;
    
    //Timer 1, Fast PWM, Mode 15, OC1B Non Inverting, IC Rising edge
    TCCR1A |= 1 << COM1B1 | 1 << WGM11 | 1 << WGM10;
    TCCR1B |= 1 << WGM13 | 1 << WGM12 | 1 << ICES1;
    
    //ICP Interrupt ein    
    TIMSK1 |= 1 << ICIE1;

    //Timer auf 20ms Periodendauer einstellen, Servoimpuls auf Mittelstellung
    OCR1B = center;
    OCR1A = 19999;
    
    //Timer1 ein, Prescaler 8
    TCCR1B |= 1 << CS11;
    
    sei();
    
    while(1) {
    
        if (flag == 1){
        //prüfen ob sich die Impulslänge im erlaubten Bereich befindet
        if((pulse > 899) || (pulse < 2199)) {
            
            //Wenn ja, impulslänge berechnen
            if(pulse > center) {
                tmp = pulse - center;
                pulse = center - tmp;
            }
            else {
                tmp = center - pulse;
                pulse = center + tmp;
            }

            //Impulslänge einstellen
            OCR1B = pulse;
        }
        }//OCR1B=1500;
        flag = 0;
        
    }
    
    return(1);
}

ISR(TIM1_CAPT_vect) {
    
    static uint16_t start;
    static uint16_t stop;
    
    if(TCCR1B & (1 << ICES1)) {
        start = ICR1;
    }
    else {
        stop = ICR1;
    }
    
    //ICES toggle, Interrupt Flag löschen
    TCCR1B ^= 1 << ICES1;
    TIFR1 |= 1 << ICF1;
    
    //Impulslänge berechnen
    if (stop < start) {
        pulse = stop + 19999 - start;
    }
    else {
        pulse = stop - start;
    }
    flag = 1;
}


Danke und Gruß,
Stefan

haschenk

RCLine User

Beruf: Dipl. Ing.

  • Nachricht senden

17

Dienstag, 18. Januar 2011, 09:17

Hallo Stefan,

ohne daß ich mich nun in die Details deines Progs vertieft habe- mir kommt das unnötig kompliziert vor.
Um die 20 ms Framezeit brauchst du dich doch garnicht zu kümmern; mit dem Eingangsimpuls hast du schon den "pacemaker" für die Ausgabe...

Das Grundgerüst würde so aussehen:
1. Warte auf positive Flanke eines Eingangsimpulses
2. Wenn das passiert, diese "auszählen", bis negative Flanke
3. Länge des auszugebenden Impulses daraus berechnen
4. Diesen ausgeben
5. Zurück nach 1

Das kann man im Detail auf verschiedene Weise umsetzen, noch Plausibilitätsprüfungen usw. einbauen... Geht alles mit Timer 1; auch ohne Interrupts.

Wenn jetzt nicht ich einen Denkfehler drin haben, dann wird das recht einfach und übersichtlich.

Gruß,
Helmut

Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von »haschenk« (18. Januar 2011, 09:28)


18

Dienstag, 18. Januar 2011, 09:32

RE: Servoreverser mit ATtiny

Hey Stefan,

ich habe jetzt dein Program nicht in jedem Detail analysiert, aber mir scheint es etwas "kompliziert" und "kompliziert" neigt zu Fehlern...

Ich denke das mit dem Timer auf 20ms etc einstellen würde ich völlig sein lassen. So wie du das machst kann das IMHO nur problemlos funktionieren wenn deine 20ms (für den Timer) EXAKT mit der Framelänge deines Impulses übereinstimmt, wenn nicht gibts Synchroprobleme...

... und wenn du dem Timer seine volle Periode lässt, dann klappt das mit dem ICP auch völlig einfach mit nur pulse = stop - start.

In der ICP Routine brauchst du nur ein static, z.B. lastICR, dann wird die Routine auch übersichtlicher (je nach ToggleEinstellung kannst du lastICR als start oder stopp interpretieren, aber eigentlich brauchst du ja nur start).

Mir würden einige Varianten einfallen dass umzusetzten. Z.B.:
Wenn man den Timer nicht durchlaufend braucht oder hier keine "Skrupel" hat, könnte man es z.B. so machen, erst über ICP die Dauer einlesen, dann im Hauptprogram den Timer auf Null setzen und OCR1B entsprechend setzen. Vorteil, mit OVF kannst du leicht auf Signalverlust prüfen. Bei dieser Variante muss die Timerlänge natürlich länger als die längste Framelänge sein.
Manchmal oder oft will man aber lieber einen durchlaufenden Timer. Hier wieder mit ICP Dauer einlesen. Jetzt geht das mit dem PWM aber nicht, da es ja sonst wenn die 20ms nicht exakt passen zu Überschneidungen kommt. Du könntest den Impuls ganz schnöde einfach durch warten im Hauptprogram machen (bei dir kein Problem da der uC ja eh nichts macht aussser zu warten). Ansonsten habe ich das in solchen Fällen so gelöst dass ich einen OCR1-Interrupt nehme. Also Ausgang auf high, OCR1 auf TCNT1+Wartezeit, OCR1-Interrupt an, im Interrupt dann Pin auf low und OCR1 Interrupt aus.

Zitat

Mein Gedanke wäre die komplette Messung und Aufbereitung anstatt in der Hauptschleife im Captureinterrupt zu erledigen.
hier sicher noch kein Problem, i.A. aber kein guter Gedanke, Grundsatz: alles was man nicht in der ISR machen MUSS auch nicht dort machen...

EDIT: sehe gerade erst Helmuts Post. Helmut hat natürlich recht dass man das alles im HP nur mit "polling" machen kann, ich denke ich würde es trotzdem mit ISRs umsetzten, weil zukunftsträchtiger (d.h. wenn man dann doch plötzlich noch dieses und jenes einbauen will)...

Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von »OlliW« (18. Januar 2011, 09:35)


swessels

RCLine User

  • »swessels« ist der Autor dieses Themas

Wohnort: 31535 Neustadt, in der Woche HH

Beruf: Arbeitsplanung in der Luftfahzeugkomponenten - Instandsetzung

  • Nachricht senden

19

Dienstag, 18. Januar 2011, 12:29

Hallo Helmit, hallo Olli,

Zitat

Original von haschenk

Das Grundgerüst würde so aussehen:
1. Warte auf positive Flanke eines Eingangsimpulses
2. Wenn das passiert, diese "auszählen", bis negative Flanke
3. Länge des auszugebenden Impulses daraus berechnen
4. Diesen ausgeben
5. Zurück nach 1
.....
Geht alles mit Timer 1; auch ohne Interrupts.


sinngemäß habe ich nichts anderes vor. Nur irgendwie klappt das nicht richtig :(
Ich glaube das ich da irgenwo nen Denkfehler habe.

Auf den Input Capture Interrupt will ich eigentlich nicht verzichten, der ist ja für solche Zwecke geschaffen. Es ist ja auch der einzige der verwendet wird.

Zitat

Original von OlliW
Ich denke das mit dem Timer auf 20ms etc einstellen würde ich völlig sein lassen. So wie du das machst kann das IMHO nur problemlos funktionieren wenn deine 20ms (für den Timer) EXAKT mit der Framelänge deines Impulses übereinstimmt, wenn nicht gibts Synchroprobleme...


Daran habe ich gar nicht gedacht. Wobei es bei der Ansteuerung von LK wohl nicht auffallen würde.
Dein Ansatz ist gefällt mir aber auch.

Zitat

Zitat

Mein Gedanke wäre die komplette Messung und Aufbereitung anstatt in der Hauptschleife im Captureinterrupt zu erledigen.

hier sicher noch kein Problem, i.A. aber kein guter Gedanke, Grundsatz: alles was man nicht in der ISR machen MUSS auch nicht dort machen...


Das ist schon klar, aber wie Du schon sagst hat der Controller fast nichts anderes zu tun. Das einzige was noch dazu kommt ist die Einstellmöglichkeit der Mittelstellung inkl. ablegen im EEPROM. Das aber erst wenn die eigentliche Funktion gegeben ist.

In der Mittagspause habe ich mal ein wenig den Code geändert, die ISR ist kürzer geworden. Hier nur ab der Hauptschleife:

Quellcode

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
while(1) {
        if (flag == 1){
            if(pulse > center) {
                tmp = pulse - center;
                pulse = center - tmp;
            }
            else {
                tmp = center - pulse;
                pulse = center + tmp;
            }
            //Impulslänge einstellen
            OCR1B = pulse;
            flag = 0;
        }        
    }
    
    return(1);
}

ISR(TIM1_CAPT_vect) {
    
    static uint16_t start;
    static uint16_t stop;
    
    if(TCCR1B & (1 << ICES1)) {
        start = ICR1;                   //ICR1 sichern -> Startwert
        TCCR1B &= ~(1 << ICES1);        //Trigger auf fallende Flanke
        TIFR1 |= 1 << ICF1;             //ICP Interrupt Flag löschen (siehe Datenblatt)
    }
    
    else {
        stop = ICR1;                    //ICR1 sichern -> Stopwert
        TCCR1B |= 1 << ICES1;           //Trigger auf steigende Flanke
        TIFR1 |= 1 << ICF1;             //ICP Interrupt Flag löschen (siehe Datenblatt)
        //Impulslänge berechnen
        if (stop < start) {
            pulse = stop + 19999 - start;
        }
        else {
            pulse = stop - start;
        }
        flag = 1;
    }
}


Danke und Gruß,
Stefan

20

Dienstag, 18. Januar 2011, 13:15

also, Stefan, soweit ich das sehe hat sich an dem Program nichts an der Funktion geändert, warum glaubst du dann dass das nun besser funktionieren sollte 8(? Mir scheint du hast jetzt drei funktionierende Lösungsvorschläge bekommen, aber vielleicht bekommst du das mit deinem PWM-Ansatz ja auch (irgendwann :D) hin... :angel: (sorry musste jetzt sein).


volatile flag=0;
volatile pulse=0;

main{
Ports auf Eingang/Ausgang initialisieren;
ICP Flanke auf low->high;
ICP Interrupt ein;
Timer1 Prescaler 8;
sei();
while(1) {
if (flag == 1){
flag = 0;
if((pulse > 899) || (pulse < 2199)) {
TCNT1=0;
AusgangFürServo auf high;
OCR1B = 2198-pulse + 900;
OCR1B Interrupt an;
}
}
return(1);
}

ISR(TIM1_CAPT_vect) {
static uint16_t start;
if(TCCR1B & (1 << ICES1)) {
start = ICR1;
ICP Flanke auf high->low;
}else{
pulse= ICR1-start;
ICP Flanke auf low->high;
flag = 1;
}
}

ISR(TIM1_OCR1B_vect) {
AusgangFürServo auf high;
OCR1B Interrupt aus;
}