Hallo, ich möchte eine Schaltung mit einem Tiny aufbauen die mir zum einen den Servoimpuls des Empfängers misst und diesen dann verzögert auf einem Port ausgibt. Damit soll dann das Fahrwerk langsam ausfahren. Das Messen des Pulses mit einem Portinterupt klappt gut, allerdings benötige ich dazu ja schon den ersten Timer. Wie bekomme ich möglichst Ressourcensparend die verzögerte Ausgabe hin?? da stehe ich auf dem Schlauch.. einen zweiten Timer wird man wohl schon brauchen oder ginge es mit einem Kunstgriff auch nur mit einem? Gruss Patrick
Patrick schrieb: > Das Messen des Pulses mit einem Portinterupt klappt gut, allerdings > benötige ich dazu ja schon den ersten Timer. Wie misst du? > Wie bekomme ich möglichst > Ressourcensparend die verzögerte Ausgabe hin?? Wenn dein 'Pulsmesstimer' ein durchlaufender Timer ist, dann hast du doch schon einen Zeitgeber, mit dem du zusätzlich noch eine Verzögerung realisieren kannst. Hängt aber davon ab, wie du Pulse misst. Übrigens: Verzögern des Pulses wird dir nicht helfen. Dann fährt das Fahrwerk einfach nur einen Tick später aus. Was du brauchst ist: Die Pulslänge an das Servo wird nicht in einem Schlag von 1ms auf 2ms gesetzt, sondern in mehreren Schritten. Ändert aber nicht viel daran, dass du auch dieses Grundtiming wahrscheinlich im bereits benutzten Timer unterbringen kannst.
Karl heinz Buchegger schrieb: > Patrick schrieb: > >> Das Messen des Pulses mit einem Portinterupt klappt gut, allerdings >> benötige ich dazu ja schon den ersten Timer. > > Wie misst du? im Prinzp so: /*********************************************************************** ***********************/ /* SIGNAL Interupt0 */ /*********************************************************************** ***********************/ SIGNAL(SIG_INTERRUPT0) { if( MCUCR == 0x03) // Testen auf steigende Flanke { steigende_Flanke(); return; } if( MCUCR == 0x02 ) // Testen auf fallende Flanke { fallende_Flanke(); return; } } > >> Wie bekomme ich möglichst >> Ressourcensparend die verzögerte Ausgabe hin?? > > Wenn dein 'Pulsmesstimer' ein durchlaufender Timer ist, dann hast du > doch schon einen Zeitgeber, mit dem du zusätzlich noch eine Verzögerung > realisieren kannst. > > Hängt aber davon ab, wie du Pulse misst. im Moment läuft der Timer nicht durch sondern wird ja über den Interrupt getriggert > > Übrigens: Verzögern des Pulses wird dir nicht helfen. Dann fährt das > Fahrwerk einfach nur einen Tick später aus. Was du brauchst ist: Die > Pulslänge an das Servo wird nicht in einem Schlag von 1ms auf 2ms > gesetzt, sondern in mehreren Schritten. > Ändert aber nicht viel daran, dass du auch dieses Grundtiming > wahrscheinlich im bereits benutzten Timer unterbringen kannst. war falsch ausgedrückt.. klar muss der Impuls dann verlängert werden aber wie?
Patrick schrieb: >> Hängt aber davon ab, wie du Pulse misst. > > im Moment läuft der Timer nicht durch sondern wird ja über den Interrupt > getriggert D.h. Du setzt den Timer bei 'steigender Flanke' auf 0 und startest ihn. Und bei einer fallenden Flanke stoppst du ihn wieder? Kann man so machen. Muss man aber nicht. Der Timer kann auch ständig laufen. Bei einer steigenden Flanke merkst du dir den Timerwert, bei einer fallenden Flanke ziehst du dann vom dann vorliegenden Timerwert den gemerkten Startwert ab und schon hast du die Anzahl der Timerticks zwischen den beiden 'Ereignissen' >> gesetzt, sondern in mehreren Schritten. >> Ändert aber nicht viel daran, dass du auch dieses Grundtiming >> wahrscheinlich im bereits benutzten Timer unterbringen kannst. > > war falsch ausgedrückt.. klar muss der Impuls dann verlängert werden > aber wie? möchte man haben, dass sich ein Wert langsam an einen anderen anpasst und nachzieht, dann geht das zb so while( 1 ) { if( aktueller_Wert < Soll_Wert ) aktueller_Wert++: if( aktueller_Wert > Soll_Wert ) aktueller_Wert--: mach was mit aktueller_Wert } Wann immer sich der Sollwert ändert, wird der Wert den du im weiteren benutzt (zb bei dir eben die Servoposition) in jedem Schleifendurchlauf nur ein Stückchen in Richtung des Sollwerts verändert. Bei vielen Schleifendurchläufen wird der tatsächlich benutzte Wert aktueller_Wert irgendwann den Soll_Wert erreichen. Aber eben nicht sofort, sondern in vielen kleinen Stufen. Ob man dann als Stufenbreite 1 nimmt (wie hier) oder ob man da in größeren Schritten operiert, hängt von der Anwendung ab bzw. davon wie schnell die Schleife dann tatsächlich durchläuft. Bei dir wäre zb Soll_Wert die Pulslänge, die du gemessen hast. Aktueller_wert ist die Pulslänge, wie du sie generierst und zum Servo schickst. Und die Hauptschleife führt den einen Wert dem anderen nach und schon läuft dein Servo langsam in die durch den Sollwert vorgegebene Position. Ist das Servo novh unterwegs und ändert sich der Soll_wert ist das auch kein Problem, die Schleife führt den aktuellen Wert dann eben auf einen anderen Soll_wert nach.
Hallo Karl Heinz, herzlichen Dank, das ist eine sehr gute Idee! ich könnte zb. den Timer mit 10us laufen lassen, dh. bei einer Pulslänge zwischen 1-2ms hätte ich eine Auflösung zwischen 100-200 Tics... sollte reichen. den gleichen Timer muss ich halt durch einen Teiler im Interrupt verlangsamen so dass ich zb. 1sec (100.000tics) Hoch/Runter Zählimpulse bekomme. Den Ausgabe Impuls müsste ich dann daraus berechnen indem ich den max wert der Periodendauer = 20ms = 2000tics minus dem der gerechneten Pulslänge verwende und auch wieder über den gleichen Zähler ausgebe. Ich dachte mir quasi immer dann eine Ausgabe zu starten wenn der Port wieder auf 0 geht und die Impulsdauer gemessen wurde. Gruss Patrick
Hallo, ich hab die Umsetzung mittels zweitem Timer1 versucht. Theoretisch funktionierte auch alles, aber leider tut sich mein Tiny25 mit den kurzen Zeiten schwer. Er läuft intern mit dem 8Mhz RC Oszilator, normal nochmal mit einer Fuse durch 8 geteilt. D.h wenn der Timer1 mit 10us laufen soll geht quasi nichts mehr. Ich denke dass die Abarbeitungszeit dann länger braucht als der Timerinterrupt. Ich hab den Teiler /8 auch mal abgeschaltet so dass ich die vollen 8Mhz zur Verfügung habe, aber auch damit komme ich nicht auf einen so schnelle Abarbeitung. Gibts dazu einen Trick oder mache ich was falsch? Gruss Patrick
Patrick schrieb: > Hallo, > > ich hab die Umsetzung mittels zweitem Timer1 versucht. Theoretisch > funktionierte auch alles, aber leider tut sich mein Tiny25 mit den > kurzen Zeiten schwer. > Ich hab den Teiler /8 auch > mal abgeschaltet so dass ich die vollen 8Mhz zur Verfügung habe, aber > auch damit komme ich nicht auf einen so schnelle Abarbeitung. Gibts dazu > einen Trick oder mache ich was falsch? Du willst mir doch nicht ernsthaft erzählen, dass ein mit 8Mhz getakteter Prozessor Schwierigkeiten mit einem Timing hat, welches sich im Millisekundenbereich bewegt. Nur zu Veranschaulichung: In 1 Millisekunde bearbeitet dein Tiny rund 7-Tausend Befehle! Da wirst du wohl etwas falsch machen.
Naja, mich wundert's nicht, wenn er einen Timer so einstellt, daß er alle 10 µs einen Interrupt auslöst. Dann hat man bei 8 Mhz pro Interrupt 80 Taktzyklen, die vermutlich größtenteils in der ISR selbst schon verbraucht werden. Bei 1 Mhz wären es noch 10 Taktzyklen pro Interrupt, was gar nicht reichen kann, weil es schon unter dem liegt, was eine komplett leere ISR braucht.
Rolf Magnus schrieb: > Naja, mich wundert's nicht, wenn er einen Timer so einstellt, daß er > alle 10 µs einen Interrupt auslöst. Dann hat man bei 8 Mhz pro Interrupt > 80 Taktzyklen, die vermutlich größtenteils in der ISR selbst schon > verbraucht werden. Bei 1 Mhz wären es noch 10 Taktzyklen pro Interrupt, > was gar nicht reichen kann, weil es schon unter dem liegt, was eine > komplett leere ISR braucht. Genau, wenn ich den Puls von 2ms Länge mit einer Auflösung von 200 Schritten auflösen möchte brauch ich halt die 10us für eine Timer ISR. Per Flankentriggerung gehts natürlich aber dann kann ich den Timer ja für nichts anderes mehr verwenden. Gruss Patrick
Pseudocode:
1 | externer_Interrupt // oder input-capture interrupt |
2 | {
|
3 | if( inputpin == 1 ) |
4 | anfang = timer; |
5 | else
|
6 | in_pulsdauer = timer - anfang; |
7 | {
|
8 | |
9 | output_compare_Interrupt
|
10 | {
|
11 | if( outputpin == 0 ){ |
12 | OCR1A = timer + pausen_dauer; |
13 | setze_pin_bei_compare(); |
14 | }else{ |
15 | OCR1A = timer + out_pulsdauer; |
16 | loesche_pin_bei_compare(); |
17 | }
|
18 | }
|
Nimm am einfachsten nen ATtiny24, dann hast Du nen 16Bit Timer, da sollte die Auflösung dicke reichen. Peter
ok, die Output Compare Funktion muss ich mir noch durchlesen.. damit hatte ich noch nichts gemacht. Folgender Ansatz, im Prinzip wie oben. Ich starte den Timer mittels Pin ISR bei steigender Flanke, wenn die fallende Flanke erkannt wird merke ich mir nur den Wert des Timers für die Impulslänge stoppe diesen aber noch nicht sondern benutze Ihn weiter um quasi im Anschluss den "veränderten" Ausgangsimpuls zu erzeugen. Dadurch bräuchte ich quasi immer nur auf das Ende zu warten um die Pins zu toggeln.. vlt. geht so. Gruss Patrick
Hallo Patrick, ich habe das gleiche vor wie du. Bist du mit deinem Ansatz schon weiter gekommen? VG Ole
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.