mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik Servo delay board


Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo an alle Experten,

ich habe ein kleines Projekt, das sich wie folgt darstellt:

Ich habe 3 Modellbauservos deren Verfahrgeschwindigkeit verlangsamt 
werden soll und das für jede Achse einzeln einstellbar. So siehts im 
Endeffekt aus:

Empfänger                    µC                    Servos
Kanal 1     PWM Messen    verzögern   PWM Ausgabe    Servo 1
Kanal 2     PWM Messen    verzögern   PWM Ausgabe    Servo 2
Kanal 3     PWM Messen    verzögern   PWM Ausgabe    Servo 3

Die Verfahrgeschwindigkeit soll über Potis eingestellt werden können.
Zuerst muss die Pulsweite ja gemessen werden. Dafür hab ich nen Atmega88 
genommen und die externen Interrupts genutzt (INT0, INT1, und PCI20). 
Wenn jetzt so ein ext. interrupt auslöst schaue ich nach ob das Level am 
PIN high ist und wenn ja dann kopiere ich mir den aktuellen Wert des 
Timer - Registers in eine Variable start. Geht der PIN auf low und dabei 
wird wieder der INT ausgelöst, dann speicher ich mir den aktuellen timer 
Wert in eine Variable end. Ziehe ich die beiden voneinander ab hab ich 
die Pulsweite. So jetzt ist der Wert der Soll - Wert für die PWM 
Ausgabe, jedoch soll diese ja verlangsamt ablaufen. Dafür hol ich mir 
den ADC Wert von einem Poti was zwischen GND und VCC hängt (Wertbereich 
von 0 bis 1023). Dieser Wert fungiert jetzt als Inkrementor für das PWM 
Output.
Beispiel:

Messung: 26000 (entspricht 1.625ms)
Aktuelle Ausgabe PWM: 24000 (enspricht 1.5ms)
Jetzt wird pro Hauptschleifen Durchlauf der Ausgabe PWM Wert mit dem ADC 
Wert für diesen Kanal addiert bis der Wert dem der Messung 
entspricht....

So sollte es sein.
Ich hab versucht das ganze mit einem Chip zu bewerkstelligen, jedoch 
leider ohne Erfolg. Jetzt ists so daß ein ATMega88 die Pulsweiten der 
drei Kanäle und die ADC Wert der Potis misst und diese an einen ATMega8 
per SPI weitergibt, der dann die PWM Ausgabe übernimmt. Klappt leider 
auch noch nicht so doll, aber das krieg ich schon noch hin.

Hat jemand vielleicht eine Idee wie sowas effizienter bzw. sogar mit 
einem Chip lösbar ist ?

Grüße,

Michael

