CMOS-Dezimal-Counter- bzw. -Teiler-Kaskade in Bascom umsetzen

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

    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!

    • An dem Code wird ja immer mehr rum-gefrickelt.
      Sieht für mich auch ziemlich planlos aus.

      Bei jedem Problem (z.B. Tasten sperren/freigeben usw., Heizung abschalten, wie) wird wieder was neues dazu gefrickelt.
      Und das geht schon die ganze Zeit so.

      Der arme @delatube ist bestimmt schon komplett verwirrt.

      @ceperiga hat es auch schon anfangs erwähnt, mal einen Plan zu machen, was da wie nacheinander passieren soll.
      Damit ihr nicht im Wald steht hab ich mal so ein Diagramm gezeichnet, wie das aussehen könnte.
      Das ist natürlich jetzt nur meine Interpretation aus den Forums-Beiträgen.
      E1T-Uhr-Ablaufplan.pdf

      Ich persönlich bin ein Freund davon, den Ablauf tabellarisch zu machen, weil es doch einfacher zum Editieren und Erweitern ist.
      Zudem kann man mehr Details reinbringen.

      Hier meine Ablauf-Tabelle.
      E1T-Uhr-State-Tabelle.pdf

      Wie das jetzt programmtechnisch aussehen könnte, könnte ich jetzt auch zeigen.
      Ich gehe aber davon aus, dass ihr noch weiter-frickeln wollt?
    • Mitch64 wrote:

      An dem Code wird ja immer mehr rum-gefrickelt.
      Sieht für mich auch ziemlich planlos aus.
      Da hast Du sicherlich recht und ja, den Code zu durchsteigen als Anfänger fällt zunehmend schwerer. Ich bin aber sehr sehr dankbar für die Hilfe und die Ideen, die ich vor allem von @Pluto25 bekommen habe und muss zur Verteidigung sagen, dass ich das "Rumgefrickel" ja selbst quasi verursacht habe, denn ich hatte mir eben keinen Ablaufplan gemacht und dann immer nochmals neue Ideen und Wünsche reingebracht, die dann irgendwie mit dem schon Vorhandenen zusammenspielen sollten. Dabei sind ja auch Überlegungen dazu gekommen, die ich oder das Forum nicht auf dem Schirm hatten.

      Mitch64 wrote:

      E1T-Uhr-Ablaufplan.pdf

      Mitch64 wrote:

      E1T-Uhr-State-Tabelle.pdf
      Das ist Klasse und wollte ich eigentlich auch irgendwie so ähnlich erstellen, bin dann aber vom Fortschritt beim Coden abgelenkt worden. Im Prinzip, wenn ich es richtig sehe und interpretieren, stimmt das überein mit dem, was wann wie passieren soll. Nur die Pause zwischen 'Anodenspannung An' und 'Zeit Sync Röhren' kann viel kürzer, d.h. unter 1s sein und jene zwischen 'Anodenspannung Aus' und 'Heizung Aus' kann entfallen, denn beide Spannungen können problemlos zeitgleich ausgeschaltet werden. (Im Diagramm fehlt bei den Tastern der Reset sehe ich gerad noch).

      Mitch64 wrote:

      Wie das jetzt programmtechnisch aussehen könnte, könnte ich jetzt auch zeigen.
      Ich gehe aber davon aus, dass ihr noch weiter-frickeln wollt?
      Besonders als Einsteiger möchte ich ja soviel wie möglich auch dabei lernen. Daher nehme ich Dein Angebot sehr gern an und bin gespannt auf Deine Lösung/Deinen Ansatz. Dankeschön!
    • Freut mich, dass dich mein Ansatz interessiert.

      Nun, mein Ansatz weicht von deinem schon deutlich ab.
      Denn ich überlege erst mal, bevor ich anfange, was das Programm tun soll.
      Die Tabelle hast du ja gesehen. In der Spalte links sind die Phasen, in der sich das Programm befinden kann.
      Die muss man sich überlegen und sinnhaft benennen.

      Im Fach-Chargon nennt man die Phasen aus Zustände bzw. States.
      In der Hauptschleide werden die Zustände mittels Select Case auseinander gehalten.
      So kann man ober eine Variable bestimmen, welcher Codeabschnitt (State) ausgeführt wird.

      Um Zustände zu wechseln bedarf es ein Auslöser. Das kann eine Taste sein, ein Timeout oder ein Signal.
      Und dann wird bestimmt, mit welchem zustand es weiter gehen soll.

      Die ganzen Routinen, die man dazu noch braucht, sind thematisch in sogenannte Module ausgelagert, die man einfach einbindet.

      Ich zeig dir mal die Hauptdatei (Main.bas).

      BASCOM Source Code: Main.bas

      1. ' Projekt: E1T-Uhr
      2. ' Module: Main.bas (Hauptmodul)
      3. ' Autor: Mitch64
      4. ' Erstellt: 11.2024
      5. ' Version: 0.1 (Prototyp)
      6. ' Uhr mit 6x E1T-Röhren
      7. ' Jede der 6 Röhren stellt ein Digit der Uhrzeit dar hh:mm:ss.
      8. ' ----------------------------------------------
      9. ' Controller-Einstellung
      10. ' ----------------------------------------------
      11. $regfile = "m8def.dat"
      12. '$crystal = 1000000 Original
      13. $Crystal = 3686400 ' Quarz
      14. $swstack = 64
      15. $hwstack = 64
      16. $framesize = 64
      17. ' ----------------------------------------------
      18. ' Compiler-Einstellung
      19. ' ----------------------------------------------
      20. Config SubMode = New
      21. Config Base = 0
      22. '$SIM
      23. ' ----------------------------------------------
      24. ' Module einbinden
      25. ' ----------------------------------------------
      26. $Include "Include\Config.inc"
      27. $Include "Include\Time.inc"
      28. $Include "Include\Tube.inc"
      29. $Include "Include\Taster.inc"
      30. $Include "Include\Timeout.inc"
      31. $Include "Include\FSM.inc"
      32. ' ----------------------------------------------
      33. ' Initialisierung der Hardware
      34. ' ----------------------------------------------
      35. Call Time_Init() ' int. Uhr Init
      36. Call Tube_Init() ' Röhren-Init
      37. Call Key_Init() ' Taster-Init
      38. Call SetState(ST_POWER_ON) ' Start-Zustand
      39. Enable Interrupts
      40. ' ----------------------------------------------
      41. ' Hauptschleife
      42. ' ----------------------------------------------
      43. Do
      44. ' Steuerung der Uhr
      45. Select Case GetState() ' aktueller Zustand?
      46. ' -------------------------
      47. Case ST_POWER_ON ' Start-Phase (Controller-Reset)
      48. ' -------------------------
      49. ' Zahlweise in Standby oder zum Uhrenstart
      50. Call SetState(ST_HEAT_ON) ' Uhr starten oder
      51. 'Call SetState(ST_STANDBY) ' alternativ in Standby gehen
      52. ' -------------------------
      53. Case ST_HEAT_ON ' Anheiz-Phase der Röhren
      54. ' -------------------------
      55. If StateChanged() = True then
      56. Call Tube_SwitchHeat(True) ' Heizung einschalten
      57. Call TO_SetTimeout(HEAT_ON_DELAY) ' Timeout Vorwärmdauer setzen
      58. End If
      59. If TO_Elapsed() = True then ' Vorwärmzeit abgelaufen?
      60. Call SetState(ST_ANODE_ON) ' nächster Zustand
      61. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      62. Call Time_Update() ' int. Uhr +1s
      63. End If
      64. ' -------------------------
      65. Case ST_ANODE_ON ' Anode Einschalt-Phase
      66. ' -------------------------
      67. If StateChanged() = True then
      68. Call Tube_SwitchAnode(True) ' Anoden-Spannung an
      69. Call TO_SetTimeout(ANODE_ON_DELAY) ' Timeout Delay setzen
      70. End If
      71. If TO_Elapsed() = True then ' Delay abgelaufen?
      72. Call SetState(ST_TIME_SYNC) ' nächster Zustand
      73. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      74. Call Time_Update() ' int. Uhr +1s
      75. End If
      76. ' -------------------------
      77. Case ST_TIME_SYNC ' interne Uhr updaten (ungezählte Time-Ticks)
      78. ' -------------------------
      79. If Time_IsUpToDate() = True then ' Alle Ticks in int. Uhr verrechnet?
      80. Call SetState(ST_UPGRADE_TUBE) ' nächster Zustand
      81. Else
      82. Call Time_Update() ' Zeit +1 Sekunde
      83. End If
      84. ' -------------------------
      85. Case ST_UPGRADE_TUBE ' Anzeige Upgraden auf beliebige Zeit von int. Uhr
      86. ' -------------------------
      87. Call Tube_Upgrade() ' Anzeige stellen
      88. Call SetState(ST_SHOW_TIME) ' nächster Zustand
      89. ' -------------------------
      90. Case ST_SHOW_TIME ' Normalbetrieb mit Zeitanzeige
      91. ' -------------------------
      92. If Key_Power() = True then ' Taste Power gedrückt?
      93. Call SetState(ST_ANODE_OFF) ' nächster Zustand
      94. ElseIf Key_Sec() = True then ' Taste Sec gedrückt?
      95. Call Tube_Update() ' Anzeige +1s
      96. Call Time_Update() ' int. Uhr +1s
      97. ElseIf Key_Min() = True then ' Taste Min gedrückt?
      98. Call Time_EditMin() ' Minuten +1
      99. Call SetState(ST_TIME_SYNC) ' Zeit neu synchronisieren
      100. ElseIf Key_Hour() = True then ' Taste Hour gedrückt?
      101. Call Time_EditHour() ' Stunden +1
      102. Call SetState(ST_TIME_SYNC) ' Zeit neu synchronisieren
      103. ElseIf Key_Reset() = True then ' Taste Reset gedrückt?
      104. ' Was soll Taster Reset bewirken?
      105. ' aktuell wird Uhr auf 00:00:00 gesetzt
      106. ' und Anzeige auf diese Zeit gestellt.
      107. Call Time_Reset() ' Uhr auf Null
      108. Call SetState(ST_UPGRADE_TUBE) ' Anzeige wie Uhr einstellen
      109. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      110. Call Tube_Update() ' Anzeige +1s
      111. Call Time_Update() ' int. Uhr +1s
      112. End If
      113. ' -------------------------
      114. Case ST_ANODE_OFF ' Anoden Abschalt-Phase
      115. ' -------------------------
      116. If StateChanged() = True then
      117. Call Tube_SwitchAnode(False) ' Anodenspannung abschalten
      118. Call TO_SetTimeout(ANODE_OFF_DELAY) ' Timeout Delay setzen
      119. End If
      120. If TO_Elapsed() = True then ' Delay abgelaufen?
      121. Call SetState(ST_HEAT_OFF) ' nächster Zustand
      122. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      123. Call Time_Update() ' int. Uhr +1s
      124. End If
      125. ' -------------------------
      126. Case ST_HEAT_OFF ' Heizung abschalten
      127. ' -------------------------
      128. If StateChanged() = True then
      129. Call Tube_SwitchHeat(False) ' Heizung aus
      130. Call TO_SetTimeout(HEAT_OFF_DELAY) ' Timeout Abhühldauer setzen
      131. End If
      132. If TO_Elapsed() = True then
      133. Call SetState(ST_STANDBY) ' nächster Zustand
      134. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      135. Call Time_Update() ' int. Uhr +1s
      136. End If
      137. ' -------------------------
      138. Case ST_STANDBY ' Standby-Betrieb
      139. ' -------------------------
      140. If StateChanged() = True then
      141. Call Tube_SwitchAnode(False)
      142. End If
      143. If Key_Power() = True then ' Taste Power gedrückt?
      144. Call SetState(ST_HEAT_ON) ' nächster Zustand
      145. ElseIf Time_IsUpToDate() = False then ' int. Uhr Nachstellen?
      146. Call Time_Update() ' int. Uhr +1s
      147. End If
      148. End Select
      149. Loop ' Ende Main-Loop
      Display All
    • Hier noch der Rest (Nachricht zu lang)

      Ab Zeile 32 siehst du die Module, die ich einbinde.
      Dort sind also die ganzen Routinen für den Betrieb untergebracht. Damit ist der Ballast aus dem Hauptprogramm weg und macht es übersichtlich nachzuvollziehen.

      Z.B. findest du im Modul 'Tasten.inc" die Abfragen der Tasten. Diese liefert true, wenn sie gedrückt werden. Diese Tastenabfragen machen auch nur das, Taste abfragen, sonst nichts. Dadurch kann man die tasten auch in anderen Zuständen mit anderen Funktionen belegen, one Code zu ändern.

      Im Modul "FSM.inc" sind die Hilfsroutinen, mit denen ich die Zustände umschalte und abfrage.

      Im Modul Config ist die Konfiguration abgelegt.
      Also Konstanten für z.B. Timeouts für Vorheizen, Abkühlen oder die Aliasnamen für die Pins.

      Die Hauptschleife geht ab Zeile 61 los.
      Dort ist der ganze Programmablauf kodiert.

      Die Zustände findest du in der Tabelle wieder und auch die Trigger (Tasten, etc.), die die Zustände umschalten.
      Das nennt sich Statemachine. Ich habe dazu ein Tutorial geschrieben. Du findest es im Lexikon.

      Durch das Aufteilen des Programmablaufs in Zustände, kannst du in jedem Zustand genau bestimmen, welche Tasten abgefragt werden sollen, wie darauf reagiert werden soll, oder was ein oder auszuschalten ist. Im Grunde ganz easy.

      Vergleiche mal die Tabelle mit der Main-Loop. Ich denke, dann wird klar was ich meine.

      Eine Besonderheit gibt es noch zu den Routinen der Statemachine.
      Wenn ein State mit 'SetState(neuerZustand)' gesetzt wird, wird auch ein Flag gesetzt, dass der Zustand geändert wurde.
      Die Abfrage StateChanged() fragt dieses Flag ab und löscht es sogleich. Heißt, nach einem Zustandswechsel
      wird die erste Abfrage StateChanged() True sein, weitere Abfragen sind Fals, solange der Zustand nicht wieder neu gesetzt wird.

      Das nutze ich in der Hauptschleife aus, um einmalige Aktionen bei einem Zustandswechsel auszuführen.
      Das ist ein nettes Feature, was oft nützlich ist.

      Das wäre also mein Ansatz.
      Wie gefällt er dir?
    • Entweder mit Call und immer mit Klammer, auch wenn keine Parameter übergeben werden,
      oder ohne Call und dann auch die Klammern weg lassen.

      Beides ist in Bascom zulässig lt. Hilfe.

      Nicht so schön ist, wenn man das in einem Projekt vermischt, also mal so dann anders.
      Man sollte sich für eine Variante entscheiden und diese dann konsequent einhalten.

      Ganz schlecht ist, wenn man Call verwendet und die Klammern weg lässt, weil man keine Parameter zu übergeben hat.
      Syntax-Technisch ist das falsch und könnte irgendwann mal mit Fehler quittiert werden, wenn der Compiler genauer drauf schaut.
    • Mitch64 wrote:

      Ich zeig dir mal die Hauptdatei (Main.bas).
      Wow und Danke. Auf jeden Fall ist der Code allein schon rein von der Optik her sehr sehr stringent und aufgeräumt. Für mich bietet es dadurch aber auf den ersten Blick zunächst noch weniger Ansatz zum Nachvollziehen was wie wann wo passiert. Das muss ich mir in Ruhe ansehen und sicherlich auch in das Tutorial reinschauen. Lust zum Durchsteigen habe ich schon.

      Die Deklaration oben ist sicherlich nicht vollständig oder wo kommen die Taster usw? Auch finde ich den Code für die einzelnen Module nicht? Ggf. verstehe ich hier aber auch etwas grundlegendes noch nicht?
    • delatube wrote:

      Für mich bietet es dadurch aber auf den ersten Blick zunächst noch weniger Ansatz zum Nachvollziehen was wie wann wo passiert.
      Ich kann der Frage nicht so recht folgen.
      Was genau kannst du nicht nachvollziehen?
      Was genau willst du jetzt sehen?

      Im Grunde liest sich das Hauptmodul (Hauptschleife) wie ein Buch (für mich zumindest).

      Wenn da steht Key_Power() oder Key_Hour(), dann wird da eine Taste abgefragt. Im ersten Fall die Taste zum an/aus Schalten, im 2. Fall die Stunden-Taste.

      SetState(..) setzt eunen neuen Zustand, GetState() fragt den ab.

      TO_Timeout() setzt einen Timeout und TO_Elapsed() liefert True, wenn abgelaufen.
      Im Grunde stehen die Kommentare daneben.

      Kannst du deine Frage konkretisieren?
    • Mitch64 wrote:

      Ich kann der Frage nicht so recht folgen.
      Dass Du darin wie in einem Buch liest merkt man, aber um im Bild zu bleiben, bin ich noch Leseanfänger. Dein Ansatz sieht ja schon von den Zeilen und Kommandos her zumindest für mich völlig anders aus nicht nur als der Code bislang sondern auch als das, was in den Einsteigerkursen gezeigt wird. Daher vermisste ich so Basics wie 'Debounce' oder "If Taster...then...' oder auch irgendwelche Deklarationen zu Timern, Variablen, welche Portpins für Taster, für Eingänge oder Zahlenwerte für Delays usw. Das verwirrt mich aktuell noch mehr als mir die Übersichtlichkeit hilft. Das ist sicherlich nur ein Verständnisproblem und auflösbar.
      Das Gerüst aus der Abfrage verschiedener Zustände der Funktion der Uhr kann ich aber, denke ich, nachvollziehen. Dein Tutorial habe ich noch nicht gelesen, mach ich aber alsbald.

      Noch eins: Hab mir den Code auch im Bascom Editor angesehen. Dort sagt er mir, dass er die Files in Zeile 34 und 35 nicht finden kann(?).
    • delatube wrote:

      Daher vermisste ich so Basics wie 'Debounce' oder "If Taster...then...'
      Die Taster-Abfrage ist in dem Modul Taster.inc untergebracht. Dort ist auch das Debounce in den Routinen verbaut.
      Im Hauptprogramm ruft man also nur das Ergebnis der Entsprechenden Tasten-Abfrage ab.

      BASCOM Source Code: Modul Taster.inc

      1. ' Modul: Taster.inc
      2. ' Autor: Mitch64
      3. ' Erstellt: 11.2024
      4. ' Beschreibung
      5. ' Routinen zur Taster-Abfrage / Initialisierung
      6. ' Prefix 'Key_'
      7. ' ----------------------------------------------
      8. ' Taster initialisieren
      9. ' (PullUps an)
      10. ' ----------------------------------------------
      11. Sub Key_Init()
      12. Set pinKeySecPU ' PullUp an
      13. Set pinKeyMinPU ' PullUp an
      14. Set pinKeyHourPU ' PullUp an
      15. Set pinKeyResetPU ' PullUp an
      16. Set pinKeyPowerPU ' PullUp an
      17. End Sub
      18. ' ----------------------------------------------
      19. ' Abfrage Sekunden-Taster
      20. ' Liefert True, wenn Taster gedrückt wird
      21. ' ----------------------------------------------
      22. Function Key_Sec() as Byte
      23. Debounce pinKeySec , 0 , _Key_Sec
      24. Key_Sec = False
      25. Exit Function
      26. _Key_Sec:
      27. Key_Sec = True
      28. End Function
      29. ' ----------------------------------------------
      30. ' Abfrage Minuten-Taster
      31. ' Liefert True, wenn Taster gedrückt wird
      32. ' ----------------------------------------------
      33. Function Key_Min() as Byte
      34. Debounce pinKeyMin , 0 , _Key_Min
      35. Key_Min = False
      36. Exit Function
      37. _Key_Min:
      38. Key_Min = True
      39. End Function
      40. ' ----------------------------------------------
      41. ' Abfrage Stunden-Taster
      42. ' Liefert True, wenn Taster gedrückt wird
      43. ' ----------------------------------------------
      44. Function Key_Hour() as Byte
      45. Debounce pinKeyHour , 0 , _Key_Hour
      46. Key_Hour = False
      47. Exit Function
      48. _Key_Hour:
      49. Key_Hour = True
      50. End Function
      51. ' ----------------------------------------------
      52. ' Abfrage Stunden-Taster
      53. ' Liefert True, wenn Taster gedrückt wird
      54. ' ----------------------------------------------
      55. Function Key_Reset() as Byte
      56. Debounce pinKeyReset , 0 , _Key_Reset
      57. Key_Reset = False
      58. Exit Function
      59. _Key_Reset:
      60. Key_Reset = True
      61. End Function
      62. ' ----------------------------------------------
      63. ' Abfrage Power-Taster (Gerät An/Aus)
      64. ' Liefert True, wenn Taster gedrückt wird
      65. ' ----------------------------------------------
      66. Function Key_Power() as Byte
      67. Debounce pinKeyPower , 0 , _Key_Power
      68. Key_Power = False
      69. Exit Function
      70. _Key_Power:
      71. Key_Power = True
      72. End Function
      Display All
    • delatube wrote:

      oder auch irgendwelche Deklarationen zu Timern, Variablen, welche Portpins für Taster, für Eingänge oder Zahlenwerte für Delays usw.
      Wie gesagt, das ist in den Modulen untergebracht.

      Oft sind Variablen für einen bestimmten Zweck angelegt.
      Das sind z.B. die Variablen für Sekunden, Minuten und Stunden. Sowas lege ich im Modul mit ab. In dem Fall das Modul Time.inc.
      Dort ist auch die ISR für die Zeitbasus zu finden und die Timer-Deklaration.

      BASCOM Source Code: Modul Time.inc

      1. ' Modul: Time.inc
      2. ' Autor: Mitch64
      3. ' Erstellt: 11.2024
      4. ' Beschreibung
      5. ' Routinen zur Steuerung der internen Uhr,
      6. ' 1 Hz Zeitbasis (Timer1)
      7. ' sie läuft auch im Standby-Mode weiter.
      8. ' Prefix 'Time_'
      9. Dim _Time_Sec , _Time_Min , _Time_Hour as Byte ' Valiablen halten interne Zeit
      10. Dim _Time_Ticks as Byte
      11. ' ----------------------------------------------
      12. ' Initialisierung Zeitmodul
      13. ' ----------------------------------------------
      14. Sub Time_Init()
      15. Call Time_Reset() ' int. Uhr auf 00:00:00
      16. ' Timer1 erzeugt 1Hz Zeitbasis
      17. Config Timer1 = Timer , Prescale = 1024 , CLEAR_TIMER = True
      18. Compare1A = 3600 - 1 ' ergibt 1Hz Takt
      19. On Compare1A Time_ISRTick
      20. Enable Compare1A
      21. End Sub
      22. ' ----------------------------------------------
      23. ' OC1A-ISR-Routine
      24. ' Zeitbasis 1 Hz
      25. ' ----------------------------------------------
      26. Sub Time_ISRTick()
      27. Incr _Time_Ticks ' 1Hz Pulse zählen
      28. Call TO_Tick()
      29. End Sub
      30. ' ----------------------------------------------
      31. ' Inkrementiert die interne Zeit um 1 Sekunden
      32. ' Kein Übertrag auf Minuten
      33. ' ----------------------------------------------
      34. Sub Time_EditSec()
      35. Incr _Time_Sec
      36. If _Time_Sec >= 60 then _Time_Sec = 0
      37. End Sub
      38. ' ----------------------------------------------
      39. ' Inkrementiert die interne Zeit um 1 Minuten
      40. ' Kein Übertrag auf Stunden
      41. ' ----------------------------------------------
      42. Sub Time_EditMin()
      43. Incr _Time_Min
      44. If _Time_Min >= 60 then _Time_Min = 0
      45. End Sub
      46. ' ----------------------------------------------
      47. ' Inkrementiert die interne Zeit um 1 Stunden
      48. ' ----------------------------------------------
      49. Sub Time_EditHour()
      50. Incr _Time_Hour
      51. If _Time_Hour >= 60 then _Time_Hour = 0
      52. End Sub
      53. ' ----------------------------------------------
      54. ' Liefert 10er-Stelle der Sekunden
      55. ' ----------------------------------------------
      56. Function Time_GetSec10() as Byte
      57. Time_GetSec10 = _Time_Sec \ 10
      58. End Function
      59. ' ----------------------------------------------
      60. ' Liefert 1er-Stelle der Sekunden
      61. ' ----------------------------------------------
      62. Function Time_GetSec01() as Byte
      63. Time_GetSec01 = _Time_Sec Mod 10
      64. End Function
      65. ' ----------------------------------------------
      66. ' Liefert 10er-Stelle der Minuten
      67. ' ----------------------------------------------
      68. Function Time_GetMin10() as Byte
      69. Time_GetMin10 = _Time_Min \ 10
      70. End Function
      71. ' ----------------------------------------------
      72. ' Liefert 1er-Stelle der Minuten
      73. ' ----------------------------------------------
      74. Function Time_GetMin01() as Byte
      75. Time_GetMin01 = _Time_Min Mod 10
      76. End Function
      77. ' ----------------------------------------------
      78. ' Liefert 10er-Stelle der Stunden
      79. ' ----------------------------------------------
      80. Function Time_GetHour10() as Byte
      81. Time_GetHour10 = _Time_Hour \ 10
      82. End Function
      83. ' ----------------------------------------------
      84. ' Liefert 1er-Stelle der Stunden
      85. ' ----------------------------------------------
      86. Function Time_GetHour01() as Byte
      87. Time_GetHour01 = _Time_Hour Mod 10
      88. End Function
      89. ' ----------------------------------------------
      90. ' Liefert True, wenn alle Time-Ticks
      91. ' in der Uhrzeit verarbeitet wurden.
      92. ' ----------------------------------------------
      93. Function Time_IsUpToDate() as Byte
      94. If _Time_Ticks > 0 then
      95. Time_IsUpToDate = False
      96. Else
      97. Time_IsUpToDate = True
      98. End If
      99. End Function
      100. ' ----------------------------------------------
      101. ' Interne Uhrzeit um 1 Sek. weiter takten
      102. ' ----------------------------------------------
      103. Sub Time_Update()
      104. If _Time_Ticks > 0 then
      105. Decr _Time_Ticks
      106. Incr _Time_Sec ' int. Uhr nachstellen
      107. If _Time_Sec >= 60 then
      108. _Time_Sec = 0
      109. Incr _Time_Min
      110. If _Time_Min >= 60 then
      111. _Time_Min = 0
      112. Incr _Time_Hour
      113. If _Time_Hour >= 24 then
      114. _Time_Hour = 0
      115. End If
      116. End If
      117. End If
      118. End If
      119. End Sub
      120. ' ----------------------------------------------
      121. ' Setzt die Uhr auf 00:00:00 zurück.
      122. ' ----------------------------------------------
      123. Sub Time_Reset()
      124. _Time_Hour = 0
      125. _Time_Min = 0
      126. _Time_Sec = 0
      127. End Sub
      Display All
      Im Grunde ist alles ausgelagert in Subs oder Funktionen, die thematisch zusammen gehören in ein Modul.
      Damit wird die Hauptdatei nicht so überladen mit Code.

      Schließlich muss man ja nicht ständig den Code von einer Routine sehen. Es reicht zu wissen, dass es sie gibt und welche Parameter sie braucht und evtl. was sie zurück gibt. So ist es ja z.B. bei den Tasten.

      In der Hauptschleife werden dann nur die Routinen in den Modulen aufgerufen und das Ergebnis verarbeitet.

      Hast du mal in das Tutorial reingeschaut?
      Dort ist das Prinzip erklärt.

      Mir ist klar, dass du Anfänger bist und hier vielleicht nicht gleich durchsteigst.
      Das verlangt auch keiner.

      Ich bin lediglich deiner Bitte nachgekommen, meinen Ansatz aufzuzeigen. Und das habe ich ja versucht.
      Wenn du konkret fragst, kann ich auch konkret antworten.

      Mit der Auskunft Anfänger zu sein gibt es ziemlich viel Spielraum für Spekulation. Man kann gar nichts können oder man kennt Bascom, aber weis es nicht anzuwenden. Es gibt mehrere Formen, wie man Anfänger definiert. Kurzum, ich weiß nicht, was du weist, auf was ich aufbauen kann, und was du nicht weist.

      Ich stehe da auch im Wald.

      Deswegen gibts ja ein Forum.

      Was der Befehl $Include macht, und was eine INC-Datei ist, weist du aber, oder?
      Select Case kennste auch und weist wie es anzuwenden ist?

      Wo hakt es?
    • Ahh, okay. Damit wirds klarer. Vielen Dank für die Erläuterungen. Die Module müssen also noch erstellt bzw. sind bereits vorhanden aber in der Main natürlich nicht sichbar, müssen aber im "finalen Code" eingefügt werden und Teil dessen sein. Daher auch das "nicht finden" der Files im Bascomcodeeditor der Module, denke ich.

      Als Anfänger bezeichne ich mich, da ich noch nie irgendwas programmiert habe und Bascom gerade kennenlerne.

      Mitch64 wrote:

      Was der Befehl $Include macht, und was eine INC-Datei ist, weist du aber, oder?
      Select Case kennste auch und weist wie es anzuwenden ist?
      Ersteres beides nein. Select Case habe ich schonmal gehört/gesehen.

      Mitch64 wrote:

      lseIf Key_Reset() = True then ' Taste Reset gedrückt?
      ' Was soll Taster Reset bewirken?
      ' aktuell wird Uhr auf 00:00:00 gesetzt
      ' und Anzeige auf diese Zeit gestellt.
      Call Time_Reset() ' Uhr auf Null
      Call SetState(ST_UPGRADE_TUBE) ' Anzeige wie Uhr einstellen
      Den Resettaster hatte ich ursprünglich geplant, um die Anzeigen und die Zählerkette auf 0 zu setzen und dann von da aus neu einzustellen über die anderen Taster. Durch das automatische Setzen der Uhrzeit nach dem Aufheizen würde dies allerdings wohl überflüssig und dieser Taster eingespart werden können.

      Das Tutorial habe ich noch nicht gelesen, werde ich aber alsbald nachholen.

      P.S.: Der finale Code hat dann ne ganze Menge Zeilen, krass.

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

    • Na ja mit Übersichtlich hat das nun gar nichts mehr zu tun. Eine aufgeblähte Main in der man vor lauter 100buchstabenvariablen/Aliase/Subs kaum noch durchblickt. Dazu sehr viele unnötige Sprünge in noch unnötigere incs, so das man drei Monitore braucht um das zu erkennen was in Deinem ersten Code auf einer Seite sofort zu sehen war. a_67_e210de67 Nun ist ja genug Zeit und Flash da, da kann man auch aasen. :D

      Ps weiß jemand was das weiße Kästchen da macht? bzw wie das gelöscht werden kann?
    • Pluto25 wrote:

      unnötigere incs, so das man drei Monitore braucht um das zu erkennen was in Deinem ersten Code auf einer Seite sofort zu sehen war.
      Das sind keine unnötigen Incs. Alle Routinen darin werden von dem Programm benötigt.
      Aber alles in die Main zu packen macht es nur unübersichtlicher.

      Zudem benennt man Routinen so, dass man daraus die Funktion erahnen kann. Wenn eine Routine geschrieben ist und funktioniert, braucht man nicht mehr reinschauen. Im Grunde ist es dann egal wie sie ihre Arbeit macht. Wie bei Libs.

      Oder hast du den Code von der mcs.lib auch parallel auf wenn du Routinen daraus verwendest? - Sicher nicht, vielleicht in Ausnahmen.
      Und genau so kann man die Module auch sehen. Wie eine Lib, die eben noch als Quellcode vorliegt.
      Sie hat notwendige Routinen, die eben gerade wichtig sind.

      Zudem können Module, je nachdem wie man sie auslegt, auch in anderen Projekten verwendet werden.
      Nach Deiner vorherrschenden Methode, frickelst du jedes mal aufs neue.

      Ich denke ich muss mich nicht rechtfertigen. Meine Projekte funktionieren nach der Methode sehr gut. Man hat volle Kontrolle über das Programm und sein Verhalten und muss nicht mit irgendwelchen Effekten rechnen, weil man zu einem ungünstige Zeitpunkt eine Taste gedrückt hat. Im Vergleich zu der Methode, wie du sie anwendest, habe ich heute viel weniger Probleme. Zugegeben, es ist etwas langsamer, was dich vermutlich furchtbar stört, aber hier ist alles unkritisch.

      Aber es muss jeder selber wissen und die Erfahrung machen. Ich habe meine gemacht. Daraus sind auch diese Methoden entstanden.
      Im übrigen ist Statemachine, falls dich das auch stört, Pflichtfach bei Informatik-Studenten. Und das nicht ohne Grund!
      Auch das modulare Programmieren und das erstellen von Zweck-bezogenen Routinen/Algorithmen, die jede ihre Aufgabe in dem Projekt hat, gehört dazu.

      Muss jeder selber wissen. Ich frickel jedenfalls nicht gerne. Mir ist wichtig, dass der Code sauber läuft und nicht zickt. Und das erreicht man mit dieser Methode.
    • delatube wrote:

      Als Anfänger bezeichne ich mich, da ich noch nie irgendwas programmiert habe und Bascom gerade kennenlerne.
      Das erklärt so einiges.
      Ich bin davon ausgegangen, dass du die meisten Bascom-Anweisungen kennst.
      Das ist zum effektiven Programmieren natürlich essenziell.

      An dieser Stelle macht es vermutlich wenig Sinn für dich das Tutorial anzusehen. Kannst aber trotzdem rein schauen.

      Ich empfehle dir mal die Befehle, die es in Bascom gibt anzuschauen. (Bascom-Hilfe)
      Dabei meine ich die Sprachbestandteile von Basic selbst und nicht unbedingt UART I2C und ähnliche Features.

      Sondern was macht/wie funktioniert $Include <Datei> oder die Anweisung Select Case ...
      Das sind Sprachbestandteile die man immer wieder braucht.

      Genauso wie For Next, While Wend , Do Loop usw.
      Aber auch Berechnungen (Grundrechenarten), Vergleiche und binäre Verknüpfungen (Und Oder Not Xor).

      Wenn man ein Problem (Projekt) in Code formulieren soll. Ist es ganz schlecht, die Sprachbestandteile nicht zu kennen.
      Das wird das kaum was (gescheites) werden.

      Später kommen dann bei Bedarf andere Features dazu wie Timer und Interfaces vom Controller.

      Wenn du in deinem Projekt ein RTC-Modul anbauen willst, musst du wissen, welche Schnittstelle dafür benötigt wird. Meist I2C, aber es könnte auch SPI-Interface oder Uart denkbar sein. Ich will jetzt nix verkomplizieren, aber sowas muss sitzen, oder man muss wissen, wo es steht und es dann verstehen.

      Gerade für Anfänger / Einsteiger in Bascom gibt es einige Bücher. Die Hilfe finde ich da nicht so die 1. Wahl. Eher als Referenz.
      Ich hatte mir damals das Buch "Programmieren der AVR Risc Mikrocontroller" von Claus Kühnel gegönnt. Es gibt aber auch andere.

      Um meinen Ansatz zu verstehen musst du auch wissen, wie man Funktionen Schreibt, die einen Rückgabewert liefern und wie das mit Sub-Routinen geht.
      Denn ich verwende diese Technik fast ausschließlich. Labels sind bei mir nur in Ausnahmen zu finden.

      Eine Ausnahme findest du z.B. in den Key_Routinen, weil ich da Debounce verwende und das verlangt ein Label.

      Als ich damals mit Bascom angefangen habe, habe ich mir nicht gleich ein Projekt vorgeknöpft. Das wäre kläglich gescheitert.
      Vielmehr habe ich als erstes mal eine LED an einem Pin blinken lassen. Dann mit Taster kombiniert, um die LED zu schalten.
      Und so kam eins zum anderen. Ich habe also erst mal gelernt mit den Befehlen und auch mit der IDE umzugehen.
      Erst dann als ich mir mehr zugetraut habe, ging ich an kleine Projekte, die sich steigerten.
      Darunter war so als Highlight auch ein Ambilight für TV, welches das Bild analysiert und in Echtzeit die Farbe hinter dem Fernseher per LED an die Wand strahlt.
      Als 2. Highlight brauchte ich dazu ein Bildgenerator, der mir ein dauerhaftes Testbild lieferte, um die Justierung des Ambilight durchzuführen. Der Testgenerator schafft heute so an die 20 Testbilder, zuschaltbaren 1kHz Ton (sinusähnlich), Umschaltung BAS und RGB über Scart und auch eine 16:9 Umschaltung. Alles mit einem einigen Controller 16MHz getakteten. Inkl. Display und Menüsteuerung.

      Das Ambilight bestand aus 5 Controller, die per I2C-Bus verbunden waren.

      Aber was red ich da rum.
      Aller Anfang ist bekanntlich schwer.
    • Hallo,
      kurz vorm Jahreswechsel wollte ich mich nochmals mit einem Zwischenstand melden. Ich bin immer noch dabei - und mangels durchgehender Zeit und Ruhe dauert es lang - sowohl am Code (mit Hilfe von Pluto25) als auch an der Schaltung zu stricken, denn es gibt nach wie vo Baustellen und Verbesserungswünsche. Es hat sich dabei auch herausgestellt, dass einzelne meiner Röhrenexemplare nicht mehr bzw. nicht gleich zuverlässig funktionieren und sich leider auch mal "verzählen", d.h. einzelne Ziffern hängen oder ausgelassen werden. Da muss ich nochmals die besten raussuchen und testen.
      Am Code gibts noch zu tun bei den Themen "Stellen" und "Stromspar-/Röhrenschonungs-Modus (Ab/Anschalten der Röhren)". Der Basiscode ist noch der hier vor einigen Posts vorgestellte mit Ergänzungen.

      Es ist aktuell zwar noch mehr offen und unklar als ich gedacht hätte und mir lieb ist, aber ich bleibe dran und berichte, spätestens mit der Vorstellung der hoffentlich dereinst fertigen Uhr.

      Jetzt aber allen erstmal einen guten Rutsch ins neue Jahr und VG!