Minuten, Stunden, Tage

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

    • Minuten, Stunden, Tage

      Hi,

      knabber an einer Routine Minuten, Stunden und Tage mit einem Timer zu berechnen. Muss nicht sekundengenau sein. Brauche die Zeiten für diverse Aktionen. Hab das jetzt aus dem Kopf hin gemalt weiß aber nicht ob das so richtig ist. 10 Tage zu warten ob es passt möchte ich aber auch wieder nicht. Deswegen meine Bitte:

      Überfliegt den Code mal kurz und schlagt ihn mir um die Ohren falls ich irgendwo geistigen Durchfall produziert hab.

      Source Code

      1. 'Timer
      2. Anzeigen: 'Betriebsanzeige
      3. Timer1 = 34286 '49111 Timer auf 1 sekunde
      4. Incr Sekunden
      5. If Sekunden >= 60 Then
      6. Sekunden = 0
      7. Incr Minuten
      8. If Minuten >= 60 Then
      9. Minuten = 0
      10. Incr Stunden
      11. If Stunden >= 24 Then
      12. Stunden = 0
      13. Incr Tage
      14. If Tage >= 10 Then Tage = 0
      15. End If
      16. End If
      17. End If
      18. If Sekunden = 0 And Minuten = 0 And Stunden = 0 And Tage = 0 Then 'alle 10 Tage
      19. Wait 1
      20. End If
      21. If Sekunden = 0 And Minuten = 0 And Stunden = 12 Then 'täglich um 12 Uhr
      22. Wait 1
      23. End If
      24. If Sekunden = 0 And Minuten = 0 Then 'stündlich
      25. Wait 1
      26. End If
      27. Return
      Display All
      Danke.
    • Pac-Man wrote:

      Überfliegt den Code mal kurz und schlagt ihn mir um die Ohren
      Das ist leider nur ein Bruchteil des Codes.
      Ohne Taktfrequenz nützt das Timer-Setzen nichts, ohne Stackwerte spielt das Programm verrückt.
      Wartezeiten im Timer sind ganz schlecht, außerdem ruinierst du dir den Sekundenzähler damit.
      Die dritte Abfrage ist Teil der ersten, die Wartezeiten addieren sich, wenn beide erfüllt sind.
      Ansonsten ist der Uhrcode für einfache Sachen in Ordnung.

      Wenn du sonst keine Uhr hast, sondern nur die 10 Tage Zeit brauchst, kannst du im Timer auch eine Longvariable hochzählen lassen und bei 864000 sind die 10 Tage um ;)
    • djmsc wrote:

      Warum nimmst du nicht
      OK, kenne ich nicht. Wühle mich mal rein.


      Michael wrote:

      Das ist leider nur ein Bruchteil des Codes.
      Ohne Taktfrequenz nützt das Timer-Setzen nichts, ohne Stackwerte spielt das Programm verrückt.
      Sorry, Tackt 8MHZ. Sekunden stimmen anhand einer blinkenden LED. Muss nicht auf die Sekunde genau sein. Brauche nur (alle 10 Tage), (täglich 12 Uhr), und (jede Stunde).


      Michael wrote:

      Die dritte Abfrage ist Teil der ersten, die Wartezeiten addieren sich, wenn beide erfüllt sind.
      Ja, fällt mir jetzt auf. Ist doch aber eigentlich nicht schlimm weil ja (stündlich) bei (alle 10 Tage) auch vor kommt.


      Michael wrote:

      Wartezeiten im Timer sind ganz schlecht, außerdem ruinierst du dir den Sekundenzähler damit.
      Stimmt, hab ich nicht beachtet. Ich brauche aber diese Wartezeit sonst läuft die Schleife eine Sekunde lang. So wäre es wohl besser...


      Source Code

      1. 'Timer
      2. Anzeigen: 'Betriebsanzeige
      3. Timer1 = 34286 '49111 Timer auf 1 sekunde
      4. Incr Sekunden
      5. If Sekunden >= 60 Then
      6. Sekunden = 0
      7. Incr Minuten
      8. If Minuten >= 60 Then
      9. Minuten = 0
      10. Incr Stunden
      11. If Stunden >= 24 Then
      12. Stunden = 0
      13. Incr Tage
      14. If Tage >= 10 Then Tage = 0
      15. End If
      16. End If
      17. End If
      18. If Sekunden = 0 And Minuten = 0 And Stunden = 12 And Tage = 0 Then Gosub 10_tage 'alle 10 Tage
      19. Gosub Betriebszustandsanzeige
      20. Return
      21. Sub 10_tage
      22. Wait 1
      23. End Sub
      Display All
    • Pac-Man wrote:

      So wäre es wohl besser...
      Leider nicht, mit dem Sprung in die Sub bleibt der Code immernoch im Timer.
      Nebenbei, ein Sprung in eine Sub geht mit Call und wird mit End Sub abgeschlossen.
      Der Sprung mit Gosub zu einem Label wird hingegen mit Return abgeschlossen.

      Versuch, den Interrupt so kurz wie möglich zu halten, der Rest geht im Hauptprogramm:
      Hier ein Beispiel, als nächstes gehst du du die Vermeidung von Wait an ;)

      BASCOM Source Code

      1. Do
      2. If Sekunden >= 60 Then
      3. Sekunden = 0
      4. Incr Minuten
      5. If Minuten >= 60 Then
      6. Minuten = 0
      7. Incr Stunden
      8. If Stunden >= 24 Then
      9. Stunden = 0
      10. Incr Tage
      11. If Tage >= 10 Then Tage = 0
      12. End If
      13. End If
      14. End If
      15. If Sekunden = 0 And Minuten = 0 And Stunden = 12 And Tage = 0 Then Call 10_tage 'alle 10 Tage
      16. Gosub Betriebszustandsanzeige
      17. Loop
      18. Timerinterrupt:
      19. Timer1 = 34286
      20. Incr Sekunden
      21. Return
      22. Sub 10_tage
      23. Wait 1
      24. End Sub
      Display All
    • Michael wrote:

      Der Sprung mit Gosub zu einem Label wird hingegen mit Return abgeschlossen.
      Ja, sorry. Ich hab das so direkt eingetippt aber richtig gemacht.


      Michael wrote:

      Versuch, den Interrupt so kurz wie möglich zu halten, der Rest geht im Hauptprogramm:
      Das Problem ist dass meine Hauptschleife jede Menge warten muss. Deswegen im Interrupt.

      Michael wrote:

      Leider nicht, mit dem Sprung in die Sub bleibt der Code immernoch im Timer.
      Das verstehe ich nicht. Ich kann doch einen Interrupt nicht durch eine Schleife oder wait in einer sub ausbremsen. Ich denke dass der immer feuert wenn die Bedingungen eintreffen.
    • Ich stelle sie mal rein aber ich hab da noch einen anderen Thread in den ich das Ganze rein stellen möchte. Da passt es eher hin.

      Source Code

      1. Do
      2. Debounce Handlebar_1 , 1 , Taster_1 , Sub
      3. Debounce Handlebar_2 , 1 , Taster_2 , Sub
      4. If Flag_gefunden = 1 Then
      5. 'Print#2 , ">" ; Left(empfangene_daten , 6)
      6. Select Case Left(empfangene_daten , 6)
      7. Case "+CMGR:"
      8. '+CMGR: "REC UNREAD","+491727430283","","20/10/30,02:23:32+04" (CRLF) Testnachricht (CRLF)(CRLF) OK (CRLF)
      9. '+CMGR: "REC UNREAD","80808","","20/10/30,12:01:01+04" (CRLF) Dein Guthaben beträgt 2,44 Euro. Lad es bitte wieder in Deiner App oder unter 22922 auf. Freundl
      10. '+CMGR: "REC UNREAD","+491722270333","","20/10/31,08:38:04+04" (CRLF) Nachricht für +49172xxxxxxx vom 31.10.20 08:38:04 ist am 31.10.20 um 08:38:05 ausgeliefert worden. (CRLF)(CRLF) OK (CRLF)
      11. '+CMGR: "REC READ","224466","CallYa-Angebot","20/11/06,20:06:30+04" (CRLF) ig. Weiteren Nachrichten kannst Du jederzeit widersprechen. Freundliche Grüße, Dein Vodafone-Team (CRLF)(CRLF) OK (CRLF)
      12. '+CMGR: "REC READ","224466","CallYa-Angebot","20/11/06,20:06:29+04" (CRLF) com/de?s=BU2 und bezahle sicher mit Deinem Prepaid-Guthaben. Die Abos sind jederzeit kündbar. Hinweis: mobiles Anklicken des Links ist ggf. kostenpflicht
      13. '+CMGR: "REC UNREAD","80808","","20/11/13,12:18:16+04" (CRLF) Dein Guthaben ist schon unter 1 Euro und Du kannst gerade nicht aufladen? Dann aktivier jetzt den CallNow Vorschuss. Und surf, sims und telefonier für zu
      14. '+CMGR: "REC UNREAD","80808","","20/11/13,12:18:18+04" (CRLF) sätzlich 3,00 Euro. Für diesen Service zahlst Du nur 0,49 Euro. Lädst Du das nächste Mal auf, gleichst Du den Vorschuss wieder aus. Bis dahin nutzt Du e
      15. '+CMGR: "REC UNREAD","70257","","20/11/13,13:17:51+04" (CRLF) Du bekommst vom Teilnehmer mit der Rufnummer 0172xxxxxxx einen CallNow-Transfer von 5.00 Euro. Freundliche Grüße, Dein Vodafone-Team
      16. Sms_komplett = "" : Sekunden = 0
      17. Do
      18. If Flag_gefunden = 1 Then
      19. Flag_gefunden = 0
      20. If Left(empfangene_daten , 2) = "OK" Then Exit Do 'Nachricht mit OK abgeschlossen
      21. Sms_komplett = Sms_komplett + Empfangene_daten
      22. If Sekunden > 2 Then
      23. Flag_gefunden = 0
      24. Flag_fehler_aufgetreten = 1
      25. Print#2 , "Fehler"
      26. Call Sms_auswerten(empfangene_daten )
      27. Empfangene_daten = ""
      28. Exit Do
      29. End If
      30. End If
      31. Loop
      32. Call Sms_auswerten(sms_komplett )
      33. Empfangene_daten = "" : Sms_komplett = ""
      34. Print "AT+CMGD=" ; Val(dummy_sms_nummer) ; Chr(13 ) ; 'sms gleich löschen
      35. Call Auf_string_warten( "OK" , 2 , 10 , "keine antwort auf löschen")
      36. If Flag_fehler_aufgetreten = 1 Then Print "Fehler"
      37. If Val(dummy_sms_nummer) > 10 Then Sms_loeschen
      38. Case "+CUSD:"
      39. '+CUSD: 1, "Aktuelles Guthaben: 13,32 EUR (LF) Wähl bitte aus: (LF) 1 Aufladen (LF) 2 Guthaben & Verbrauch (LF) 3 Tarife & Optionen (LF) 4 Spracheinstellungen (LF) 5 Vorteilsangebot", 0 (CRLF)
      40. '+CUSD: 0, "Kontostand: 0,14 EUR (LF) Bonus Guthaben: 0,00 EUR", 0
      41. '+CUSD: 0, "Zu viele Eingabefehler. (LF) Bitte versuch es erneut oder probier es unter 22922.", 0
      42. '+CUSD: 0, "Zurzeit steht das System aus technischen Gründen leider nicht zur Verfügung. Vielen Dank für Dein Verständnis.", 0
      43. If Left(empfangene_daten , 8) = "+CUSD: 2" Then
      44. Print#2 , "CUSD Session canceled."
      45. 'End If
      46. Else
      47. 'If Left(empfangene_daten , 6) = "+CUSD:" Then
      48. Flag_gefunden = 0
      49. Pos_1 = Charpos(empfangene_daten , ":" , 6) : Pos_1 = Pos_1 + 2 ':
      50. Pos_2 = Charpos(empfangene_daten , 10 , Pos_1 )
      51. I = Pos_2 - Pos_1
      52. Sms_komplett = Mid(empfangene_daten , Pos_1 , I)
      53. 'Print#2 , "Guthaben: " ; Sms_komplett
      54. Sms_komplett = "Guthaben: " + Sms_komplett
      55. Call Sms_versenden(sms_komplett , Alarm_nummer_1 )
      56. Empfangene_daten = "" : Sms_komplett = ""
      57. 'Print#2 , Empfangene_daten
      58. End If
      59. Case "+CMTI:" 'SMS angekommen
      60. Pos_1 = Charpos(empfangene_daten , "," )
      61. Pos_2 = Len(empfangene_daten)
      62. Incr Pos_1
      63. Dummy_sms_nummer = Mid(empfangene_daten , Pos_1 , Pos_2) 'Speichernummer der empfangenen SMS
      64. 'Print#2 , Val(dummy_val)
      65. Print "AT+CMGR=" ; Val(dummy_sms_nummer) ; Chr(13 ) ; 'sms abrufen
      66. Empfangene_daten = "" : Sms_komplett = ""
      67. Case "+CSQ: " 'sendestärke angekommen
      68. Pos_1 = Charpos(empfangene_daten , ":" )
      69. Pos_2 = Charpos(empfangene_daten , "," )
      70. Incr Pos_1
      71. I = Pos_2 - Pos_1
      72. Empfangs_staerke = Mid(empfangene_daten , Pos_1 , I)
      73. 'Print#2 , "Empf" ; Empfangs_staerke
      74. Empfangene_daten = "" : Sms_komplett = ""
      75. 'Flag_gefunden = 0
      76. Case "+CCLK:"
      77. '+CCLK: "20/11/15,09:03:37+04"
      78. Pos_1 = Charpos(empfangene_daten , 34) : Incr Pos_1 'Datum/zeit
      79. Date_time = Mid(empfangene_daten , Pos_1 , 17)
      80. Empfangene_daten = "" : Sms_komplett = ""
      81. Case Else
      82. 'Print#2 , "*" ; Left(empfangene_daten , 3) ; "*"
      83. 'Flag_gefunden = 0
      84. End Select
      85. Flag_gefunden = 0
      86. '(
      87. Ww = _hwstackstart - _hw_lowest
      88. Www = _hwstack_low - _sw_lowest
      89. Wwww = _frame_high - _fw_highest
      90. ' ANPASSEN AN $framsize!
      91. ' $framesize = 800
      92. ' Wwww = 800 - Wwww
      93. Print #2 , "HW-SW-FS: " ; Ww ; "-" ; Www ; "-" ; Wwww
      94. ')
      95. End If
      96. '(
      97. Ww = _hwstackstart - _hw_lowest
      98. Www = _hwstack_low - _sw_lowest
      99. Wwww = _frame_high - _fw_highest
      100. ' ANPASSEN AN $framsize!
      101. ' $framesize = 800
      102. ' Wwww = 800 - Wwww
      103. Print #2 , "HW-SW-FS: " ; Ww ; "-" ; Www ; "-" ; Wwww
      104. ')
      105. Loop
      Display All

      Pac-Man wrote:

      Ich kann doch einen Interrupt nicht durch eine Schleife oder wait in einer sub ausbremsen.
      ?
    • Pac-Man wrote:

      Das verstehe ich nicht. Ich kann doch einen Interrupt nicht durch eine Schleife oder wait in einer sub ausbremsen. Ich denke dass der immer feuert wenn die Bedingungen eintreffen.
      Klar geht das. Absichtich mit Disable Interrupts oder wie in Deinem Fall wenn von der Isr die Sub aufgerufen wird (Betriebsanzeige).Dann wird die in aller Ruhe ausgeführt um dann wieder in die Isr zurück zu springen. Solange man die nicht verläßt wird kein neuer Int ausgeführt. Ich würde die Sekunden vielleicht auch Minuten drinn lassen. und den Rest von der Hauptschleife erledigen lassen wenn sie dann mal Zeit hat. 13:60:03 sieht zwar nicht so toll aus, verursacht aber kaum ein Problem. Eine Isr die solange dauert das eine Halbe Nachricht (oder immer wieder Sekunden) verloren geht scheint mir da lästiger.
    • Hi, neuer Vorschlag. Dieses mal in der Do Loop und ohne Wait.

      Source Code

      1. Do
      2. If Flag_minute_rum = 1 Then
      3. Incr Minuten
      4. If Minuten >= 60 Then
      5. Minuten = 0
      6. Incr Stunden
      7. If Stunden >= 24 Then
      8. Stunden = 0
      9. Incr Tage
      10. If Tage >= 10 Then Tage = 0
      11. End If
      12. End If
      13. If Flag_minute_rum = 1 And Minuten = 0 And Stunden = 0 And Tage = 0 Then 10_tage 'alle 10 Tage
      14. If Flag_minute_rum = 1 And Minuten = 0 And Stunden = 0 Then Taeglich 'täglich um 12 Uhr
      15. If Flag_minute_rum = 1 And Minuten = 0 Then Stuendlich 'stündlich
      16. Flag_minute_rum = 0
      17. End If
      18. If Flag_fehler_aufgetreten = 1 Then Led_5 = 1
      19. Loop
      20. End
      21. '##################################### Ende Hauptschleife ####################################
      22. 'Timer
      23. Anzeigen: 'Betriebsanzeige
      24. Timer1 = 34286 '49111 Timer auf 1 sekunde
      25. Incr Sekunden
      26. Incr Sekunden_tick
      27. If Sekunden >= 60 Then
      28. Flag_minute_rum = 1
      29. Sekunden = 0
      30. End If
      31. Gosub Betriebszustandsanzeige
      32. Return
      33. Sub 10_tage
      34. End Sub
      35. Sub Taeglich
      36. Print#2 , "Tag"
      37. End Sub
      38. Sub Stuendlich
      39. Print#2 , "Stunde"
      40. End Sub
      41. Sub Betriebszustandsanzeige
      42. Toggle Led_1
      43. End Sub
      Display All
      Eine Stunde dauert etwa 1Min40Sec zu lange. Liegt das an Timer1 = 34286 oder an der Ungenauigkeit des internen Tackts (8MHZ)
    • Aber das ändert doch nichts an seinem Problem.
      Deine Abweichung ist weniger als 3% und damit locker innerhalb der Spec. vom internen Osc.
      Entweder auf einen Quarz gehen oder über das OSCCAL Register vorsichtig die Frequenz ziehen. Aber der ist halt Temp.-abhängig und wird immer einen größeren Fehler haben.
    • Franz wrote:

      Aber das ändert doch nichts an seinem Problem.
      Tut es nicht. Hab's probiert. Warum also nicht >= benutzen?


      Franz wrote:

      Deine Abweichung ist weniger als 3% und damit locker innerhalb der Spec. vom internen Osc.
      Danke, hab ich mir gedacht. Mit OSCCAL Register zu arbeiten macht denke ich keinen Sinn weil das ja dann für jeden Kontroller gemacht werden muss.

      Ist die neue Routine soweit richtig?
    • Ich benutze ungerne das Setzen des Timer Wertes, weil dann die Genauigkeit auch noch davon abhängt, welche Interrupts sonst noch laufen.
      Wenn du den Compare Interrupt nimmst und den Compare Wert auf 31250-1 setzt, wird deine ISR genauso oft aufgerufen, aber dafür kann sich kein Fehler aufaddieren, weil dir etwas anderes dazwischenkommt.
    • Pac-Man wrote:

      Warum also nicht >= benutzen?
      Doch benutzen. Es ist ein Takt schneller als > alleine und sicherer als =. Falls irgendwas dazwischenkommt geht sie damit gleich 4 Minuten nach.

      Franz wrote:

      Wenn du den Compare Interrupt nimmst und den Compare Wert auf 31250-1 setzt, wird deine ISR genauso oft aufgerufen, aber dafür kann sich kein Fehler aufaddieren, weil dir etwas anderes dazwischenkommt.
      Nur wenn die isr den Wert neu berechnet oder der Timer zurückgesetzt wird (CTC). Dann brauchts gar keine Isr mehr. (So lange die Main nicht mehr als eine Sekunde für nen Loop braucht.)