Autor: uwegw (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
An welcher Stelle klemmt es denn? Hast du dir mal Zwischenergebnisse 
ausgeben lassen? Wie genau äußern sich die Probleme?

Normalerweise gibt der Empfänger die Impulse nacheinader auf die 
Ausgänge, weil sie auch so per Funk übertragen werden. Man könnte also 
auch alle Kanäle über Dioden auf einen einzigen Interrupt hängen und 
nacheinader messen. Dabei könnte man dann den Timer bei jedem 
Impulsbeginn neu starten und hätte so z.B. kein Probleme mit nem 
überlaufenden Zähler (wie hast du das bei dir abgefangen?). Den Start 
der Impulsfolge könnte man über die längere Pause zwischen dem letzen 
und dem ersten Kanal bestimmen und sich so synchronisieren.

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@uwegw: Also die Pulsmessungen sind soweit in Ordnung (hab sie per RS232 
mal ausgeben lassen), jedoch schwanken diese vereinzelt, was bei der 
Ausgabe dann zu einem leichten Servozittern führt. Dies konnte ich jetzt 
so lösen, daß immer ein Kanal nach dem anderen gemessen wird und nicht 
alle gleichzeitig.
-> Messung Kanal 1
* Schalte Interrupt für Kanal 1 ein
* Timer läuft immer durch
* Hole start - Zeit
* Hole end - Zeit
* Interrupt für Kanal 1 ausschalten
* Pulsweite berechnen (end - start), da ists egal ob in der Zeit ein 
Überlauf war oder nicht ! Variable als uint16 definiert.
<- Ende Messung Kanal 1

Bei manchen Empfänger (PPM) Modus gebe ich dir mit der sequentiellen 
Ausgabe Recht. Nicht jedoch bei IPD bzw. (S)PCM Empfängern. Da kommen 
die Signale synchron raus und genau so einen SMC20 DS von Graupner 
verwende ich.

Die Ausgabe muss eigentlich nicht synchron sein. Bis jetzt mach ich's so 
daß zwei Timer laufen. Ein 8er der mir alle 20ms einen Int auslöst, 
wonach dann der 16er gestartet wird und dann die vom 88er gemessenen 
Pulsweiten umgerechnet (dekrementiert bzw. inkrementiert) und dann 
sequentiell (erst Kanal 1 dann Timer-Reset, dann Kanal 2, ...) ausgibt.

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
1ms ist doch Anschlag an einer Seite des Servos, der relevante Teil ist 
doch aber nur bei 1ms - 2ms, also 1ms Änderung zu suchen. 1ms passt doch 
schon recht gut zu deinem ADC-Wert von 1024. Also von deinem Messwert 
1ms abziehen den Rest durch 1024 teilen und mal ADC-Wert rechnen. Zum 
Schluss noch 1ms addieren und fertig ist dein neuer Sollwert.
Wenn ich jetzt nichts übersehen habe, sollte das so klappen.

Viel Erfolg, Uwe

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Also.

Messwert ist z.B. p_soll = 24000 (entspricht exakt 1.5ms), ADC = 654

1ms ^= 16000

p_ausgabe = (p_soll - 1ms) / 1024 * ADC + 1ms

ergibt

p_ausgabe = (26000 - 16000) / 1024 * 654 + 16000
p_ausgabe = 8000 / 1024 * 654 + 16000
p_ausgabe = 7,8125 * 654 + 16000
p_ausgabe = 5190,375 + 16000
p_ausgabe = 21109

Wenn sich ADC und p_soll nicht mehr verändern, dann ist der Wert 
statisch. Er  sollte sich aber langsam dem soll-Wert annähern:

         ____30000____                    ____30000_______
         |                                /
_24000___|                   --> _24000__/


Ich hab das hier versucht mal zu skizzieren. Ein Sprung am Soll - 
Eingang soll dann am Ausgang den Wertverlauf verzögert nachbilden, aber 
dennoch diesen erreichen !

Grüße,

Michael

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Ach so meinst du das, -und was willst du jetzt mit dem Poti verändern?
Die Zeit bis Imp.soll = Imp.ist? Wenn ja, Timer mit ADC-Wert laden und 
wenn abgelaufen Imp.ist +(was du möchtest) bis Soll=Ist.

MFG Uwe

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Uwe: Ich hab mein Problem jetzt erst so richtig lokalisiert. Das 
Problem ist nicht die PWM Ausgabe sondern die Messung. Momentan läuft 
diese folgendermassen:
* 16 bit Timer starten, permanenter Durchlauf
* Der Empfängerausgang hängt direkt am externen Int Pin (INT0, interner 
Pullup aktiviert).
* Der externe Interrupt wird eingeschaltet und reagiert auf toggle.
* In der ISR wir abgefragt, ob der PIN high ist, wenn ja Starttimerwert 
speichern
* Beim zweiten auslösen des Ints und der PIN ist low dann Endtimerwert 
speichern.
* Die Differenz ist der Messwert der Pulsweite.

Diese Werte hab ich direkt per RS232 mal ausgeben lassen und im Gros 
sind diese auch korrekt. Problem sind nur "Ausreisser". Angenommen der 
Steuerknüppel liegt auf neutral, dann betragen die Messwerte rund 24200 
(enspricht rund 1.51ms, was passt). Aber vereinzelt, kommen auch 
Messwerte mit 8000 und auch mit 50000. Diese stören natürlich ganz 
gewaltig, denn bei den Werten fängt bei der Ausgabe das Servo zum zucken 
an.

Ich habe auch schon versucht die Werte in einem Bereich zu limitieren, 
sprich zwischen 18000(ca 1ms) und 300000(2ms). Dann wird es besser und 
die groben Ausreisser fallen raus, aber trotzdem, wenn der Knüppel 
verfahren wird treten Ausreißer im zulässigen Band auf .... --> 
Servozittern

Für Vorschläge wäre ich sehr sehr dankbar !

Grüße,

Michael



Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du ermittelst 3 Impulsbreiten vom Sender (Sollwerte)
Du erzeugst 3 Impulsbreiten für die Servos (Istwere)
Du liest 3 Potis ein (Verzögerungswerte)
Du hast also 3 Sollwerte und 3 Verzögerungswerte, mit denen Du Deine 3 
Istwerte manipulieren musst.

Ist Sollwert unter Istwert, dann musst Du den Istwert verkleinern.
Ist Sollwert über Istwert, dann musst Du den Istwert vergrößern

Der Betrag, um den der Istwert "dem Sollwert nachlaufen" soll, wird vom 
ADC-Wert bestimmt. Bei schnellem Nachlauf wird der Istwert in größeren 
Schritten dem Sollwert angenähert, bei mittlerem Nachlauftempo nur um 
einen Schritt, bei geringem nachlauftempo nur um einen Schritt, aber 
nicht bei jeder "Runde" (bei jedem Schleifendurchgang, z.B. durch die 
Impulsfolge des Senders synchronisiert).

Das alles passt (in ASM) problemlos in einen Mega48, der mit 1MHz 
internem Takt tuckert...

...

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Hannes,

genau da liegt mein Problem. Ich kann kein ASM ? C muss doch aber auch 
gehen oder ?

Irgend eine Idee warum meine Sollwerte ab und an "Ausreisser" enthalten 
?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> C muss doch aber auch gehen oder ?

Aber locker.
Da kriegst du noch eine Datenbank mit in den µC.

> Irgend eine Idee warum meine Sollwerte ab und an "Ausreisser"
> enthalten

Zerbrech mir schon die ganze Zeit den Kopf darüber.
Lass dir doch mal die Start- und die Endtimerwerte
dazu ausgeben. Vielleicht bringt das etwas Licht ins
Dunkel.

Die Gretchenfrage wird wohl sein:
Kommen die AUsreisser schon so vom Empfänger oder entstehen
sie im µC.

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hm. Gute Frage.
Ich nutze einen SMC20 DS mit Hold Funktion, von dem her kann man 
eigentlich Störungen als Ursache ausschließen. Komisch ist nur, wenn ich 
die Fernsteuerung ausschalte und der Empfänger die letzten korrekt 
empfangenen Signale ausgibt sind auch die Ausreisser weg. Kann es sein, 
daß der µC den Empfänger stört ?
Ich werde heute abend mal die Start und Endwerte ausgeben lassen und 
schauen was Sache ist. Zudem werde ich die EInts mal nicht mehr im 
reinen Toggle Betrieb betreiben sondern wirklich die Flanken abfragen 
die ich haben will.
Also für Startwert von low nach high und dann in der ISR umschalten für 
Int von high nach low. Vielleicht wirds dann besser.
Die Idee, daß alles auf einem µC läuft gefällt mir sehr gut!

Wie würde die Aufteilung der einzelnen Timer dann ausschauen ?

Vielleicht so:
* Messung mit 16bit Timer.
* PWM ausgabe mit ersten 8bit Timer (Signal alle 50Hz)
* Erzeugung der Pulsweite mit zweitem 8bit Timer

Danke für Eure Hilfe !

Grüße,
Michael

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was interessieren Dich die Ausreißer?

Du musst vom Sollwert doch nur wissen, ob er mehr vom Istwert abweicht, 
als eine "Nachlaufstufe". Dann änderst Du den Istwert in die 
entsprechende Richtung.

ASM-C
Das ist auch in C kein Problem, aber ich kann kein C.

...

Autor: Michael K. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes: Du meinst also eine relative Anpassung des Ausgangs, aber so 
ganz vorstellen kann ichs mir noch nicht. Wäre klasse, wenn Du den 
Programmablauf am Beispiel kurz skizzieren könntest !

Danke,

Michael

Autor: Michael K. (mmike) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,

anbei mal nen Log von der direkten Ausgabe des ATMega88 per RS232. Die 
Werte sehen traumhaft aus (hab auch ein wenig mit dem Knüppel agiert) 
und so langsam kann ich mir nicht mehr vorstellen, daß dieser Mist misst 
;-) !! Ich vermute jetzt eher, daß die SPI Verbindung Müll produziert 
(Bei der hab ich eh kein gutes Gefühl)! Momentan werden die Daten 
nämlich per SPI an den ATMega8 weitergegeben, der diese dann umrechnet 
und schlussendlich das PWM erzeugt. Aber vielleicht brauchts das ja 
nicht mehr, da schon einige Meinungen vorhanden sind die sicher sind, 
daß es auch mit einem µC geht ! Ich hoffe es sehr !
Ich werde die Tage mal weiter coden und versuchen alles auf den 88er zu 
bringen.

