Uraltes Programm geändert- warum funktionierts nicht?

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

    Aufgrund technischer Veränderungen ist der Mailverkehr innerhalb des Forums (Private Nachrichten) nur noch eingeschränkt möglich. Die Einschränkung ist notwendig, um zusätzliche Betriebskosten für das Forum zu vermeiden. Näheres zu den Hintergründen im Thread "Aktuelles zum Forum".Wir bitten um Verständnis.

    Hinweis kann nach Kenntnisnahme deaktiviert werden!

    • Uraltes Programm geändert- warum funktionierts nicht?

      Hallo,

      ich hab mir vor fast 20 Jahren ein Messgerät gebaut, mit dem ich Treppen und ähnliches aufmesse.
      Da ist unter anderem ein kleines Modul mit einem Mega16 drin, mit dem ich mittels
      eines Encoderschaltkreises (HCTL2020) messe, wie lang ein dünnes Edelstahlseil ausgezogen
      ist.
      Sehr selten gab es das Problem, das ein sogenannter Unterlauf aufgetreten ist, oder wie nennt
      man das Gegenteil vom Überlauf?
      Ich hatte mal vor Jahren das Überlaufproblem beseitigt, da es in ganz seltenem Extremfällen
      passiert ist, das der 16Bit Zähler des HCTL2020 übergelaufen ist (Zeile 69-72). das habe ich
      aber nur mangelhaft programmiert, denn dadurch trat das Unterlaufproblem auf.
      Immer dann, wenn sich nach dem Einschalten durch eventuelle mechanische Erschütterungen
      die Seiltrommel sich mal gurz um einen winzigen Betrag rückwärts gedreht hatte.
      In Zeile 71 müßte der Wert also nicht 0 sondern -32768 sein.
      Das Programm ist nicht schön, aber eben auch uralt, seht es mir nach. Diese Unterlaufgeschichte
      trat in den vielen Jahren vielleicht 5 Mal auf.
      Nun wollte ich das Problem doch beseitigen, denn manchmal fahre ich lange Strecken um mal was aufzumessen
      und dann wäre es doch ärgerlich. Außerdem ändere ich sowieso noch eine andere Sache am Gerät.

      Das neue Programm habe ich ausgiebig im Simulator getestet und da läuft es eigentlich. Was mir
      aufgefallen ist, ich hab ausversehen zweimal den Befehl End eingefügt und außer den notwendigen Änderungen
      Enable Interrupts zu den Initialisierungen verschoben.
      Das Pogramm wartet, bis der Befehl "1" über die serielle Schnittstelle kommt und sender dann
      einen Analogwert (Biegebalken mit Dehnungsmeßstreifen) und den Zählerwert.
      Das man das besser mit einem Interrupt lösen kann, ist mit bewußt. ja und Gosub nimmt man auch nicht. a_19_23577ce2

      Ich würde jetzt erst mal Einiges ausprobieren aber das ist aufwendig. Ich komm da mechanisch schlecht ran,
      und dachte, vielleicht fällt jemand der Fehler sofort ins Auge. Es scheint so, als wenn das Programm
      gar nichts, oder null sendet.

      Fällt da jemand, außer den Schönheitsfehlern was auf?

      Danke! a_58_b54cfdb4

      Gruß Ralf

      Originalprogramm:

      BASCOM-Quellcode

      1. $regfile = "m16def.dat" 'Definituonsdatei für Mega16
      2. $crystal = 16000000 'Quarz: 16 MHz
      3. $baud = 38400 'Baudrate der UART: 9600 Baud
      4. Dim Variable As Word
      5. Dim Lwert As Byte
      6. Dim Hwert As Byte
      7. Dim Encoders As Word
      8. Dim Ueberl As Word
      9. Dim I As Byte
      10. Config Portc = Input
      11. Config Portd.2 = Input 'U/D HCTL
      12. Config Portd.4 = Output 'Shutdown Pin RS232
      13. Config Portd.5 = Output 'Reset Pin HCTL2020
      14. Config Portd.6 = Output 'O/E Pin HCTL2020
      15. Config Portd.7 = Output 'SEL Pin HCTL2020
      16. Portd.2 = 1
      17. Reset Portd.4 'Sender hochohmig
      18. Set Portd.5 'Pin auf High
      19. Set Portd.6
      20. Set Portd.7
      21. Waitms 10 'Reset HCTL2020
      22. Reset Portd.5
      23. Waitms 10
      24. Set Portd.5
      25. Waitms 10
      26. Ueberl = 0
      27. On Int1 Ueberlauf
      28. Enable Int1
      29. Config Int1 = Rising
      30. Config Adc = Single , Prescaler = 128 , Reference = Internal
      31. Start Adc 'ADC starten
      32. Do 'Endlosschleife
      33. If Usr.rxc = 1 Then 'Wenn Byte empfangen...
      34. I = Udr 'Byte aus UART auslesen
      35. If I = "1" Then 'Wenn Kennung stimmt...
      36. Gosub Senden 'Daten senden
      37. End If
      38. End If
      39. Loop
      40. End
      41. Senden:
      42. Enable Interrupts
      43. Reset Portd.6 'Output Enable
      44. Reset Portd.7 'SEL auf Low
      45. Waitms 1
      46. Hwert = Pinc 'höherwertiges Byte einlesen
      47. Set Portd.7 'SEL umschalten
      48. Waitms 1
      49. Lwert = Pinc 'niederwertiges Byte einlesen
      50. Waitms 1
      51. Set Portd.6 'O/E deaktivieren
      52. Encoders = Hwert * 256 'Werte zusammensetzen
      53. Encoders = Encoders + Lwert
      54. Encoders = Encoders / 2
      55. Encoders = Encoders + Ueberl
      56. Variable = Getadc(0) 'AD Wandler auslesen
      57. Set Portd.4 'RS232 aktivieren
      58. Waitms 1
      59. Printbin Encoders ; Variable 'Werte ausgeben
      60. Waitms 100
      61. Reset Portd.4 'Sender abschalten
      62. Return
      63. Ueberlauf:
      64. If Pind.2 = 1 Then Ueberl = 32768
      65. If Pind.2 = 0 Then Ueberl = 0
      66. Return
      Alles anzeigen


      Meine Verschlimmbesserung:

      BASCOM-Quellcode

      1. $regfile = "m16def.dat" 'Definituonsdatei für Mega16
      2. $crystal = 16000000 'Quarz: 16 MHz
      3. $baud = 38400 'Baudrate der UART: 9600 Baud
      4. Dim Variable As Word
      5. Dim Lwert As Byte
      6. Dim Hwert As Byte
      7. Dim Encoders As Word
      8. Dim Ueberl As Long , Ueberl_temp As Long
      9. Dim I As Byte
      10. Config Portc = Input
      11. Config Portd.2 = Input 'U/D HCTL
      12. Config Portd.4 = Output 'Shutdown Pin RS232
      13. Config Portd.5 = Output 'Reset Pin HCTL2020
      14. Config Portd.6 = Output 'O/E Pin HCTL2020
      15. Config Portd.7 = Output 'SEL Pin HCTL2020
      16. Portd.2 = 1 'Pullup= EIN
      17. Reset Portd.4 'Sender hochohmig
      18. Set Portd.5 'Pin auf High
      19. Set Portd.6
      20. Set Portd.7
      21. Waitms 10 'Reset HCTL2020
      22. Reset Portd.5
      23. Waitms 10
      24. Set Portd.5
      25. Waitms 10
      26. Ueberl = 0
      27. On Int1 Ueberlauf
      28. Config Int1 = Rising
      29. Enable Int1
      30. Enable Interrupts
      31. Config Adc = Single , Prescaler = 128 , Reference = Internal
      32. Start Adc 'ADC starten
      33. Do 'Endlosschleife
      34. If Usr.rxc = 1 Then 'Wenn Byte empfangen...
      35. I = Udr 'Byte aus UART auslesen
      36. If I = "1" Then 'Wenn Kennung stimmt...
      37. Gosub Senden 'Daten senden
      38. End If
      39. End If
      40. Loop
      41. End
      42. Senden:
      43. Reset Portd.6 'Output Enable
      44. Reset Portd.7 'SEL auf Low
      45. Waitms 1
      46. Hwert = Pinc 'höherwertiges Byte einlesen
      47. Set Portd.7 'SEL umschalten
      48. Waitms 1
      49. Lwert = Pinc 'niederwertiges Byte einlesen
      50. Waitms 1
      51. Set Portd.6 'O/E deaktivieren
      52. Encoders = Hwert * 256 'Werte zusammensetzen
      53. Encoders = Encoders + Lwert
      54. Ueberl_temp = Ueberl + Encoders 'Überlauf bzw. unterlauf addieren
      55. Ueberl_temp = Ueberl_temp / 2 'halbieren (Wertebereich Wordvariable)
      56. If Ueberl_temp > 65535 Then Ueberl_temp = 65535 'sicherheitshalber Wertebereich begrenzen
      57. If Ueberl_temp < 0 Then Ueberl_temp = 0
      58. Encoders = Ueberl_temp 'halbieren (Wertebereich Wordvariable)
      59. Variable = Getadc(0) 'AD Wandler auslesen
      60. Set Portd.4 'RS232 aktivieren
      61. Waitms 1
      62. Printbin Encoders ; Variable 'Werte ausgeben
      63. Waitms 100
      64. Reset Portd.4 'Sender abschalten
      65. Return
      66. Ueberlauf:
      67. If Pind.2 = 1 Then 'Überlauf
      68. Ueberl = Ueberl + 65536
      69. Else 'Unterlauf
      70. Ueberl = Ueberl - 65536
      71. End If
      72. Return
      73. End
      Alles anzeigen
    • So wie ich das Datenblatt mal kurz überflogen habe, ist deine Art zu zählen nicht die vorgesehene Art ;)
      Nach meinem Verständnis gibt dir der Chip auf Anfrage einen 16 Bit Wert des Aktuellen Zählerstandes.
      Du liest den Zähler aus, addierst den Wert zu deinem internen Zähler und löschst den Zählerstand des HCTL2020
      Das ganze natürlich bevor der interne Zähler des HCTL überläuft.
      Der Überlaufimpuls zeigt dir dann an, dass du nicht schnell genug warst und die internen Daten ungültig sind - Meustart mit Referenz nötig.

      Wie groß ist denn dein erwarteter Wertebereich?

      Dein Programm hat übrigens keine Stackwerte eingetragen.
      Für Interrupts und Printausgaben und Unterprogramme braucht es Stackwerte.

      $hwstack= 32
      $swstack=16
      $framesize=32

      kannst du dem Prozessor noch gönnen, sonst gibt es unschöne Effekte
    • Hallo Michael,


      Michael schrieb:

      So wie ich das Datenblatt mal kurz überflogen habe, ist deine Art zu zählen nicht die vorgesehene Art
      Nach meinem Verständnis gibt dir der Chip auf Anfrage einen 16 Bit Wert des Aktuellen Zählerstandes.
      Du liest den Zähler aus, addierst den Wert zu deinem internen Zähler und löschst den Zählerstand des HCTL2020
      Das wäre mir neu und ich habe damal sehr viel mit diesen Bausteinen gearbeitet.


      Michael schrieb:

      Das ganze natürlich bevor der interne Zähler des HCTL überläuft.
      Der Überlaufimpuls zeigt dir dann an, dass du nicht schnell genug warst und die internen Daten ungültig sind - Meustart mit Referenz nötig.
      Der Überlaufimpuls wird doch hauptsächlich im Zusammenhang mit dem U/D Pin benutzt, um den Wertebereich zu erweitern, könnte also mit einen Zähler IC kaskadiert werden. Irre ich mich da?


      Michael schrieb:

      Wie groß ist denn dein erwarteter Wertebereich?
      Passt zu 99% in den 16 Bit Zähler. Wird das Seil extrem weit ausgezogen, dann wäre es mechanisch möglich, das er Überläuft. Das vermeide ich aber, um das Gerät nicht zu beschädigen.
      Einmal ist es wohl passiert, deshalb habe ich vor ca. 5 Jahren die fehlerhafte ISR eingefügt.


      Michael schrieb:

      Dein Programm hat übrigens keine Stackwerte eingetragen.
      Für Interrupts und Printausgaben und Unterprogramme braucht es Stackwerte.

      $hwstack= 32
      $swstack=16
      $framesize=32

      kannst du dem Prozessor noch gönnen, sonst gibt es unschöne Effekte
      Das ist ein guter Tip, sitze gerade dran und werde das erledigen.

      Danke! :)
    • Ich hatte ja irrtümlich zwei END Befehle im Programm, in Zeile 44 und in Zeile 79.
      Könnte da der Fehler sein, hat das einen Einfluß?

      Die Stackwerte sind noch nicht dran, aber es funktioniert scheinbar schon. Die kommen natürlich noch rein, ich wüßte nur zu gern die Ursache. a_27_b277ca12
    • Läuft einfach Instabil.
      Ich habe die fehlerhafte Überlaufbehandlung jetzt rausgenommen, jetzt ist das Programm wieder im Urzustand wie vor knapp 20 Jahren.
      Da sind etliche ATMegas drin die über die RS232 Schnittstelle angesprochen werden. Auf Befehl aktivieren die jeweils die Schnittstelle und senden die Daten. Wenn irgendeiner nicht schnell genug reagiert, ist alles blockiert. Eine Fehlerbehandlung habe ich im Hauptcontroller nicht programmiert.
      Ich könnte da was machen, aber der ist uralt und nicht mehr lieferbar. (Basic Tiger von Wilke)
      Wenn was schiefgehen würde, kann ich das Gerät erst mal vergessen und ich brauche es für meine Arbeit.

      So läuft alles und das "Unterlaufproblem" ist auch gelöst. (Wie nennt man eigentlich das Gegenteil vom Überlauf?)
    • Ralf schrieb:

      Der Überlaufimpuls wird doch hauptsächlich im Zusammenhang mit dem U/D Pin benutzt, um den Wertebereich zu erweitern, könnte also mit einen Zähler IC kaskadiert werden. Irre ich mich da?
      Ich nehme an, U/D ist an Pind.2? und an PinD.3 hängt CAS?

      Ralf schrieb:

      Könnte da der Fehler sein, hat das einen Einfluß?
      Nein, deine END-Befehle stehen außerhalb und haben deshalb keinen Einfluss auf das normale Programm.

      Ralf schrieb:

      Die Stackwerte sind noch nicht dran, aber es funktioniert scheinbar schon.
      Irrtum, das mit den Stackwerten habe ich ernst gemeint.
      Ohne Stackwerte kannste auch 3 Würfel werfen oder einen Affen nehmen (zum zählen, nicht zum werfen ;) )

      Wie schon gesagt, der Chip zählt einen Encoder rauf und runter mit 16 Bit und Überlauf. Ein Latch dazwischen lässt Zeit, um die 16 Bit auf 2 mal auszugeben.
      Deine Wartezeiten von 1ms (Zeile 49-54) sind viel zu lang. DerChip braucht 65 ns für die Bereitstellung der Daten. Etwa eine Taktdauer deines Atmega 16.
      Wenn du da ein NOP einfügst, reicht das als Wartezeit.

      Ich verstehe Zeile 59 nicht ganz, dort halbierst du die Summe aus Zählerstand und Überläufen.
      spätestens nach 2 Überläufen bist du nicht mehr im Wertebereich und die Daten werden durch das begrenzen auch gleich, ähh, ja, ruiniert.
    • Michael schrieb:

      ch nehme an, U/D ist an Pind.2? und an PinD.3 hängt CAS?
      Genau.


      Michael schrieb:

      Irrtum, das mit den Stackwerten habe ich ernst gemeint.
      Ohne Stackwerte kannste auch 3 Würfel werfen oder einen Affen nehmen (zum zählen, nicht zum werfen )
      Die habe ich inzwischen reingenommen.


      Michael schrieb:

      Deine Wartezeiten von 1ms (Zeile 49-54) sind viel zu lang. DerChip braucht 65 ns für die Bereitstellung der Daten. Etwa eine Taktdauer deines Atmega 16.
      Wenn du da ein NOP einfügst, reicht das als Wartezeit.
      Da wirst du recht haben, aber wenn du Daten liest sind die ja im Latch gespeichert und der HCTL zählt trotzdem weiter. Das könnte ich natürlich noch ändern. :thumbup:


      Michael schrieb:

      Ich verstehe Zeile 59 nicht ganz, dort halbierst du die Summe aus Zählerstand und Überläufen.
      spätestens nach 2 Überläufen bist du nicht mehr im Wertebereich und die Daten werden durch das begrenzen auch gleich, ähh, ja, ruiniert.
      Einfach um den erwarteten Wertebereich in eine Wordvariable zu bekommen. Nach oben kann es zu maximal einem Überlauf kommen und auch das will ich vermeiden. Ich müße das Meßseil 370cm ausziehen und da ist die Feder in der Aufwickelvorrichtung an der Grenze. Die übliche Länge liegt so bei maximal 250cm eventuell auch mal 300cm.

      Das Problem bei meiner oberen Version lag ganz einfach in Zeile 71, da müßte nicht 0 sondern -32768 stehen.
    • Michael schrieb:

      Ralf schrieb:

      aber wenn du Daten liest sind die ja im Latch gespeichert und der HCTL zählt trotzdem weiter.
      du hast geschrieben, dass du ein Timingproblem hast. Bei 38400 Baud sind die 3 eingesparten ms etwa 11 übertragene Bytes.
      Gutes Argument, du meinst ein NOP reicht?
      Ich glaube damals wußte ich gar nicht,, das es auch den Befehl Waitus gibt. a_45_132ca9f5
      Meine ich Ernst.
    • Michael schrieb:

      1 Takt bei 16 MHz sind 62,5ns.
      Der Chip braucht 65ns zwischen Anfordern der Daten und Bereitstellung.
      Der AVR braucht ja mindestens einen Takt vom Schalten des SEL bis zum Lesen des PINC
      Wenn du also noch ein NOP einschiebst als Pause, hast du 125ns Wartezeit gehabt.
      Ich hab ja da viermal Waitms 1 drin, beim RS232 Baustein müßte ich mal schauen, was drin ist und was das Datenblatt sagt.
      Die anderen drei, könnte ich die auch verkürzen?
      Bringt es was, das Auslesen des AD Wandlers in die Do Loop Schleife zu verschieben?
    • Michael schrieb:

      Meinst du einen Wandlerchip?
      Da sind abschaltbare RS232 Treiber drin, die einzelnen ATMEGAS können ja am gemeinsamen Anschluß empfangen, aber senden darf nur Einer.

      Michael schrieb:

      Wie sieht die Schaltung aus?
      Vom Gesamtprojekt? Die ist aufgesplittet in Hauptplatine und in die einzelnen Sensorplatinen. Falls es Jemand interessiert und ich sie noch finde, kann ich gern was reinstellen

      Michael schrieb:

      100ms Wartezeit nach dem Senden sind sicher auch nicht nötig, der AVR macht weiter, wenn das letzte Byte an den UDR übergeben wurde, bei 38400 wäre dann höchstens noch eine Wartezeit von 270µs nötig
      Stimmt, aber es läuft ja und am Hauptprogramm, das auf dem Basic Tiger läuft wäre es mir zu riskant was zu ändern. Ideen hätte ich einige, aber dann müßte ich wenigstens Einen in Reserve haben. Es gibt sogar einen Nachfolger, der ist softwaremäßig vollständig kompatibel, hat aber 3,3 Volt Pins.
    • Counter schrieb:

      Du definierst deine "Dim Ueberl As Word"
      und willst später -32768?
      Word kann kein Minus.
      Du musst da eine Integer Variable für Minus nehmen.
      Morgen Counter,

      das ist schon klar, ich meinte nur die Zahl hätte eigentlich statt 0 -32768 sein sollen.
      Die Variablentypen müßten angepasst werden. Kannst ja mal in das zweite Programm schauen.

      Im Simulator läuft es , im Gerät nicht so richtig. Mit den Variablentypen habe ich mich etwas schwergetan,
      hätte man sicher eleganter lösen können.

      Gruß Ralf
    • Counter schrieb:

      Du musst da eine Integer Variable für Minus nehmen.
      im 2. Programm wird Long benutzt (+/- 2^31-1)



      Ralf schrieb:

      Bringt es was, das Auslesen des AD Wandlers in die Do Loop Schleife zu verschieben?
      Es ist bereits in der Do-Loop-Schleife und wird auf Anfrage ausgeführt. Das Gosub verzögert nur um 2 Takte aber verbessert die Programmierung

      Ralf schrieb:

      Stimmt, aber es läuft ja

      Ralf schrieb:

      Im Simulator läuft es , im Gerät nicht so richtig.
      Ich werd nicht so richtig schlau aus deinen Sätzen.
      Was genau funktioniert denn jetzt nun nicht (nachdem du die Stackwerte angepasst hast)
    • Ralf schrieb:

      Bringt es was, das Auslesen des AD Wandlers in die Do Loop Schleife zu verschieben?


      Michael schrieb:

      Es ist bereits in der Do-Loop-Schleife und wird auf Anfrage ausgeführt. Das Gosub verzögert nur um 2 Takte aber verbessert die Programmierung
      Aber die Do Loop Schleife wird ja pausenlos durchlaufen und das Gosub nur alle paar Sekunden aufgerufen, wenn ein Messwert angefordert wird. Also wenn die serielle Schnittstelle "1" empfängt. Dann soll es richtig schnell gehen, Waitms 1 ersetze ich noch mit NOP, wie du es vorgeschlagen hast.


      Ralf schrieb:

      Im Simulator läuft es , im Gerät nicht so richtig.

      Michael schrieb:

      Ich werd nicht so richtig schlau aus deinen Sätzen.
      Was genau funktioniert denn jetzt nun nicht (nachdem du die Stackwerte angepasst hast)
      Das zweite Programm in dem Eingangsbeitrag sendet entweder 0 oder gar keine Daten. Hin und wieder auch mal einen exakten Messwert. Da stimmt eben das Timing nicht und das schaue ich mir noch mal an. Wenn ich die Waitbefehle angepasst habe klappt es vielleicht.

      Der Stand jetzt ist, das ich die allererste Version drauf habe und alles funktioniert. Warum ich die Überlaufgeschichte nicht unbedingt brauche, hatte ich ja geschrieben:

      Ralf schrieb:

      Ich habe die fehlerhafte Überlaufbehandlung jetzt rausgenommen, jetzt ist das Programm wieder im Urzustand wie vor knapp 20 Jahren.
      Da sind etliche ATMegas drin die über die RS232 Schnittstelle angesprochen werden. Auf Befehl aktivieren die jeweils die Schnittstelle und senden die Daten. Wenn irgendeiner nicht schnell genug reagiert, ist alles blockiert. Eine Fehlerbehandlung habe ich im Hauptcontroller nicht programmiert.
      Ich könnte da was machen, aber der ist uralt und nicht mehr lieferbar. (Basic Tiger von Wilke)
      Wenn was schiefgehen würde, kann ich das Gerät erst mal vergessen und ich brauche es für meine Arbeit.

      Ralf schrieb:

      Nach oben kann es zu maximal einem Überlauf kommen und auch das will ich vermeiden. Ich müßte das Meßseil 370cm ausziehen und da ist die Feder in der Aufwickelvorrichtung an der Grenze. Die übliche Länge liegt so bei maximal 250cm eventuell auch mal 300cm.
      Also alles Bestens, ich teste heute Abend oder Morgen die neue Version ohne Waitms, aber so oder so, das Problem ist gelöst.

      Vielen Dank für die zahlreichen Antworten! 8o