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
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.
@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.
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
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
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
@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
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... ...
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 ?
> 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.
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
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. ...
@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
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
> 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. ...
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
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. _____ _______ ___________ | | __| | __| __| | | __| | __| __| | | __| ____| ______| ____|
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... ...
@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
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? ...
> 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
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... ...
> 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. ...
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. ...
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
> (sorry Hannes, leider in C).
Damit habe ich kein Problem, das erspart mir viel Arbeit... ;-)
...
Wie lange braucht der Controller denn zum Aufwachen? Das würde ich erst mal rausschmeisse.
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
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)
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.
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 ....
> Da muss ich dir leider widersprechen.
Mit Recht! Das das ein Pin Change Interrupt ist, hab
ich komplett übersehen.
Ist schon spät.
Hmmm
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
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. ...
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
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.