Danke an alle und ich werde sobald was brauchbares rausgekommen ist den 
Code mal hier einstellen.

Grüße,

Michael

Autor: Hannes (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Wäre klasse, wenn Du den
> Programmablauf am Beispiel kurz skizzieren könntest !

Hier
http://www.hanneslux.de/avr/mobau/7ksend/7ksend02.html
findest Du die Erzeugung von Impulsen für 7 Servos. Die Positionen 
werden mittels Potis und Taster eingegeben.

Um es für Deinen Zweck abzuändern müsstest Du:
- die LED und Aus-Taste an andere Ports hängen
- die Impulserzeugung auf 3..6 Kanäle begrenzen
- alle Impulseingänge an PB0..PB5 anschließen (PCINT 0..5)
- 6 Werte (16 Bit) im SRAM halten, die die Impulsbreiten der erzeugten
  6 Servoimpulse verkörpern
- 6 Werte 16 Bit im SRAM halten, die den Zeitstempel des Impulsanfangs
  aller 6 zu messenden Eingangsimpulse enthalten
- aus dem aktuellen ADC-Werte einen Werte berechnen, die das Tempo der
  Impulsänderung verkörpert und die Impulsbreitenänderung pro Zyklus
  bestimmt (Gain?)
- Eine ISR für PCInt0 einrichten und freischalten, in der Folgendes
  erfolgt:
  - Zeitstempel von Timer1 lesen (Software-ICP)
  - PINB einlesen und anhand des Zustands erkennen, ob Impulsanfang
    oder Impulsende den Int ausgelöst hat und um welchen Kanal es sich
    handelt
  - RAM-Pointer auf entsprechende Position im SRAM einstellen
  - bei Impulsbeginn Zeitstempel im SRAM sichern
  - bei Impulsende gesicherten Zeitstempel (den vom Imp-Anfang) vom
    aktuellen Zeitstempel subtrahieren und die Differenz (die gemessene
    Impulsbreite) im SRAM (Pointer +16, std) sichern
- in ISR tim1_compb die direkte Verrechnung von ADC-Wert zum Servoimpuls
  entfernen und die Servoimpulsbreite anhand alter Impulsbreite,
  eingelesenem Impulswert (im SRAM) und aktuellem Gain-Wert korregieren.

Das wars eigentlich auch schon. Ich möchte fast behaupten, dass der 
Mega48 bei 1 MHz internem Takt immernoch die meiste Zeit im Sleepmode 
verbringt.

...

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Hannes,

bin auch wieder im Lande und werde versuchen das heute abend mal in C zu 
bringen ! Vielen vielen Dank schon mal !

Grüße,

Michael

Autor: Michael K. (mmike) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,

irgendwie hab ich das Vorgehen immer noch nicht ganz durchblickt. Zudem 
sind mir noch einige Gedanken gekommen, die das Ganze erschweren 
könnten. Ich verwende ja einen SPCM Empfänger von Graupner, der die 
Eigenart hat die Servosignale quasigleichzeitig an die Ports zu legen 
(also nicht wie ein normaler PPM Empfänger der sequentiel vom PPM Signal 
die einzelnen Kanäle ausgibt !!). Daher könnte es schwierig werden in 
der ISR für PCInt0 den Kanal raus zu finden, der den Interrupt erzeugt 
hat. Da ich aber nur 3 verzögerte Kanäle benötige kann ich ja INT0 und 
INT1 auch benutzen und somit das Problem umgehen.

Anbei mal der C - Code mit "Deinen" Anweisungen umgesetzt bis es eben 
ausbeist.
Hier die Fragen dazu:
1. In welcher Betriebsart wird Timer1 genau verwendet ? (Normal?)
2. Wie genau funktioniert die PWM Ausgabe ? Ich habe ja 3 Kanäle, die 
ausgegeben werden müssen und das im 50Hz Takt. Werden diese sequentiell 
ausgegeben also:
        __
CH1: __|    |___
             ___
CH2: _______|     |______
                   __
CH3: _____________|    |_____________

3. Woher bekomme ich die 50Hz Taktung ? Separater Timer oder schon 
irgendwo versteckt eingebaut ?

Zu Deinem "Gain?":
Ich dachte mir den ADC Wert direkt als Inkrementor in die entsprechende 
Richtung abhänging vom Pulsweiten soll zu nutzen.

PWM soll         großes ADC Inc.          kleines ADC Inc.
     _____             _______                   ___________
    |                  |                       __|
    |                __|                    __|
    |               |                    __|
    |             __|                 __|
    |            |                 __|
____|      ______|            ____|



Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. (mmike) wrote unter anderem:

> Ich verwende ja einen SPCM Empfänger von Graupner, der die
> Eigenart hat die Servosignale quasigleichzeitig an die Ports zu legen
> (also nicht wie ein normaler PPM Empfänger der sequentiel vom PPM Signal
> die einzelnen Kanäle ausgibt !!). Daher könnte es schwierig werden in
> der ISR für PCInt0 den Kanal raus zu finden, der den Interrupt erzeugt
> hat.

Eigentlich nicht, dass müsste auch zu schaffen sein. Schau Dir mal die 
Entprellroutine von Peter Dannegger an, dabei nur den Teil, der die 
Flankenerkennung macht. Damit ist es mit sehr wenig CPU-Belastung 
möglich, für jeden Kanaleingang getrennt die steigende und fallende 
Flanke von bis zu 8 Bit parallel zu erfassen. Die PCINT-ISR muss also 
nur den Zeitstempel des freilaufenden Timer1 (am besten mit Zählfrequenz 
von 1 MHz) sichern und die Flankenerkennung ausführen, den Rest erledigt 
das Hauptprogramm.

Dieses muss bei gesetztem Impulsanfangsflag den Zeitstempel als 
Impulsbeginn des betreffenden Kanals sichern (Tabelle im SRAM, Kanal als 
Index) und natürlich auch das Flag wieder löschen, bei einem gesetzten 
Impulsende-Flag muss das Hauptprogramm (dieses löschen,) die Differenz 
zwischen aktuellem Zeitstempel und gemerktem Impulsbeginn bilden (das 
ist dann die gemessene Impulsbreite) und diese in einer SRAM-Tabelle 
sichern.

Selbst wenn alle Impulse zugleich beginnen, hat das Hauptprogramm 
genügend Zeit, den Zeitstempel für alle Kanäle als Impulsanfang zu 
sichern.
Auch wenn mehrere Kanäle zugleich enden, werden ja die entsprechenden 
Flags gesetzt und das Hauptprogramm kann einen Kanal nach dem anderen 
mit dem gleichen Zeitstempel behandeln.

Wo also ist das Problem?

> Da ich aber nur 3 verzögerte Kanäle benötige kann ich ja INT0 und
> INT1 auch benutzen und somit das Problem umgehen.

Dann hast Du mehrere separate ISRs, die sich gegenseitig verzögern 
können. Es reicht ja schon, dass die Timer-ISR und ADC-ISR zuschlagen 
können.

>
> Anbei mal der C - Code mit "Deinen" Anweisungen umgesetzt bis es eben
> ausbeist.

Für C bin ich zu blöd, ich kann (auf dem AVR) nur etwas ASM.

> Hier die Fragen dazu:
> 1. In welcher Betriebsart wird Timer1 genau verwendet ? (Normal?)

Der Timer läuft frei durch, keine ISR hat das Recht, am Zählerstand 
herumzudrehen. Dadurch können gleichzeitig mehrere Interrupts von einem 
Timer ausgelöst werden. Ich nutze derzeit beide OCR-Interrupts, einen 
für die Erzeugung der 50 Hz (Telegrammbeginn), einen für die 
Kanalimpulsbreite. Wenn es sein müsste, könnte der Timer nebenher noch 
ICP machen und mittels OVF ein Zeitnormal von 65,536 ms liefern.

> 2. Wie genau funktioniert die PWM Ausgabe ?

Ich wehre mich, das "PWM" zu nennen, PWM nenne ich es, wenn ich einen 
Tastgrad von 0% bis 100% (Motor, Dimmer) stellen will. In diesem 
speziellen Fall nenne ich es Servoimpuls oder Kanalimpuls, das vermeidet 
Missverständnisse.

> Ich habe ja 3 Kanäle, die
> ausgegeben werden müssen und das im 50Hz Takt. Werden diese sequentiell
> ausgegeben also:
>         ____
> CH1: __|    |___
>              _____
> CH2: _______|     |______
>                    ____
> CH3: _____________|    |_____________

Genau...

>
> 3. Woher bekomme ich die 50Hz Taktung ? Separater Timer oder schon
> irgendwo versteckt eingebaut ?

Das macht Timer1 mit einem der beiden OCR-Einheiten. Die eine beginnt 
ein neues Telegramm (erzeugt also die 50 Hz bzw. weckt den AVR nach 20 
ms), die andere Compare-Einheit hangelt sich durchs Telegramm hindurch, 
dient also als Wecker für die Termine
- Sendertastimpuls beenden (0,5 ms)
- Kanalimpulsende (1,0 ms .. 2,0 ms)
aller Kanäle nacheinander.

0,5 ms nach dem Impulsbeginn muss ja der Sender (falls einer 
angeschlossen ist) wieder deaktiviert werden. Da bietet es sich doch an, 
an dieser Stelle den ADC zu starten und die Potistellung auszumessen. 
Erst das Poti-Messergebnis bestimmt die endgültige Impulsbreite. Da 
diese aber nicht unter 1 ms sein kann, ist genügend Zeit zum Messen zur 
Verfügung.

>
> Zu Deinem "Gain?":
> Ich dachte mir den ADC Wert direkt als Inkrementor in die entsprechende
> Richtung abhänging vom Pulsweiten soll zu nutzen.

Das dachte ich auch.
Zusätzlich würde ich die Möglichkeit schaffen wollen, mit Zahlen unter 1 
arbeiten zu können, den Impulsbreitenweert (in Mikrosekunden) also um 
weniger als 1 pro 20 ms zu ändern. Er wird dann eben erst nach mehreren 
Runden um 1 geändert. Damit werden auch langsamere Nachläufe möglich. 
Obwohl, 1000 Schritte (max Servoweg) durch 50 Hz sind immer noch 20 
Sekunden für den vollen Servoweg, das dürfte eigentlich reichen.

>
> PWM soll         großes ADC Inc.          kleines ADC Inc.
>      _____             ______                   ____________
>     |                  |                       __|
>     |                __|                    __|
>     |               |                    __|
>     |             __|                 __|
>     |            |                 __|
> ____|      ______|            ____|

Ja, gut gezeichnet...

...

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Hannes:
Vielen vielen Dank für Deine Hilfe und die ausführliche Erklärung. Ich 
denke jetzt hab ich alles gerafft und werde mich spätestens am Freitag 
abend ans coden machen! Vorher hat mich leider die Arbeit zu fest im 
Griff.

> Für C bin ich zu blöd, ich kann (auf dem AVR) nur etwas ASM.
Dem kann ich nicht zustimmen. Hab tierischen Respekt vor den Leuten die 
ASM beherrschen! C ist dagegen IMHO easy.

Was ich noch nicht 100%ig verstanden habe ist was zu mit dem 
Sendertastimpuls  meinst. Eigentlich benötige ich den doch gar nicht. 
Ich hab mir Deinen Link auch mal durch gelesen, wo Du eine Art Selbstbau 
- Fernsteuerung beschreibst. Das Signal was in so ein HF - Modul 
reingeht nennt der Modellbauer PPM und enthält anfangs eine Startpuls 
und nachfolgend die Pulslängen der einzelnen Kanäle (ich denke das ist 
Dir mehr als klar). Was ich ja benötige sind die Pulslängen schon 
aufgeschlüsselt auf die einzelnen Servoausgangskanäle....

Besten Dank nochmals ....

Michael

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. (mmike) wrote unter anderem:
>> Für C bin ich zu blöd, ich kann (auf dem AVR) nur etwas ASM.
> Dem kann ich nicht zustimmen. Hab tierischen Respekt vor den Leuten die
> ASM beherrschen! C ist dagegen IMHO easy.

C auf einer Plattform mit OS mag easy sein, C direkt an der Hardware 
(AVR) erfordert auch ASM-Wissen, da der AVR kein C kann. Er kann nur 
Maschinencode, der 1:1 in ASM übersetzt werden kann. Und da ich AVRs 
direkt an der Hardware programmiere, ist für mich ASM der leichtere Weg. 
In BASIC oder C fehlt mir das Wissen, den AVR hardwarenah zu 
programmieren.

> Was ich noch nicht 100%ig verstanden habe ist was zu mit dem
> Sendertastimpuls  meinst. Eigentlich benötige ich den doch gar nicht.

Der dient dazu, das HF-Modul zu "tasten". Wenn Du ihn nicht brauchst, 
dann benutze ihn einfach nicht. Er wird (da er eh vorhanden ist) 
nebenbei als Zustandsflag missbraucht, an dem der Zeitpunkt 0,5ms nach 
Impulsbeginn erkannt wird.

> Das Signal was in so ein HF - Modul
> reingeht nennt der Modellbauer PPM

Als ich mich vor über 30 Jahren mit Funkfernsteuerungen beschäftigt 
hatte, gab es diese Bezeichnung noch nicht. Neben Tonfrequenzmodulation 
(Tipp-Kanäle) gab es das Protokoll, das einfach Digital-Proportional 
genannt wurde. Und wenn dieses Protokoll unter sogenannten Insidern 
immer mal wieder einen cool klingenden Namen bekommt, so muss ich da 
doch nicht mitmachen, oder?

> und enthält anfangs eine Startpuls
> und nachfolgend die Pulslängen der einzelnen Kanäle (ich denke das ist
> Dir mehr als klar).

Nunja, er enthält Impulse mit einer festen Breite von 0,5ms, deren 
zeitlicher Abstand (nicht die Pulsbreite) die Information enthält. Für 
n Kanäle gibt es also n+1 Impulse. Danach kommt eine größere 
Impulspause, damit sich der Empfänger (die Resetbeschaltung der damals 
verwendeten Schieberegister) auf Kanal 1 synchronisieren kann.

> Was ich ja benötige sind die Pulslängen schon
> aufgeschlüsselt auf die einzelnen Servoausgangskanäle....

Ja sicher doch, die sind doch auch herausgeführt, alle sieben. Da sind 
zwar noch die Potis angeschlossen um Strom zu sparen, aber da kann man 
trotzdem Servos anschließen. Ist denn das Programm so schlecht erklärt 
und kommentiert?

...

Autor: Michael K. (mmike) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
> Der dient dazu, das HF-Modul zu "tasten". Wenn Du ihn nicht brauchst,
> dann benutze ihn einfach nicht. Er wird (da er eh vorhanden ist)
> nebenbei als Zustandsflag missbraucht, an dem der Zeitpunkt 0,5ms nach
> Impulsbeginn erkannt wird.
Ich werde kein HF-Modul nutzen, sondern direkt mit den Signalen auf die 
Servos gehen.

> Als ich mich vor über 30 Jahren mit Funkfernsteuerungen beschäftigt
> hatte, gab es diese Bezeichnung noch nicht. Neben Tonfrequenzmodulation
> (Tipp-Kanäle) gab es das Protokoll, das einfach Digital-Proportional
> genannt wurde. Und wenn dieses Protokoll unter sogenannten Insidern
> immer mal wieder einen cool klingenden Namen bekommt, so muss ich da
> doch nicht mitmachen, oder?
Aber nicht doch. Im Anhang ist ein normales "Insider PPM" Signal konform 
zu JR/Graupner und Futaba (da ists dann invertiert) Signal (von 
http://www.mftech.de/ppm.htm). Die Pausen sind da dann auch fest in der 
Breite aber nur 0.3ms lang. Hab sowas mal für die Arbeit gemacht, damit 
man eine Modellflugsimulation (ohne "PPM" Signal der Fernsteuerung) vom 
Computer aus fliegen kann. (RS232 --> PPM Generator).

> Ja sicher doch, die sind doch auch herausgeführt, alle sieben. Da sind
> zwar noch die Potis angeschlossen um Strom zu sparen, aber da kann man
> trotzdem Servos anschließen. Ist denn das Programm so schlecht erklärt
> und kommentiert?
Das auf keinen Fall. Wahrscheinlich hab ich mich ein wenig falsch 
ausgedrückt... sorry!

Besten Dank nochmals ! Hab wirklich sehr viel gelernt ....

Dieses Forum ist wirklich fantastisch!

Grüße,

Michael

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. (mmike) wrote unter anderem:
> Aber nicht doch. Im Anhang ist ein normales "Insider PPM" Signal konform
> zu JR/Graupner und Futaba (da ists dann invertiert) Signal (von
> http://www.mftech.de/ppm.htm).

Genau das meine ich. Jetzt fällt mir ein, warum ich immer die 
Bezeichnung "SenderAUStastimpuls" im Hinterkopf habe, da wird der Sender 
aus getastet...

> Die Pausen sind da dann auch fest in der
> Breite aber nur 0.3ms lang.

Im Prinzip ist es doch egal, ob 0,3ms oder 0,5ms, der, für den ich 
Impulsdecoder programmierte, nannte mir 0,5ms.

> Hab sowas mal für die Arbeit gemacht, damit
> man eine Modellflugsimulation (ohne "PPM" Signal der Fernsteuerung) vom
> Computer aus fliegen kann. (RS232 --> PPM Generator).

Man kann das Impulstelegramm auch von RS232-Daten erzeugen, kein 
Problem. Das könnte z.B. auch für die Roboterbastler interessant sein.

>> Ja sicher doch, die sind doch auch herausgeführt, alle sieben. Da sind
>> zwar noch die Potis angeschlossen um Strom zu sparen, aber da kann man
>> trotzdem Servos anschließen.

Man kann das PPM-Signal natürlich aus dem Programm und vom Port 
entfernen. Da hier kein Sender stören kann, kann der ADC auch schon vom 
Impulsbeginn an arbeiten. Dann ist der Merker (PPM-Port) zur Erkennung 
des Impuls-Status nicht mehr erforderlich.

Natürlich sollte man auch die Abfrage des Aus-Tasters und die Steuerung 
der LED entfernen, denn für ein LowCost-Bedienteil (mit oder ohne 
Sender) ist das zwar ganz brauchbar, für einen Servoverzögerer ist das 
aber eher Unfug. Auch der ganze Kram zum Akku testen kann raus.

Das war übrigens mein letzter Versuch, ein Gerät ohne Batterieschalter 
zu realisieren. Der Ruhestrom im Power-down-Mode ist doch nicht 
vernachlässigbar, er lutscht den Akku doch leer...

...

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Im Prinzip ist es doch egal, ob 0,3ms oder 0,5ms, der, für den ich
> Impulsdecoder programmierte, nannte mir 0,5ms.
Da geb ich Dir recht! Nur in die codierte Pulslänge gehen die 0.3 bzw 
0.5ms mit ein.

> Man kann das Impulstelegramm auch von RS232-Daten erzeugen, kein
> Problem. Das könnte z.B. auch für die Roboterbastler interessant sein.
Auch schon gemacht. Jedoch nicht so komfortabel wie Du vorgeschlagen 
hast! Wird aber demnächst umprogrammiert....

> Das war übrigens mein letzter Versuch, ein Gerät ohne Batterieschalter
> zu realisieren. Der Ruhestrom im Power-down-Mode ist doch nicht
> vernachlässigbar, er lutscht den Akku doch leer...
Wieviel Strom fließt denn da noch? Hast Du da mal gemessen? Ich denke 
mal ein normales Multimeter wird nicht mehr viel anzeigen.

...

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Michael K. (mmike) wrote (unter anderem):
> Wieviel Strom fließt denn da noch? Hast Du da mal gemessen?

Nein, Das gibt meine Bastler-Messtechnik nicht her. Aber "vergessene" 
Akkus sind in ein paar Monaten leer und sogar tiefentladen, was beim 
Vorgängermodell mit AT90S4433 und Batterieschalter nicht der Fall ist.

> Ich denke
> mal ein normales Multimeter wird nicht mehr viel anzeigen.

So ist es.

...

Autor: Michael K. (mmike) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
HILFE !!!!

Hallo Leute,

also so langsam krieg ich die Krise. Ich hab den Aufbau jetzt eigentlich 
so gemacht wie von Hannes beschrieben und die Logik ist mir eigentlich 
auch klar. Jedenfalls hab ich das Programm jetzt mal für ein Servo, was 
in der Verfahrgeschwindigkeit verzögert wird fertiggestellt und ich hab 
wieder mein Hauptproblem beobachten können:
Das Servo zittert. Ich habs am Oszi mal rausgemessen. Die ausgegebene 
Pulslänge schwankt immer um rund 10 - 30 µs. Ich habe den Wert für die 
Pulslänge mal "hardgecoded" und siehe da das Fluktuieren ist weg --> 
ergo die Messung ist schuld. Dann bin ich mit dem Oszi mal direkt auf 
den Empfängerausgang und der fluktuiert aber nicht. Also irgendwo liegt 
ein "dicker Hund" und ich weiß so langsam nicht mehr weiter.
Anbei der Code (sorry Hannes, leider in C).

Bin für jede HILFE sehr dankbar !

Grüße,

Michael

Autor: Hannes Lux (hannes)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> (sorry Hannes, leider in C).

Damit habe ich kein Problem, das erspart mir viel Arbeit... ;-)

...

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie lange braucht der Controller denn zum Aufwachen?
Das würde ich erst mal rausschmeisse.

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Rahul,
hab ich auch schon probiert bei gleichem Phänomen. IHMO sollte dann 
diese Verzögerung ja immer gleich bleiben ....
ABER...

ich glaub ich weiß schon mal den ersten Fehler:
Das zittern könnte "housemade" sein, denn 10µS entsprechen genau dem 
10er Inkrement. Hier der Code:

imp_period[index] = time - imp_start[index];
if ((srv_out[0] - imp_period[index]) > 10)
{
  if (srv_out[0] < imp_period[index])
    srv_out[0] += 10;
  else
    srv_out[0] -= 10;
}

Zudem hat die greift die erste if Bedingung nur wenn srv_out größer als 
imp_period ist. Hier sollte ich den ABS Wert nehmen. Daher oszilliert 
wahrscheinlich der Servowert um den Messwert mit dem Abstand von 10 = 
10µS.

more to come....

Michael

Autor: Michael K. (mmike) (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
es wird und wird nicht besser. Anbei mal die ultimative Minimalversion 
meines Programms, aber irgendwie komme ich auf keinen grünen Zweig. Der 
Code im Anhang nutzt nur den Timer1 für die "PWM" Generierung und ALLE 
Werte sind hardgecoded. Es wird nichts anderes gemacht als die "PWM" 
Ausgabe. Und trotzdem zuckt das Servo (Änderung der Pulsweite um fast 
40µs !!). Das Phänomen ist aber weg, wenn ich den externen Interrupt für 
den PORTB ausschalte. Das kann doch nicht normal sein oder? Ich hab 
sogar schon nen Quarz dran damit ich den internen Ossi als Fehlerquelle 
ausschließen kann.

Michael (mit Vollkrise)

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn ich das richtig sehe, dann enabelst du zwar den
INT1, deine ISR geht aber auf den INT0. Mit anderen
Worten: Für deinen INT1 gibt es keine ISR.

Das ist aber fatal, dann gcc programmiert die Interrupt
Vektor Tabelle so, dass dann ein Reset durchgeführt wird
womit dein Pgm bei jedem INT1 Interrupt wieder von vorne
anfängt.

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da muss ich dir leider widersprechen. So stehts im Manual:

PCICR: Pin Change Interrupt Enable 0
When the PCIE0 bit is set (one) and the I-bit in the Status Register 
(SREG) is set (one), pin change interrupt 0 is enabled. Any change on 
any enabled PCINT7..0 pin will cause an interrupt. The corresponding 
interrupt of Pin Change Interrupt Request is executed from the PCI0 
Interrupt Vector. PCINT7..0 pins are enabled individually by the PCMSK0 
Register.

PCMSK0: Pin Change Enable Mask 7..0
Each PCINT7..0 bit selects whether pin change interrupt is enabled on 
the corresponding I/O pin. If PCINT7..0 is set and the PCIE0 bit in 
PCICR is set, pin change interrupt is enabled on the corresponding I/O 
pin. If PCINT7..0 is cleared, pin change interrupt on the corresponding 
I/O pin is disabled.

Ich gebe den Interrupt PCIE0 frei für PB0 - PB5 falls der entsprechende 
PIN in der Pin Change Enable Mask gesetzt ist (PCMSK0).

Zudem hab ich am Anfang auch eine "Warteschleife" und danach wird PD4 
auf high gelegt, woran eine LED hängt. Sollte der Controller also neu 
starten muss diese LED ja blinken. Tut sie aber nicht..... die Idee mit 
dem Neustart hatte ich auch schon ....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
> Da muss ich dir leider widersprechen.

Mit Recht! Das das ein Pin Change Interrupt ist, hab
ich komplett übersehen.

Ist schon spät.
Hmmm

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ne Idee woran das liegen könnte ??

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ich kanns ja fast nicht glauben ... so viele Experten und keine 
Meinungen ??
Auf gehts ich brauch Input .... in einer Stunde gehts nach Hause und 
dann ab in den Keller ! Da müssen doch wenigstens ein paar Vermutungen 
überprüft werden.
Grüße,
Michael

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Noch ne Frage: Wie lange dauert die Abarbeitung einer ISR im Schnitt 
(Anzahl der Zyklen) ? Kann da jemand eine Aussage drüber treffen ?
Ich vermute, daß die ISRs von Ausgabe und Messung sich in die Quere 
kommen. Jetzt hier mein gedanklicher Vorschlag:
Ich will ja von 3 Kanälen die Pulsweite messen und nehme an, daß diese 
sequentiell aus dem Empfänger kommen --> ergo bei max. Pulslänge von 
2,1ms dauert das max. 6,3ms. Ich leg noch ein paar Sicherheits "ms" 
drauf und nehme die 9ms.
Das Vorgehen sieht dann so aus:
1. Warten bis 1.Kanal vom Empfänger auf high geht und dann Timer starten 
bis 9ms rum sind. In der Zeit sollten alle Kanäle vom Empfänger 
vermessen sein.
2. Start der PWM Ausgabe für Kanäle 1 - 3.

Erhoffter Profit:

1. Die ISR's kommen sich nicht mehr in die Quere.
2. Ich synchronisiere meine PWM Periodenlänge (normalerweise rund 20ms) 
mit der des Empfängers.

...

Autor: Michael K. (mmike) (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo Leute,
also ERFOLGSMELDUNG !! So langsam kommt das Licht am Ende des Tunnels. 
Folgende Veränderungen haben zu ersten Erfolgen (kein Servozittern mehr 
und Fels - stabile Pulsweiten) geführt:
1. Den internen Prescaler abgeschaltet und 16 MHz Quarz verwendet 
(erhöht zwar den Stromverbrauch aber auch die Rechenleistung)
2. Timer1 mit 8er Prescaler
3. Erst Kanäle messen und dann ausgeben synchron mit Totzeit zum 
Empfänger
4. Servo mit seperatem Strom versorgt (nicht über das STK500, denn ich 
vermute auch fast, daß wenn das Servo mal anfährt doch merkliche 
Spannungseinbrüche am µC waren (Mein Netzgerät zeigt stellenweise bis zu 
500mA an und wenn dann das Servo noch dauern zittert ..... ohne Worte)
Danke an alle die mitgedacht haben ... allen voran Hannes, der Trollige 
und Karl Heinz (bin jetzt einfach so frei und nehme an "DU" sagen zu 
dürfen ;-) ) !
Ich melde mich wieder wenn der Code einsatzbereit ist ....
...
Michael

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.