Port-Ausgabe temporär abschalten?

    Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

    • Port-Ausgabe temporär abschalten?

      Hallo,
      zum HIntergrund: Das Programm liest ein RC-Signal und schaltet in Abhängigkeit von der Signallänge bestimmte Port ein oder aus. Soweit funktiuoniert alles wie es sein soll. Allerdings kommt es beim Umschalten am Sender ab und an zur kurzfristigen Aktivierung einer anderen Funktion. Das Einschalten findet auch nciht immer statt und es sind auch nicht immer die gleichen Funktionen davon betroffen.
      Das Programm läuft auf einem ATMEga8 mit 1 MHz, Erhöhen der Frequenz hat auch keine Lösung gebracht; genauso wenig wie das Einbauen einer Warteschleife vor dem Einstieg in die Abfrage selbst. Die sieht so aus:

      Quellcode

      1. select case wPulseSwitch 'port activation
      2. case wSwitchLow(1) to wSwitchHigh(1) 'Blinker left
      3. toggle BlinkLeft : BlinkRight = 0
      4. LightBar = 0
      5. LowLight = 0 : HighLight = 0 : RearLight = 0
      6. case wSwitchLow(2) to wSwitchHigh(2) 'Blinker right
      7. BlinkLeft = 0 : toggle BlinkRight
      8. LightBar = 0
      9. LowLight = 0 : HighLight = 0 : RearLight = 0
      10. case wSwitchLow(3) to wSwitchHigh(3) 'Blinker warn
      11. toggle BlinkLeft : toggle BlinkRight
      12. LightBar = 0
      13. LowLight = 0 : HighLight = 0 : RearLight = 0
      14. case wSwitchLow(4) to wSwitchHigh(4) 'Light bar
      15. BlinkLeft = 0 : BlinkRight = 0
      16. LightBar = 1
      17. LowLight = 0 : HighLight = 0 : RearLight = 0
      18. case wSwitchLow(5) to wSwitchHigh(5) 'Low light
      19. BlinkLeft = 0 : BlinkRight = 0
      20. LightBar = 0
      21. LowLight = 1 : HighLight = 0 : RearLight = 1
      22. case wSwitchLow(6) to wSwitchHigh(6) 'Low light + blinker left
      23. toggle BlinkLeft : BlinkRight = 0
      24. LightBar = 0
      25. LowLight = 1 : HighLight = 0 : RearLight = 1
      26. case wSwitchLow(7) to wSwitchHigh(7) 'Low light + blinker right
      27. BlinkLeft = 0 : toggle BlinkRight
      28. LightBar = 0
      29. LowLight = 1 : HighLight = 0 : RearLight = 1
      30. case wSwitchLow(8) to wSwitchHigh(8) 'Low light + blinker warn
      31. toggle BlinkLeft : toggle BlinkRight
      32. LightBar = 0
      33. LowLight = 1 : HighLight = 0 : RearLight = 1
      34. case wSwitchLow(9) to wSwitchHigh(9) 'Low light + light bar
      35. BlinkLeft = 0 : BlinkRight = 0
      36. LightBar = 1
      37. LowLight = 1 : HighLight = 0 : RearLight = 1
      38. case wSwitchLow(10) to wSwitchHigh(10) 'High light
      39. BlinkLeft = 0 : BlinkRight = 0
      40. LightBar = 0
      41. LowLight = 0 : HighLight = 1 : RearLight = 1
      42. case wSwitchLow(11) to wSwitchHigh(11) 'High light + blinker left
      43. toggle BlinkLeft : BlinkRight = 0
      44. LightBar = 0
      45. LowLight = 0 : HighLight = 1 : RearLight = 1
      46. case wSwitchLow(12) to wSwitchHigh(12) 'High light + blinker right
      47. BlinkLeft = 0 : toggle BlinkRight
      48. LightBar = 0
      49. LowLight = 0 : HighLight = 1 : RearLight = 1
      50. case wSwitchLow(13) to wSwitchHigh(13) 'High light + blinker warn
      51. toggle BlinkLeft : toggle BlinkRight
      52. LightBar = 0
      53. LowLight = 0 : HighLight = 1 : RearLight = 1
      54. case wSwitchLow(14) to wSwitchHigh(14) 'High light + light bar
      55. BlinkLeft = 0 : BlinkRight = 0
      56. LightBar = 1
      57. LowLight = 0 : HighLight = 1 : RearLight = 1
      58. case else
      59. BlinkLeft = 0 : BlinkRight = 0
      60. LightBar = 0
      61. LowLight = 0 : HighLight = 0 : RearLight = 0
      62. end select
      Alles anzeigen
      Die gute Frage ist nun, wie sich diese ungewollten Schaltvorgänge verhindern lassen. Mir ist dazu bisher nur eingefallen, zu Lasten der Lesbarkeit des Programms den jeweiligen Schaltzustand binär, also mit PortC = &Bxxxxxxx am Ende auszugeben und zuvor im "select case"-Teil das Bitmuster aufzubauen. Wobei ich mir aber icht sicher bin, ob ich damit die Ursache behebe.
      Daher meine Frage: Wäre das ein Erfolg versprechender Weg oder habt ihr noch andere Lösungsvorschläge für mich?
      Beste Grüße
      Jürgen
    • Durch eine andere Schreibweise änderst du an der (Fehl)funktion nix. Sind vielleicht deine Abgrenzungen zu nah beieinander? Wswitchhigh(2) und wswitchlow(3) zum Beispiel? Eine Erhöhung der Taktfrequenz wird die Auflösung erhöhen und du könntest da feinfühliger einen Abstand einbauen.
      Was meinst du mit 'temporär abschalten'?
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Hi JuWi
      wie die Vorredner bereits geschrieben haben, ist zur Problemlösung Dein ganzes Programm nötig. Ich habe bisher auch einiges im RC Bereich gebastelt. Erfahrungsgemäß war seltener der Programmcode zur Datenausgabe schuld an Fehlfunktionen, sondern der Teil, der das RC Signal einliest. Meine häufigsten Fehler waren:
      - Zu eng gesetzte Schaltschwellen
      - Verpasste RC-Flanken, weil gerade eine andere ISR abgearbeitet wurde
      - RC Abfragen an falscher Stelle im Code (und damit Konflikte mit vorherigem RC-Wert)
      - Zu häufige RC-Abfragen (gerade bei einfachen Schaltaufgaben braucht der RC Wert nicht 50x pro Sekunde abgefragt werden)
    • Hallo Juwi,

      vielleicht kommt Dein Problem von einem Effekt, den man mit einem Bild besser beschreiben kann als mit tausend Worten:

      Das untere Rechtecksignal auf dem Bildchen soll der Timer-Takt sein, das obere der zu messende Impuls.
      Wie man sehen kann, fallen in den ersten zu messenden Impuls zwei fallende Timer-Flanken, in den rechten aber nur eine. Obwohl beide Impulse exakt gleich lang sind, würde der Timer einmal eine Taktlänge und einmal zwei Taktlängen messen.

      Der Grund liegt darin, dass Timertakt und die zu messenden Impulse nicht aufeinander synchronisiert sind, sondern sich frei gegeneinander verschieben. Und das ist ja auch die Realität, wenn man mit einem Mikrocontroller die Länge eines extern angelegten Impulses misst.

      Du kannst ja mal das Experiment machen, einen absolut konstanten Impuls (z.B. einen Empfängerausgang bei absolut unbewegtem Steuerknüppel) kontinuierlich auszumessen und Dir jedes Ergebnis per UART auf dem PC anzegen zu lassen. Du wirst sehen, dass die einzelnen Ergebnisse immer um +/1 schwanken werden, obwohl der Impuls immer der gleiche ist.

      Diese Schwankung hat in der Mitte eines definierten Zielbereiches keinen Effekt, weil auch ein Wert drüber oder drunter noch im selben Zielbereich liegen würde. Wenn Du aber so nahe an die Grenze kommst, dass ein Zählwert mehr schon die nächste Schalt-Bedingung erfüllt, kommt es zu ungewollten Schaltvorgängen.

      Versuch doch mal was passiert, wenn Du zwischen Deinen Bereichen einen kleinen "Puffer" lässt, der größer ist als die systembedingte Schwankung um 1, also z.B. so:

      wSwitchLow(1) = 100
      wSwitchHigh (1) = 200

      wSwitchLow(2) = 202
      wSwitchHigh (2) = 300

      wSwitchLow(3) = 302
      wSwitchHigh (3) = 400

      Impulsmessung.jpg
    • Hallo,
      erst einmal vieolen Dank für eure Anregungen. Hier nun das ganze Programm (ich dachte, das wäre eventuell etwas zu viel zum Lesen...); ein paar Zeilen sind noch auskommentiert, das wird dann später getestet.
      (Ich musste es als Datei anhängen, da der Editor zu viele Zeichen angemeckert hat)

      Ich verwende die Taranis X9E von FrSky. Mit etwas Hilfstellung hier im Forum habe ich die Impulserkennung zum Laufen gebracht. Auf dem Testboard (von Pollin) ist das eingangs geschilderte Verhalten nicht aufgetreten, aber da läuft das Programm auch zeitlich etwas anders ab wegen der eingebauten Ausgaben auf dem LC-Display des Erweiterungs-Boards.
      Am Ende soll bei der ganzen Übung tatsächlich so etwas herauskommen wie die Lichtsteuerung eines Jeep (Wrangler von Axial).
      Meine ersten Versuche habe ich mit einem Prescale-Faktor von 8 gemacht. Aber da waren mir dann die Schaltabstände zu klein, so dass ich diesen Faktor jetzt auf 1 gesetzt habe. Die Ergebnisse habe ich hier zusammen gefasst:
      bascomforum.de/index.php?attac…a70050db84e5e80cd036a57fc
      Die Abstände zwischen den einzelnen Schaltzuständen sind mit ca. 70 und der Toleranz mE groß genug, um sich nicht gegenseitig zu stören.
      Meine Frage zum "Abschalten" bezieht sich auf meine Überlegung, das Ausgangssignal an den Ports so lange stehen zu lassen (konstant zu halten) bis ein neuer Schaltzustand anliegt. Also idealerweise so etwas wie (Port-Zustand alt aktiv, RC-Signal lesen, wenn Signal verändert dann Port-Zustand neu, Port-Zustand neu aktiv, Port aktivieren). Damit wollte ich die beobachteten, manchmal kurzfristig auftretenden und ungewollten Schlatzustände unterbinden.

      Zu euren Fragen:
      @Mitch64: Dem Sender habe ich beigebracht, auf einem Kanal in Abhängigkeit von diversen Schaltern unterschiedliche Impulsl#ngen zu übertragen.
      @Einzeller: Wenn ich deinen Vorschlag richtig verstanden habe, dann habe ich diesen "Abstand" zwischen den Schaltzuständen schon eingebaut. Lt. der obigen Tabelle hat das Signal für den Zustand 1 einen Wert von 1060 (dr schwankt natürlich etwas), geschaltet wird aber aufgrund der Toleranz zwischen 1040 und 1080, der nächste Zustand ist aktive im Bereich 1111 bis 1151.
      Dateien
      Beste Grüße
      Jürgen
    • Dein Bild ist leider nicht zum öffnen. Bilder müssen auch über 'Dateinhänge' hochgeladen werden und dann kann eine 'Vorschau' im Text eingefügt werden. Das Bild kann dann von allen Lesern geöffnet werden.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • @JuWi mal was zu deiner Select Case Struktur: Wären da Konstanten nicht besser als Variablen. Denn eine Variable kann sich, wie der Name schon sagt, verändern und eine Konstante nicht. Wenn die Abfragen in der Select Case also immer gleich zum Signal sind kannst du dort auch Konstaten nehmen.

      BASCOM-Quellcode

      1. Select case wPulseSwitch 'port activation
      2. Case 1040 to 1080
      3. toggle BlinkLeft : BlinkRight = 0
      4. LightBar = 0
      5. LowLight = 0 : HighLight = 0 : RearLight = 0
      6. Case 1111 To 1151
      7. ......
      8. End Select
      Das oben gezeigte soll nur als Beispiel dienen.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.
    • JuWi schrieb:

      zu Lasten der Lesbarkeit des Programms den jeweiligen Schaltzustand binär, also mit PortC = &Bxxxxxxx am Ende auszugeben und zuvor im "select case"-Teil das Bitmuster aufzubauen. Wobei ich mir aber icht sicher bin, ob ich damit die Ursache behebe.
      Bytes anstelle Alias und zum Schluß zu einem Ausgangsbyte verarbeiten wird die Lesbarkeit erhalten.
      Das Flackern sind vermutlich Störungen? Mehrfachabfragen und zum Schluß auswerten (3von5=High)?
      Oder gleich die "insari-"Methode mehr als 100 von 200 = High . wie lang sind die Pulse? ca 1ms?
    • @tschoeatsch: Im Editor hat er mir das Bild gezeigt, deshalb habe ich angenommen, dass es auch für andere sichtbar ist. Aber ich hänge es hier noch einmal an.

      @djmsc: Die Variablen-Lösung ist aus dem Gedanken heraus entstanden, dass die Impulslänge von Fernsteuerung zu Fernsteuerung etwas unterschiedlich sind. Bei einem anderen Empfänger wäre dann nur eine erneute Kalibrierung beim ersten Start erforderlich.

      @Pluto25: Impulslänge ist zwischen 1 und 2 ms. Was genau meinst du mit der "insari-Methode". Der Begriff sagt mir erst einmal nichts.

      Ich werde es, sobald ich die neue Platine fertig habe, mit dieser Konstruktion versuchen:

      Quellcode

      1. dim bCommand as byte 'switch command to port C
      2. select case wPulseSwitch 'port activation
      3. 'Port C scheme
      4. 'nc - nc - high - low - backup - bar - right- left
      5. case wSwitchLow(1) to wSwitchHigh(1) 'Blinker left
      6. if bCommand = &B0000001 then bCommand = &B00000000
      7. case wSwitchLow(2) to wSwitchHigh(2) 'Blinker right
      8. if bCommand = &B0000010 then bCommand = &B00000000
      9. case wSwitchLow(3) to wSwitchHigh(3) 'Blinker warn
      10. if bCommand = &B0000011 then bCommand = &B00000000
      11. case wSwitchLow(4) to wSwitchHigh(4) 'Light bar
      12. bCommand = &B0000100
      13. case else
      14. bCommand = &B00000000
      15. end select
      16. Portc = bCommand
      Alles anzeigen
      Die anderen Schalter werden natürlcih auch noch so geändert.
      Beste Grüße
      Jürgen
    • Hallo Jürgen,

      ich habe mir Dein Programm aus Post 7 nochmal genauer angesehen.
      Du nutzt Timer und Interrupts, um Deine RC Signale schnell und ohne längerem Ausbremsen des Hautprogramms einzulesen, aber gleichzeitig bremst Du Dein Hauptprogramm extrem aus mit dem Erfassen und Berechnen von wPulseSpeed und wPulseSwitch (je 5x20ms, also 200ms insgesamt). Grundsätzlich ist das bei einer einfachen Beleuchtungssteuerung auch kein Problem, allerdings würde ich dann eher mit Pulsein arbeiten und die "wertvollen" Timer z.B. für die Frequenz der Blinker einsetzen.

      Bei der von Dir gewählten Methode (Interrupts und Timer) KANN allerdings folgendes passieren: Ein Flankenwechsel des einen RC-Signals (z.B. Speed) löst den dazugehörigen Interrupt aus. Unmittelbar danach löst das andere RC-Signal (Switch) einen Interrupt aus. Dieser wird aber erst dann abgearbeitet, wenn der erste Interrupt (Speed) fertig abgearbeitet ist. Dadurch wird die Messung des zweiten RC-Signals (Switch) verfälscht. Ob dies allerdings ausreicht, um Deine Fehlfunktionen auszulösen, kann ich leider nicht beurteilen.

      Ein weiterer Punkt ist mir aufgefallen: In Deiner SelectCase Abfrage hast Du richtigerweise "Todbänder" zwischen den einzelnen Bereichen eingebaut. Damit verhinderst Du wildes hin- und herspringen, wenn sich wPulseSwitch im Grenzbereich zwischen 2 benachbarten Cases befinden würde. Dies machst Du aber zunichte mit "case else", den nun springst Du zwischen einem der definierten Cases und case else hin und her.

      Deine Bremslichter bremsen ebenfalls buchstäblich dein Hauptprogramm aus (und wirken sich auf Deine Blinkerfrequenz aus). Versuche, wait-Befehle gering und kurz zu halten. Früher oder später fehlt Dir einfach die Zeit dafür. Bei Deiner Anwendung (Bremslichter) könntest Du das waitms 300 durch eine Zählvariable umgehen, die das Bremslicht nach einer bestimmten Anzahl von Programmdurchläufen wieder ausschaltet. Wenns genauer sein soll/muss, kann man auch hier wieder auf einen Timer zurückgreifen.

      BASCOM-Quellcode

      1. Dim Programmdurchlaufzaehler As Word
      2. if wSpeedBreak > SpeedDelta then
      3. Breaklight = 1
      4. Incr Programmdurchlaufzaehler
      5. If Programmdurchlaufzaehler > 1000 Then
      6. Breaklight = 0
      7. Wspeedbreak = Wpulsespeed
      8. Programmdurchlaufzaehler = 0
      9. End If
      10. End If
      Alles anzeigen

      Netter Grüße
      Robert
    • JuWi schrieb:

      "insari-Methode"
      Ist nicht wirklich ein Fachbegriff: Insari ist ein Forenmitglied und seine Listings enthalten so richtig viele Abfragen wodurch einzelne Ausreißer das Ergebniss nicht mehr "verschmutzen".


      JuWi schrieb:

      mit dieser Konstruktion versuchen:
      Das ist nun nicht mehr übersichtlich und wird dann schwierig wenn mehreres gleichzeitig ausgegeben werden muß: z.b. Licht+Blinker
      Würde jede Funktion seinen Namen als Byte behalten könnte zum Schluß einfach "aufaddiert" werden:
      Port c.0=Blinker_links
      Portc.1=....
      oder if Blinker_links >100 then set Portc.0 falls 200 Abfragen durchlaufen werden. Bei 2ms würde dann die Ausbabe ca 2 mal pro Sekunde aktualisiert.
      Wie sauber sind die Signale? Keine Spannungseinbrüche mitten drin oder Peeks in den Pausen?
      Wie lang sind die Pausen?

      @R2D2Bastler Sollte ein endif nicht vor Zeile6? So geht das Bremslicht entweder garnicht mehr aus oder nach 1000 Durchläufen obwohl noch gebremst wird.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von Pluto25 ()

    • Mein Beispiel war nur der "innere" Teil einer weiteren If-Abfrage, war aber trotzdem falsch, da Wspeedbreak = Wpulsespeed nicht innerhalb der If Abfrage stehen darf. a_67_e210de67

      Pluto25 schrieb:

      So geht das Bremslicht entweder garnicht mehr aus oder nach 1000 Durchläufen obwohl noch gebremst wird.
      Im Originalcode wurden die Bremslichter erst dann abgeschaltet, wenn die Geschwindigkeit (Wpulsespeed) im Vergleich zur letzten Messung gleich geblieben oder wieder zugenommen hat. Ich vermute mal, die 300ms wurden gesetzt, damit die Bremslichter eine bestimmte Mindestleuchtdauer haben, auch wenn gleich nach dem Bremsen sofort wieder beschleunigt wird.

      So müsste es gehen:

      BASCOM-Quellcode

      1. Dim Programmdurchlaufzaehler As Word
      2. If Wpulsespeed >= Wspeedbreak Then 'brake light switch
      3. If Breaklight = 1 Then
      4. Incr Programmdurchlaufzaehler
      5. If Programmdurchlaufzaehler > 1000 Then 'hier Mindestleuchtdauer vom Breaklight einstellen
      6. Breaklight = 0
      7. Programmdurchlaufzaehler = 0
      8. End If
      9. End If
      10. Else
      11. Wspeedbreak = Wspeedbreak - Wpulsespeed
      12. If Wspeedbreak > Speeddelta Then
      13. Breaklight = 1
      14. End If
      15. End If
      16. Wspeedbreak = Wpulsespeed 'stores current speed
      Alles anzeigen

      PS: Der Wert 1000 ist bei diesem Programm natürlich viel zu hoch, da das Hauptprogramm (sofern die RC Abfrage nicht geändert wird) ja immer noch ca 200ms für einen Durchlauf braucht. Solage reicht anstelle der 1000 auch der Wert 1 oder 2
    • R2D2 Bastler schrieb:

      Wspeedbreak = Wspeedbreak - Wpulsespeed
      Ist Wspeedbreak nicht der (konstante minimum-)Wert zur Bremserkennung? Dann sollte er nicht in der Schleife verändert werden sonst bremslichtet er sonstwann oder gar nicht mehr.
      Der Vorteil der Flags ist das sie während der Schleife beliebig verändert werden können ohne das es flackert. Daher können die Abfragen eigenständig sein und müssen nicht ein einer "If Verwirrung " stehen:

      Wspeedbreakmax = Wspeedbreak + Speeddelta

      Quellcode

      1. If Wpulsespeed >= Wspeedbreak and Wpulsespeed<Wspeedbreakmax Then
      2. Breaklight = 1
      3. Programmdurchlaufzaehler = 10
      4. end if
      5. if Programmdurchlaufzaehler > 0 then decr Programmdurchlaufzaehler
      6. if Programmdurchlaufzaehler = 0 then Breaklight=0
      7. .
      8. .
      9. .
      10. Portx,y = Breaklight
    • Pluto25 schrieb:

      Ist Wspeedbreak nicht der (konstante minimum-)Wert zur Bremserkennung?
      So wie ich das aus dem Originalcode rauslese, ist Wspeedbreak die Variable, die den Wert der letzen RC-Messung sichert, um ihn mit der aktuellen Messung zu vergleichen (also nicht konstant). Innerhalb der IF-Abfrage wird Wspeedbreak auch mal als Hilfsvariable missbraucht, sollte aber kein Problem darstellen, da unmittelbar danach der Wert der aktuellen Messung wieder in Wspeedbreak geschrieben wird.

      Den Programmdurchlaufzaehler zu setzen und außerhalb der Abfrage runterzählen lassen, ist natürlich deutlich übersichtlicher (warum komme ich nicht auf so einfache Lösungen :whistling: )

      Dies sollte funktionieren

      BASCOM-Quellcode

      1. Dim Programmdurchlaufzaehler As Byte
      2. .
      3. .
      4. .
      5. If Wpulsespeed < Wspeedbreak Then 'brake light switch
      6. Wspeedbreak = Wspeedbreak - Wpulsespeed
      7. If Wspeedbreak > Speeddelta Then
      8. Breaklight = 1
      9. Programmdurchlaufzaehler = 10 'hier Mindestleuchtdauer vom Breaklight einstellen
      10. End If
      11. End If
      12. If Programmdurchlaufzaehler > 0 Then Decr Programmdurchlaufzaehler
      13. If Programmdurchlaufzaehler = 0 Then Breaklight = 0
      14. Wspeedbreak = Wpulsespeed 'stores current speed
      Alles anzeigen

      Nette Grüße
      Robert
    • Hallo,
      nicht, dass ihr denkt, das Thema wäre entschlafen...
      Ich kämpfe nur gerade mit der Schaltung. Die habe ich neu gemacht wegen einer nicht funktionierenden Hardware-Verbindung (war ein Gedankenfehler von mir). Obwohl die wesentlichen Teile unverändert sind, tut sich gerade mehr oder weniger gar nichts. Der µC weigert sich, auch nur einen Ausgang zu schalten. Die Kalibrierung der Impulslänge macht er, aber das war's. Auch ein Aufbau mit neuen Bauteilen (kann ja immerhin sein, dass beim Auslöten etwas schief gegangen ist) bringt kein anderes Resultat.
      Ich verstehe nur gerade nicht, warum ein Teil des Programms läuft und der Rest nicht a_67_e210de67
      Beste Grüße
      Jürgen