Unterprogramm, 2. Mikrocontroller

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

    • Unterprogramm, 2. Mikrocontroller

      Hallo,
      für eine Alarmanlage oder andere Überwachungsschaltungen soll eventuell vor oder nach dem Auslösen eine Taste gedrückt werden, damit soll der Tonalarm unterbunden werden.
      Das habe ich mit einem Sub realisiert.

      Sub Keypressed
      If Pind.3 = 0 Then Pind.3 = 1
      Wait 3600

      Nun soll aber die Überwachung in der Wartezeit nicht unterbrochen werden. Ist das möglich?
      Gruß
      Fiete
    • sowas lässt sich mit einem timerinterrupt lösen. Dabei wird ein timer so eingerichtet, dass er zB alle 10 mS in seine eigene interrupt-Routine springt. Dort zählt er jedesmal eine Variable herrunter. Wird die dann mal =0 dann kann er was machen. Bei dir würde die Variable mit 3600x100 geladen und der Alarm abgestellt und der timer gestartet. Wenn diese Variable dann (durch ständiges Anspringen der interrupt-sub alle 10 mS) =0 wird, wird der Alarm wieder angestellt. So mal ganz grob.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Jetzt wird's verwirrend. Das Beste wäre, @Fiede, du zeigst uns dein komplettes Programm, sonst vermuten wir nur unterschiedliches Zeugs.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • danke für die prompten Antworten.

      hier ist das Programm:
      Schalterüberwachung
      '
      'es sollen 3 Schalter überwacht werden. Es handelt sich um Kühlwassertemperatur,
      'Kühlwasserdruck und Getriebeöldruck. Die Aufnehmer befinden sich im
      'Maschinenraum.
      'Es sollen je 1 optische und 1 akustische
      'Schalttafeln im Steuerhaus und im Maschinenraum angesprochen werden.
      'Die Aufnehmer öffnen oder schließen einen Schalter je nach an dem Aufnehmer
      'einzustellendem Druck oder Temperatur.
      '
      'Die Anlage wird vom Maschinenraum eingeschaltet.
      '
      'Nach dem Einschalten sollen die 3 Leuchten 5 Sekunden blinken und das
      'Signalhorn nach 5 Sekunden 2 kurze Töne ausgeben.
      'Beim Schalten eines oder mehrerer Schalter (Alarm) soll die jeweilige LED
      'blinken,gleichzeitig soll ein Warnton ertönen.
      'Der Warnton kann durch einen Schalter abgestellt werden. Eine Zeitschleife
      'überprüft nach 60 Sekunden ob der Alarm noch anliegt, sollte das der Fall sein,
      'wird der Warnton wieder aktiviert.
      '
      'Anzeigen : Superhelle LEDs, eventl. über Mosfets
      'Signalhörner Anteuerung über Mosfets
      '24 Volt Versorgung durch Festspannungsregler 7805 auf 5 Volt
      '



      $regfile = "m8def.dat"
      $crystal = 3686400
      $hwstack = 32
      $swstack = 10
      $framesize = 80

      Declare Sub Keypressed


      'Die Schalter schalten gegen Masse, alle Ports haben einen Pullup-Widerstand

      Config Portb.0 = Input 'Wassertemperatur
      Portb.0 = 1

      Config Portb.1 = Input 'Motoroeldruck
      Portb.1 = 1

      Config Portb.2 = Input 'Getriebeoeldruck
      Portb.2 = 1

      Config Portb.3 = Input 'Quittierschalter
      Portd.1 = 1

      Config Portd.0 = Output 'LED Wassertempe-
      'ratur
      Config Portd.1 = Output 'LED Motoroeldruck

      Config Portd.2 = Output 'LED Getriebeoel-
      'druck
      Config Portd.3 = Output 'Hupe


      Toggle Portd.0
      Toggle Portd.1
      Toggle Portd.2
      Waitms 100
      Toggle Portd.0
      Toggle Portd.1
      Toggle Portd.2
      Waitms 100

      Portd.3 = 1
      Waitms 500
      Portd.3 = 0
      Waitms 500
      Portd.3 = 1
      Waitms 500
      Portd.3 = 0



      Do

      If Pinb.0 = 0 Then Pind.0 = 1
      If Pinb.1 = 0 Then Pind.1 = 1
      If Pinb.2 = 0 Then Pind.2 = 1
      If Pind.0 = 1 Or Pind.1 = 1 Or Pind2. = 1 Then Pind.3 = 1

      Debounce Pinb.3 , 0 , Keypressed , Sub


      Loop


      '----------------------------------------------------------------------------

      Sub Keypressed
      If Pind.3 = 0 Then Pind.3 = 1
      Wait 60

      End Sub

      End


      Vorerst schon mal Dank für die Hilfe.
      Gruß
      Fiete
    • Fiede schrieb:

      If Pind.0 = 1 Or Pind.1 = 1 Or Pind2. = 1 Then Pind.3 = 1
      Das schaltet deine Hupe ein. Übrigens, ports, die was schalten sollen, musst du mit portx.y ansprechen, bei deiner Hupe also portd.3=1.
      Jetzt kannst du das Anschalten noch von einem flag abhängig machen. Dieses flag (Variable) steuert dann, ob die Hupe überhaupt hupen kann.
      If Pind.0 = 1 Or Pind.1 = 1 Or Pind2. = 1 and flag=0 Then Portd.3 = 1
      Es wird also nur gehupt, wenn einer der Schalter bedient wurde und das flag=0 ist.
      Das flag setzt du mit deiner sub. Jetzt geht's nur noch um das Zurücksetzen des flags. Deine do..loop-Schleife rast ja permanent durch, wenn die einen 10 mS-Ruckler macht, wäre das hier auch nicht bemerkbar. Aber mit diesem Ruckler ist die Durchlaufzeit berechenbarer. Das heißt, wenn die do..loop 100x durchlaufen wird, vergeht mindestens 1 Sekunde. Das kannst du verwenden, ein gesetztes flag nach einer Zeit zurück zu stellen.
      das könnte dann so aussehen

      Dim flag as word
      dim hupe as bit
      flag=0
      Do

      If Pinb.0 = 0 Then Portd.0 = 1
      If Pinb.1 = 0 Then Portd.1 = 1
      If Pinb.2 = 0 Then Portd.2 = 1
      If Pinb.0 = 0 Or Pinb.1 = 0 Or Pinb2. = 0 and flag=0 Then
      hupe=1
      else
      Hupe=0
      end if

      Portd.3 = hupe
      waitms 10
      if flag >0 then decr flag

      Debounce Pinb.3 , 0 , Keypressed , Sub


      Loop
      Sub Keypressed
      If Hupe=1 Then flag=60000

      End Sub

      Ich hab' jetzt noch weiter drin rumgeschmiert, die ports (Ausgänge) abzufragen ist nicht gut. Lieber Variablen verwenden und die ports mit Variablen setzen.
      Raum für Notizen

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

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

      Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von tschoeatsch ()

    • Fiede schrieb:

      Der Warnton kann durch einen Schalter abgestellt werden. Eine Zeitschleife
      'überprüft nach 60 Sekunden ob der Alarm noch anliegt, sollte das der Fall sein,
      'wird der Warnton wieder aktiviert


      Frage ist der Schalter Pflicht?

      Normal ist dies bei Alarmanlagen nicht so. Es sollte immer ein Taster sein, dann hat sich dein Problem von selbst erledigt. Also nur eine kurze Quttierung „ich habe den Alarm gehört“. Jede Unterbrechung der Signalisierung ob zeitlich oder nicht sollte in solche Anlagen schon vorab ausgeschossen werden. Es sei denn das akustische Signal ist nur eine zusätzliche Option. Lichtsignal zeigt ja wer was ausgelöst hat. Nun ist man gezwungen Fehler zu beheben der Tasterimpuls schaltet das „lästige Signal nur solange ab bis Fehler behoben ist. Das muss natürlich in der Software so verknüpft sein.

      Viel Erfolg
    • Mitch64 schrieb:

      Das wäre jetzt eine schöne Steuerung, die sich mit einer Statemachine lösen lässt.
      @Fiede Statemachine Tutorial Jetzt musst du dich auch mal bei der timerProgrammierung einlesen. Ist aber auch nicht schlimm.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • Mitch64 schrieb:

      einer Statemachine lösen
      Ein großes Wort für eine einfache Abfrage - erinnert stark an Ärztelatein = simple Dinge kompliziert Aussagen.

      tschoeatsch schrieb:

      die ports (Ausgänge) abzufragen ist nicht gut. Lieber Variablen verwenden und die ports mit Variablen setzen.
      Was ist daran nicht gut? ?( Sofort ersichtlich welcher Pin was tut(tuen soll). 8o
      Zu Variablen / Aliase fallen mir gleich mehrere Nachteile ein. :S
    • Pluto25 schrieb:

      Ein großes Wort für eine einfache Abfrage - erinnert stark an Ärztelatein = simple Dinge kompliziert Aussagen.
      Das war ein Vorschlag.

      An einfachen Steuerung lernt man die Statemachine (Zustandsautomat) am besten.
      Sozusagen als Übung.

      Ärztelatein ist nicht mein Ding, Controller und Programmieren schon. ;)
      Kaum macht man es richtig - und schon geht's!
    • Die Zeile

      BASCOM-Quellcode

      1. If Pind.0 = 1 Or Pind.1 = 1 Or Pind2. = 1 Then Pind.3 = 1
      ließe sich sogar verkürzen wenn alle drei Pins 1 sein müssten

      BASCOM-Quellcode

      1. If Portd = 7 Then Portd.3 = 1
      Allerdings wird dann immer nur der gesamte Port abgefragt und nicht die einzelnen Zustände der Pins.
      Eine Lösung habe ich nicht, aber mir gefällt Ihr Problem.

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

    • Fiede schrieb:

      Sub Keypressed
      If Pind.3 = 0 Then Pind.3 = 1
      Wait 3600
      Hier ein Beispiel für eine freilaufende Hauptschleife unter Benutzung eines Timers.

      BASCOM-Quellcode

      1. 'Arduino Leonardo
      2. 'Programmieren ohne Wait
      3. 'Beispiel für freilaufende Haupschleife und einer blinkenden LED
      4. ' Udo Lorenz 27.11.2018
      5. '$sim
      6. $regfile = "m32u4def.dat"
      7. $crystal = 16000000
      8. $hwstack = 80
      9. $swstack = 80
      10. $framesize = 100
      11. $baud = 115200
      12. Dim Milli As Dword
      13. Dim Milli1 As Dword
      14. Config Portc.7 = Output
      15. Led Alias Portc.7
      16. ' Timer und Teiler festlegen Werte für 1ms
      17. Config Timer3 = Timer , Prescale = 64 , Clear Timer = 1 , Compare_a = Disconnect
      18. Ocr3a = 249 'Wert für 1000 ms = 62499/P=256; 1ms= 249/P=64
      19. On Compare3a Timer_irq 'Unterprogramm festlegen
      20. Start Timer3 'Aktivieren des Timers
      21. Enable Compare3a 'Timer Interrupt
      22. Enable Interrupts 'Interrupt Global ON
      23. Declare Sub Beispiel
      24. Milli1 = Milli + 500 '500 = 500ms
      25. 'Milli2 = Milli + 1000 '2. Zeitzähler
      26. 'Hauptschleife
      27. Do
      28. If Milli1 =< Milli Then
      29. Call Beispiel 'hier kann natürlich auch gleich "Toggle LED" stehen
      30. Milli1 = Milli + 500
      31. End If
      32. Loop
      33. End
      34. Sub Beispiel
      35. 'beliebiger Code, Ausführung alle 500ms
      36. Toggle Led
      37. End Sub
      38. Timer_irq:
      39. Milli = Milli + 1 'oder "incr Milli"
      40. Return
      41. End
      Alles anzeigen
    • Ich mache das mit dem Timer ähnlich, allerdings (so glaube ich) einfacher nachvollziehbar. Hier mal die wesentlichen Fragmente aus einem meiner Programme.

      1: Deklaration des Timers mit Timerstartwert für 1ms (1/1000 s):

      BASCOM-Quellcode

      1. '==============================================================================
      2. 'Timerkonfiguration Timer 1 (16 Bit) für 1/1000 Sekunde
      3. '------------------------------------------------------------------------------
      4. Config Timer1 = Timer , Prescale = 1
      5. On Timer1 Timer1_isr
      6. Disable Timer1
      7. Enable Interrupts
      8. Const Timerstartwert = 57536 '1 / 1000s Bei 8 Mhz
      9. Timer1 = Timerstartwert


      Die dazugehörende Interruptroutine:

      BASCOM-Quellcode

      1. '==============================================================================
      2. ' Timer Interruptroutine
      3. '------------------------------------------------------------------------------
      4. 'Ansprung in Intervallen von 1/1000 Sekunden
      5. 'Für jede Funktion (hier LED 1 bis 7) wird der Wert hochgezählt
      6. 'der Wert ist für jede Funktion auch unabhängig steuerbar
      7. '==============================================================================
      8. Timer1_isr:
      9. Timer1 = Timerstartwert 'zu Beginn den Timerstartwert zurücksetzen
      10. Incr ledcounter_1
      11. Incr ledcounter_2
      12. Incr ledcounter_3
      13. Incr ledcounter_4
      14. Incr ledcounter_5
      15. Incr ledcounter_6
      16. Incr ledcounter_7
      17. Return
      Alles anzeigen

      Im Hauptprogramm kann die Blinkfrequenz (oder aber alle anderen gewünschten Funktionen) unabhängig gesteuert werden. Für jede gewünschte Funktion wird halt eine Zählvariable deklariert, die in der Interruptroutine kontinuierlich verändert wird. Die Rückstellung der Variable erfolgt im Hauptprogramm.

      BASCOM-Quellcode

      1. Do
      2. If Ledcounter_1 = 500 Then
      3. Toggle Led_1
      4. Ledcounter_1 = 0
      5. End If
      6. If Ledcounter_2 = 600 Then
      7. Toggle Led_2
      8. Ledcounter_2 = 0
      9. End If
      10. If Ledcounter_3 = 700 Then
      11. Toggle Led_3
      12. Ledcounter_3 = 0
      13. End If
      14. If Ledcounter_4 = 800 Then
      15. Toggle Led_4
      16. Ledcounter_4 = 0
      17. End If
      18. If Ledcounter_5 = 900 Then
      19. Toggle Led_5
      20. Ledcounter_5 = 0
      21. End If
      22. If Ledcounter_6 = 1000 Then
      23. Toggle Led_6
      24. Ledcounter_6 = 0
      25. End If
      26. If Ledcounter_7 = 100 Then
      27. Toggle Led_7
      28. Ledcounter_7 = 0
      29. End If
      30. Loop
      Alles anzeigen
      Wenn das die Lösung ist, möchte ich mein Problem wieder haben.
    • Nochmals vielen Dank für die Vorschläge. -Pluto hat nicht ganz unrecht mit dem "erschlagen". Ich bemühe mich das zu verstehen.
      Gleichzeitig muss ich mich aber auch für meine Schlampigkeit entschuldigen. Mein Entwurf war ja voll von Fehlern.
      Ihr habt sicher Recht. es ist kein Schalter sondern ein Taster der unterbricht.
      Noch einmal in der Kurzfassung: Alarm (3 verschiedene) wird am Motor durch einen Schalter (gegen Masse oder plus) ausgelöst.
      Dann soll die jeweilige LED anzeigen, gleichzeitig ertönt die Hupe.
      Es sollen 3 Einheiten eingesetzt werden. 1. Maschinenraum, 2. Messe und 3. Steuerhaus. In der Messe und im Steuerhaus soll der akustische Alarm abschaltbar sein, muss aber, wenn der Alarm weiterhin ansteht nach einer gewissen Zeit (ca. 3 bis 8 Minuten) wieder ertönen. Sollte dann aber auch wieder über diesen Zeitraum abstellbar sein. -Die Zeit von 3 bis 4 Std. war für eine andere Alarmanlage gedacht.
      Die einstellbare Zeit ist kein Faktor der exakt sein muss - ich werde mich aber trotzdem mit dem Timer beschäftigen. Mit den Timereinstellungen kenne ich mich etwas aus, weiß aber nicht genau wie ich die interrups einsetzen kann. Ich werde dran bleiben und mich wieder melden.
      Das Programm sieht jetzt so aus.
      Schalterüberwachung
      '

      BASCOM-Quellcode

      1. $regfile = "m8def.dat"
      2. $crystal = 3686400
      3. $hwstack = 32
      4. $swstack = 10
      5. $framesize = 80
      6. Declare Sub Keypressed
      7. Dim Flag As Word
      8. Dim Hupe As Bit
      9. Flag = 0
      10. 'Die Schalter schalten gegen Masse, alle Ports haben einen Pullup-Widerstand
      11. Config Pinb.0 = Input 'Wassertemperatur
      12. Portb.0 = 1
      13. Config Pinb.1 = Input 'Motoroeldruck
      14. Portb.1 = 1
      15. Config Pinb.2 = Input 'Getriebeoeldruck
      16. Portb.2 = 1
      17. Config Pinb.3 = Input 'Quittierschalter
      18. Portb.1 = 1
      19. Config Portd.2 = Output 'LED Wassertempe-
      20. 'ratur
      21. Config Portd.3 = Output 'LED Motoroeldruck
      22. Config Portd.4 = Output 'LED Getriebeoel-
      23. 'druck
      24. Config Portd.5 = Output 'Hupe
      25. Portd.2 = 1
      26. Portd.3 = 1
      27. Portd.4 = 1
      28. Waitms 1000
      29. Portd.2 = 0
      30. Portd.3 = 0
      31. Portd.4 = 0
      32. Waitms 1000
      33. Portd.2 = 1
      34. Portd.3 = 1
      35. Portd.4 = 1
      36. Waitms 1000
      37. Portd.2 = 0
      38. Portd.3 = 0
      39. Portd.4 = 0
      40. Waitms 1000
      41. Portd.2 = 1
      42. Portd.3 = 1
      43. Portd.4 = 1
      44. Waitms 1000
      45. Portd.2 = 0
      46. Portd.3 = 0
      47. Portd.4 = 0
      48. Wait 1000
      49. Portd.5 = 1
      50. Waitms 500
      51. Portd.5 = 0
      52. Waitms 500
      53. Portd.5 = 1
      54. Waitms 500
      55. Portd.5 = 0
      56. Do
      57. If Pinb.0 = 0 Then
      58. Portd.2 = 1
      59. Else
      60. Portd.2 = 0
      61. End If
      62. If Pinb.1 = 0 Then
      63. Portd.3 = 1
      64. Else
      65. Portd.3 = 0
      66. End If
      67. If Pinb.2 = 0 Then
      68. Portd.4 = 1
      69. Else
      70. Portd.4 = 0
      71. End If
      72. If Pinb.0 = 0 Or Pinb.1 = 0 Or Pinb2. = 0 And Flag = 0 Then
      73. Portd.5 = 1
      74. Hupe = 1
      75. Else
      76. Portd.5 = 0
      77. Hupe = 0
      78. If Flag > 0 Then Decr Flag
      79. End If
      80. Debounce Pinb.3 , 0 , Keypressed , Sub
      81. Loop
      82. '----------------------------------------------------------------------------
      83. Sub Keypressed
      84. If Hupe = 1 Then Flag = 60000
      85. End Sub
      86. End
      Alles anzeigen
    • In der do...loop wird das flag runter gezählt. Wie lange das braucht, richtet sich nach dem Zeitverbrauch für die einzelnen Befehle. Das geht recht flott und ist so auch erst mal garnicht bekannt. Aus meiner Sicht ist es besser, wenn man da eine feste Zeitverzögerung wie waitms 10 einfügt. Dann weiß man, ein Durchgang braucht mindestens 10 mS und das Runterzählen von 60000 braucht dann 10 Minuten. Gut, es geht auch ohne, wenn man die Durchlaufzeit mit dem Simulator misst und den Wert für flag entsprechend anpasst.
      Raum für Notizen

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

      -----------------------------------------------------------------------------------------------------
    • @Friede, Das "booten" ist recht professionell - Da denkt der Kunde "das Ding tut ja richtig was" a_447_3df864b7
      Schon mal über ne Schleife nachgedacht :
      Dim a as Byte 'ab Zeile 58
      For a = 1 to 3
      Portd=$1C ' (36) = &B00011100
      Wait 1
      Portd=0
      Wait 1
      next
      erspart 17 Zeilen Schreibarbeit a_221_2cffa601

      tschoeatsch schrieb:

      besser, wenn man da eine feste Zeitverzögerung wie waitms 10 einfügt
      Das erspart auch ne böse Überraschung wenn der Code mal woanders (anderer Chip/Quarz) eingesetzt wird.