RC Empfänger 2-3 Kanäle auslesen

    This site uses cookies. By continuing to browse this site, you are agreeing to our Cookie Policy.

    • RC Empfänger 2-3 Kanäle auslesen

      Hallo
      Ich möchte gerne von einem RC Empfänger 1-3 Kanal auslesen (Servoimpuls) wieder ausgeben, und wenn das Servo gegen einen Endschalter fährt selbiges stoppen und nur noch eine Rückwärtsbewegung zulassen. geht das ohne Timer ??
      Denn: Timer, Quarzferquenz, Prescaler habe ich bis jetzt noch nicht verstanden; wenn ich das mit Timer0 bzw. Timer1 verstehen würde wäre mir auch geholfen. (1 Kanal reicht schon)
      Mega 8 und Mega 328P (Arduino Nano) vorhanden.
    • Im Prinzip geht das auch ohne Timer, solange man nur Pulse einlesen oder nur ausgeben will.
      Zusammen gehts natürlich nur mit Timer.

      Servopulse einlesen kannst du z.B. mit dem Befehl PulseIn und ausgeben entsprechend mit PulseOut oder von Hand. Für die Ausgabe bietet Bascom aber auch einen fertigen Befehl an, der intern jedoch einen Timer verwendet. Um diesen müsstest du dich aber dann nicht direkt kümmern. Siehe hierzu Bascomhilfe config servos.

      Weitere Infos über Aufbau und Timing zu den Sevo-Signalen findest du bei Wikipedia.

      Timer bei den Controllern sind im übrigen sehr vielseitig einsetzbar und es ist hilfreich, diese zu verstehen. Sich damit auseinander zu setzen ist also über kurz oder lang ein muss!
      Kaum macht man es richtig - und schon geht's!
    • @Pocketpcuser wie ist dein Plan? Die Pulsbreite für jedes Servo wird gelesen und in der gleichen Breite wieder erzeugt und ausgegeben. 'Gleichzeitig' werden Endschalter abgefragt, wenn aktiv wird die Pulsbreite 'eingefroren' (Servo bewegt sich nicht mehr) und erst, wenn eine neue Breite eintrifft, die vom Schalter wegbewegen würde, wird dieser Puls wieder durchgereicht?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Hallo Danke für die Antworten !
      @tschoeatsch genau wie du schreibst, Servo fährt bis zum Schalter (low) dann nur noch rückwärtsmöglich möglich bis Schalter wieder (High)
      Servos sind Analog-Servos mit 50Hz bzw. 20ms. Der Mega 8 läuft mit 8Mhz, der Nano mit 16Mhz.
      wenn ich das richtig verstehe kann ich mit Pusein die impulsbreite auslesen,dann einen Timer starten der die Ausgabe macht (Impulsbreite+low-anteil) sind dann 20ms erreicht sollte der Timer überlaufen und neu beginnen.??
      oder Impulsbreite ausgeben für Servo1, Servo2,... und dann Überlauf bei 20ms ??
      wie wird das gehen ??

      The post was edited 1 time, last by Pocketpcuser ().

    • Ich würde mal ganz einfach anfangen, mit pulsein nacheinander die Pulsbreite messen und im Weiteren mit pulsout wieder ausgeben.

      BASCOM Source Code

      1. $regfile = "m328pdef.dat"
      2. $crystal = 16000000
      3. $hwstack=64
      4. $swstack = 32
      5. $framesize = 30
      6. Dim S1 As Word , S2 As Word , S3 As Word 'Pulsbreiten
      7. 'Eingänge definieren
      8. 'Ausgänge definieren
      9. Do
      10. Pulsein S1 , Pinx , Pin , 0 'in 10µs/4Mhz
      11. Pulsein S2 , Pinx , Pin , 0
      12. Pulsein S3 , Pinx , Pin , 0
      13. s1=10*s1:s2=10*s2:s3=10*s3
      14. Pulseout Port , Pin , S1 'in 1µs/4Mhz
      15. Pulseout Port , Pin , S2
      16. Pulseout Port , Pin , S3
      17. Loop
      18. End
      Display All
      pulsein wartet ja auf einen Puls, somit sollten die Eingänge so auf die Servopulse verteilt werden, dass die schön nacheinander eintreffen. Durch das Warten wird auch automatisch die längere Pause zwischen den Servopulsen übernommen.
      Einfach mal das Programm vervollständigen und probieren, wie sich die Servos an den Ausgängen verhalten. Man kann ja auch erstmal mit einem Servo probieren, aber dann auch nur mit einem pulsein, sonst wartet der unbenutzte 'ewig' und das Ergebnis wird verfälscht.

      Könnte grad so klappen, bei default 1µs/unit und 4MHz kommt man bis 65ms, bei 16MHz dann bis 16ms für die maximale Pulslänge.

      Edit: ich komme in's schleudern. Pulseout macht 1µs/unit bei 4MHz, pulsein 10µs/unit by default. Also muss ich das Gemessene x10 wieder senden.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------

      The post was edited 2 times, last by tschoeatsch ().

    • Wenn ich einen timer verwenden wollte, dann um die Einschränkungen von pulsein zu vermeiden. Dazu würde ich eine isr basteln, in der nacheinander die pins, wo die Servosignale anliegen, auf den Pegel für den Puls abgefragt wird, und wenn dieser anliegt, eine Variable inkrementiert wird. Liegt kein Puls an, dann ein flag setzen. Die Variable, multipliziert mit dem Aufrufintervall der isr ergibt die Pulslänge, die man dann im Hauptprogramm mit pulseout ausgeben kann. Und das, wenn das flag das Ende des Eingangspulses signalisiert hat. Im Hauptprogramm wird auch vor der Ausgabe die Endschalter und deren Begrenzung auf den Puls mit bedacht.
      Den Vorteil sehe ich durch die 'gleichzeitig' mögliche Pulsmessung aller Pulse, die wahrscheinlich nicht benötigt wird, aber die Sortierung, wann welcher pin durch pulsein abzufragen ist, ist so hinfällig.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • 1. Timer Versuch

      So nun mein 1. Timer versuch
      Led ist aber etwas zu schnell, wohl was falsch gerechnet ??

      Source Code

      1. 'Timer1 test
      2. $regfile = "m8def.dat"
      3. $crystal = 16000000
      4. $baud = 9600
      5. $hwstack = 64
      6. $swstack = 32
      7. $framesize = 30
      8. Config Portd = Output 'definiert Portd als Output
      9. Config Timer1 = Timer , Prescale = 256 'Konfiguriere Timer1
      10. Enable Timer1 'schalte den Timer1 ein
      11. On Timer1 Isr_von_timer1 'verzweige bei Timer1 überlauf zu Isr_von_Timer1
      12. Enable Interrupts
      13. Timer1 = 49910 'Timer1 soll schon von 49910 wegzählen
      14. Do
      15. Print "Hauptprogramm"
      16. Waitms 500
      17. Print "-------------"
      18. Loop
      19. End
      20. Isr_von_timer1: 'ISR von Timer1
      21. Timer1 = 49910 'Timer1 soll wieder von 49910 wegzählen
      22. Toggle Portd.4 'schaltet Portd.4 im Sekundentakt
      23. Return
      24. '16 Bit Timer::: Startwert65536 - (16000000/Prescale/f_Wunsch) hier 1Hz f_Wunsch
      Display All
    • Falsch gerechnet. Der timer wird mit 16000000/256 hz getaktet, also mit 62500 hz. Wenn du ihn 62500 Schritte zählen lässt, braucht er die 1 Sekunde. Also musst du den timer bei65536-62500 loszählen lassen.
      Aber sonst, passt doch alles, kennst dich doch mit timern aus :thumbup:
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • BASCOM Source Code: Servo_Steurung

      1. ' BASCOM-Programm
      2. ' Ansteuerung mehrerer Servos mit einem Timer intern 1Mhz
      3. '
      4. ' In: Poti Mittelabgriff an c.0 (= ADC0). Poti zwischen Plus und Gnd.
      5. '
      6. '
      7. $regfile = "m8def.dat"
      8. $crystal = 1000000 '1 Mhz
      9. $hwstack = 32 ' default use 32 for the hardware stack
      10. $swstack = 10 ' default use 10 for the SW stack
      11. $framesize = 40 ' default use 40 for the frame space
      12. $baud = 9600
      13. Ddrb = &B00011111
      14. Servos Alias Portb
      15. Servo1 Alias Portb.1
      16. Servo2 Alias Portb.2
      17. Servo3 Alias Portb.3
      18. Servo4 Alias Portb.4
      19. ' Bei Timer1 (65536) mit 1 MHz und Prescaler=8
      20. ' 1 Tick: 1/1000000 *8 =8us
      21. ' 65536 - 63036 = 2500 * 8us = 20ms
      22. ' 65536 - 65411 = 125 * 8us = 1ms
      23. ' 65536 - 65286 = 250 * 8us = 2ms
      24. Const 20ms = 63036 '40536 'Timerstartwert fuer 20ms
      25. Const Rechteranschlag = 65411 '63036 '1ms
      26. '$prog &HFF , &HFF , &HDF , &H00 ' generated. Take care that the chip supports all fuse bytes.
      27. '$prog &HFF , &HFF , &HDF , &H00 ' generated. Take care that the chip supports all fuse bytes.
      28. Const Linkeranschlag = 65286 '46000 '2ms Differenz=125
      29. Config Timer1 = Timer , Prescale = 8
      30. Timer1 = 20ms
      31. On Timer1 Timer1_isr
      32. Enable Timer1
      33. Enable Interrupts
      34. Dim Servo(4) As Word '0..125
      35. Dim Servo_nummer As Byte
      36. Servo_nummer = 0
      37. Dim S5 As Word
      38. Dim I As Byte
      39. Dim Zaehler1 As Word
      40. Dim Zaehler2 As Word
      41. Dim Richtung As Integer
      42. Richtung = 1 'hochzaehlen
      43. Dim Analogwandler As Integer 'Variable zur Aufnahme des Wertes vom Analogwandler
      44. Config Adc = Single , Prescaler = Auto , Reference = Avcc 'Analogwandler definieren
      45. Do
      46. Pulsein S5 , Pinb , 5 , 0
      47. 'Servo1: Schnelles Hin- und Herschalten zwischen links und rechts:
      48. Incr Zaehler1
      49. If Zaehler1 = 2000 Then Zaehler1 = 0 'warten
      50. If Zaehler1 = 1 Then Servo(1) = 0 'Aktion: ganz links
      51. If Zaehler1 = 1000 Then Servo(1) = 125 'Aktion: ganz rechts
      52. 'Servo2: Langsames Hin- und Herschalten zwischen links und rechts:
      53. Incr Zaehler2
      54. If Zaehler2 = 20 Then Zaehler2 = 0
      55. If Zaehler2 = 1 Then 'Aktion:
      56. I = I + Richtung
      57. If I = 125 Then Richtung = -1 'runter
      58. If I = 0 Then Richtung = 1 'hoch
      59. Servo(2) = I
      60. End If
      61. 'Servo3: Servostellung je nach Poti-Stellung:
      62. Analogwandler = Getadc(0) '0..1023
      63. Servo(3) = Analogwandler / 8 'S5-1000' Analogwandler / 8 ' 0..127
      64. 'Print Analogwandler
      65. 'Servo4: Servostellung je nach Poti-Stellung:
      66. Analogwandler = Getadc(1) '0..1023
      67. Servo(4) = Analogwandler / 8 ' 0..127
      68. Waitus 1
      69. Loop
      70. End
      71. Timer1_isr:
      72. Select Case Servo_nummer
      73. Case 0:
      74. Incr Servo_nummer
      75. Servos = 0 'alle aus
      76. Timer1 = 20ms 'Pause ca. 20 ms
      77. Case 1:
      78. Incr Servo_nummer
      79. Portb = 0
      80. Servo1 = 1 'Impuls an Servo1
      81. Timer1 = Linkeranschlag + Servo(1) ' für 1ms bis 2ms
      82. Case 2:
      83. Incr Servo_nummer
      84. Servos = 0
      85. Servo2 = 1 'Impuls an Servo2
      86. Timer1 = Linkeranschlag + Servo(2) ' für 1ms bis 2ms
      87. Case 3:
      88. Incr Servo_nummer
      89. Servos = 0
      90. Servo3 = 1 'Impuls an Servo3
      91. Timer1 = Linkeranschlag + Servo(3) ' für 1ms bis 2ms
      92. Case 4:
      93. Servo_nummer = 0
      94. Servos = 0
      95. Servo4 = 1 'Impuls an Servo4
      96. Timer1 = Linkeranschlag + Servo(4) ' für 1ms bis 2ms
      97. End Select
      98. Return
      Display All
      Hier nun Mein Code der Leider nicht funktioniert
      Ich Steure Servo3 mit Dem Poti über Adc ist alles ok, ersetze ich die Werte in Zeile 77 durch Die Pulsein werte so fängt das Servo an zu Zittern.
      Nutze ich Die Bascom Befehle Für die Servo-Ausgabe so ergibt sich der selbe effekt; die Servos zittern um die mittelstellung.
      nutze ich feste werte für das Servo so steht es wie angenagelt.
      was kann das sein ??
    • BASCOM Source Code

      1. '
      2. $regfile = "m8def.dat"
      3. $crystal = 1000000
      4. $hwstack = 32 ' default use 32 for the hardware stack
      5. $swstack = 10 ' default use 10 for the SW stack
      6. $framesize = 40 ' default use 40 for the frame space
      7. Ddrb = &B00000011
      8. 'Const Linkeranschlag = 35 'oder z.B. 40 ganz rechts - je nach Servo
      9. 'Const Rechteranschlag = 10 'oder z.B. 110 ganz links- je nach Servo
      10. ' Bei Timer1 (65536) mit 1 MHz und Prescaler=8
      11. ' 1 Tick: 1/1000000 *8 =8us
      12. ' 65536 - 63036 = 2500 * 8us = 20ms
      13. ' 65536 - 65411 = 125 * 8us = 1ms
      14. ' 65536 - 65286 = 250 * 8us = 2ms
      15. Dim S1 As Word
      16. Const 20ms = 63036
      17. Const Rechteranschlag = 65411 '1ms
      18. Const Linkeranschlag = 65286 '2ms Differenz=125
      19. Config Timer1 = Timer , Prescale = 8
      20. Timer1 = 20ms
      21. On Timer1 Timer1_isr
      22. Enable Timer1
      23. Enable Interrupts
      24. Dim Servo As Word '0..125
      25. Dim Analogwandler As Integer 'Variable zur Aufnahme des Wertes vom Analogwandler
      26. Config Adc = Single , Prescaler = Auto , Reference = Avcc 'Analogwandler definieren
      27. Start Adc 'AD-Wandler starten (nach Config automatisch)
      28. 'Pulsein S1 , Pinb , 4 , 0 'hier ist der Fehler !!!!!
      29. 'Servostellung je nach Poti-Stellung:
      30. Do
      31. Analogwandler = Getadc(0) '0..1023
      32. Servo = Analogwandler / 8 ' 0..127
      33. Loop
      34. End
      35. Timer1_isr:
      36. If Pinb.1 = 1 Then 'wenn 1 war
      37. Portb.1 = 0 'dann aus und
      38. Timer1 = 20ms ' Pause ca. 20 ms
      39. Else 'sonst
      40. Portb.1 = 1 'Impuls
      41. Timer1 = Linkeranschlag + Servo ' für 1ms bis 2ms
      42. End If
      43. Return
      Display All
      Hallo Bascom Freunde
      nun mein Programm reduziert auf 1 Servo, sobald ich Zeile 40 aktiviere bewegt sich das Servo von selbst (zittert sehr stark)
      obwohl ich keinen Empfänger angeschlossen habe; wie kann ich die Impulse einlesen mit Timer0 weil ich Timer1 für die Ausgabe schon benutze. ??
    • Deine Umschalterei in der isr mit portb.1 ist nicht so toll. Ich würde da eine Bitvariable verwenden, die man lesen und schreiben kann. Mal pinb.1 und dann portb.1 verwenden, hm, weißt du sicher, was du da prüfst?
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • The PULSIN statement will wait for the specified edge.
      When state 0 is used, the routine will wait until the level on the specified input pin is 0. Then a counter is started and stopped until the input level gets 1.
      Ich hab' das in meinem Beispiel wohl falsch vorgegeben. Wenn man die Länge des high-Pulses will, braucht man die 1, wie @R2D2 Bastler schrieb.
      Raum für Notizen

      -----------------------------------------------------------------------------------------------------

      -----------------------------------------------------------------------------------------------------
    • Noch ein kleiner Nachtrag zu Pulsein. Bei Pulsein wartet das Programm auf die gewünschte Flanke. Kommt diese nicht, gehts standartmäßig erst nach 655,35ms weiter (das ist eine Pause von mehr als einer halbe Sekunde!). Wie Michael schon schrieb, läuft der Timer in der Zeit schon unzählige male über. Daher, wenn Du Pulsein benutzt, auch ein RC-Signal anlegen.
      Wenn der Eingangspin offen liegt, kann da alles mögliche detektiert werden.

      Pulsein liefert bei normalen RC Signalen (1ms-2ms) Werte zwischen 100 und 200 als Ergebnis. Da RC Signale aber oft auch länger und kürzer als 1-2ms sind, liegen die tatsächlichen Ergebnisse meist zwischen 80 und 220. Da Du einen Nano hast, kannst Du Dir die tatsächlichen Werte ja recht einfach am PC anzeigen lassen.

      Aus welcher Quelle stammt eigentlich Dein RC Signal? Ich hatte auch schon schlaflose Nächte wegen zitternder Servos und genau wie bei Dir war das Zittern weg, sobald man Festwerte eingab. Bei mir lags am billigen Servotester kombiniert mit unzureichender Stromversorgung. Sobald ich einen richtigen RC Empfänger und ein ausreichendes BEC dran hing, war das Zittern weg.