-         

Ergebnis 1 bis 4 von 4

Thema: küchenuhr - timer1 läuft "einfach" los

  1. #1
    Neuer Benutzer Öfters hier
    Registriert seit
    29.04.2006
    Beiträge
    10

    küchenuhr - timer1 läuft "einfach" los

    Anzeige

    Hallo,

    bereits vor einiger Zeit habe ich mich mit dem Thema Küchenuhr beschäftigt.
    Damals noch mit Logikbausteinen => http://www.roboternetz.de/phpBB2/zei...033&highlight=

    Nachdem die digitale Schaltung mit Mega8 fertig war mit Assembler (ist wohl nicht ganz mein Ding) und seit dieser Woche mit Bascom. Im Grunde bin ich schon viel weiter von der Funktion gekommen als zuvor, jedoch weiß ich bei ein paar Problemen einfach nicht weiter und wollte um eure Hilfe bitten

    Im folgenden seht ihr das Bascom-Programm (über bessere Programmiermöglichkeiten bin ich natürlich auch erfreut )

    Code:
    'Cooktimer Version 0.1 by Patrick Beck
    '-------------------------------------
    'Cooktimer is a cook clock on the base
    'of a ATMEL AVR Mega8 microcontroller.
    'Programming language is Bascom basic.
    '-------------------------------------
     
    $regfile = "m8def.dat"
    $framesize = 60
    $hwstack = 40
    $swstack = 32
     
    Config Timer0 = TIMER , Prescale = 64                       ' multiplex timer
    ON Timer0 Timer0_isr
    CONST Timer0load = 178
     
    Config Timer1 = TIMER , Prescale = 1024                     ' one minute timer
    ON Timer1 Timer1_isr
    CONST Timer1load = 6941
     
     
    Ddrb = &B11111111                                           ' PORTB as output
    Ddrd = &B11111111                                           ' PORTD (7-segment) as output
    Ddrc = &B00000000                                           ' PINC (pushbutton) as input
    Portc = &B11111111                                          ' activate the pullup resistors of PINC
     
    DIM Onedigit AS Byte
    DIM Twodigit AS Byte
    DIM Timer1_active AS Byte
     
    Onedigit = 0
    Twodigit = 0
    Timer1_active = 0
     
    DO
     
       IF Pinc.1 = 0 THEN                                       ' when PINC.1 is pressed the digits will be activated
          Waitms 50                                             ' and shows 1 on the onedigit segment
          Enable Timer0                                         ' wait to detect only one signal of a push
          Enable Interrupts                                     ' enable timer and interrupts for segment multiplexing
          Incr Onedigit
          Portb.1 = 1
       END IF
     
       IF Pinc.0 = 0 THEN                                       ' when PINC.2 is pressed the digits will be activated
          Waitms 50                                             ' and shows 1 on the twodigit segment
          Enable Timer0                                         ' wait to detect only one signal of a push
          Enable Interrupts                                     ' enable timer and interrupts for segment multiplexing
          Incr Twodigit
          Portb.2 = 1
       END IF
     
       IF Onedigit = 10 THEN                                    ' when the onedigit variable reach 10 (9 on the segment) then set it to 0
          Onedigit = 0
       END IF
     
       IF Twodigit = 10 THEN
          Twodigit = 0                                          ' when the twodigit variable reach 10 (9 on the segment) then set it to 0
       END IF
     
       IF Pinc.2 = 0 AND Timer1_active = 0 THEN                 ' starts the timer if not started yet
          Waitms 50
          Disable Interrupts                                    ' switch the segments of and one - for a visual acception after the timer start
          Portb = 0
          Waitms 100
          Enable Interrupts
          Timer1 = Timer1load
          Enable Timer1
          Timer1_active = 1
       END IF
     
     
       IF Pinc.0 = 0 AND Timer1_active = 1 THEN                 ' you can change the digits when the timer is running, timer will be stopped after a push
          Timer1_active = 0                                     ' you can start the timer with the Button PINC.2
          Disable Timer1
          Incr Twodigit                                         'the digit will be increased in the same time (only one push essential)
          Waitms 50
       END IF
     
       IF Pinc.1 = 0 AND Timer1_active = 1 THEN                 ' the same for twodigit
          Timer1_active = 0
          Disable Timer1
          Incr Onedigit
          Waitms 50                                             ' detect only one push
       END IF
     
       IF Pinc.2 = 0 AND Timer1_active = 1 THEN                 ' when the timer is started you can reset the variables with the start timer button
          Timer1_active = 0
          Disable Timer1                                        ' timer will be stopped and all variables are reset
          Waitms 50                                             ' detect only one push
          GOTO 0
       END IF
     
    LOOP
    END
     
    Segmente:                                                   ' 7-Segment table to control the digit output
    '---------abc.degf--------
      DATA &B10110111                                           ' 0
      DATA &B00000110                                           ' 1
      DATA &B01110011                                           ' 2
      DATA &B01010111                                           ' 3
      DATA &B11000110                                           ' 4
      DATA &B11010101                                           ' 5
      DATA &B11110101                                           ' 6
      DATA &B00000111                                           ' 7
      DATA &B11110111                                           ' 8
      DATA &B11010111                                           ' 9
     
    Timer0_isr:
       Timer0 = Timer0load
     
       IF Portb.1 = 1 THEN
       Portd = Lookup(onedigit , Segmente)                      ' lookup in table with onedigit variable
       Portb = &B00000100                                       ' onedigit active
     
          ELSE
          Portd = Lookup(twodigit , Segmente)
          Portb = &B00000010                                    ' twodigit active
                                                                 ' lookup in table with twodigit variable
       END IF
    RETURN
     
    Timer1_isr:
       Timer1 = Timer1load
       IF Twodigit = 0 AND Onedigit = 1 THEN                    ' if all digits zero, then activate the buzzer
          Disable Timer1
          Timer1_active = 0
          Portb.0 = 1
          Waitms 200
       END IF
                                                                 ' if onedigit greater zero then decrease the onedigit variable
       IF Onedigit > 0 THEN
          Decr Onedigit
     
       ELSEIF Onedigit = 0 AND Twodigit > 0 THEN                ' if onedigit zero and twodigit greater then zero decrease twodigit
          Decr Twodigit                                         ' and set the ondigit variable to nine
          Onedigit = 9
       END IF
     
    RETURN
    Im Grunde habe ich zwei Timer im Einsatz einen zum Multiplexen der 7-Segment-Anzeigen und einen um nach einer Minute einen Interrupt auszulösen (war für mich einfacher ohne eine variable hochzuzählen, wie genau die Sache ist steht aber auf einem anderen Blatt).

    Drei Taster sind verbaut. Zwei um jeweils ein zugehöriges Segment einzustellen und der dritte Taster zum starten des Timers (ist der Timer gestartet soll dieser Taster dazu dienen zum reseten => Goto 0)

    Ist auf beiden Segmenten die 0 erreicht ertönt ein Summer. Im Grunde war dies dann schon die komplette Funktionsweise

    Mein größtes Problem bei der Umsetzung ist, wenn ich die Segmente aktiviere z.B durch das Betätigen des Einer-Segments, wobei ich es auf 1 stelle, jedoch nicht den Start-Taster drücke - drücke ich nun nachdem bereits einige Minuten vergangen sind auf den Start-Taster, ertönt direkt der Summer. Mir ist nicht klar, wie der Timer1 losläuft (läuft er überhaupt los) oder woher das Problem rührt.

    Ein weiteres Problem ist das der Taster für das Starten des Timers, sowie zum Reset manchmal zufällige Funktionen ausführt. Dies bedeutet, ich setze eine Variable wenn der Timer läuft und setze sie zurück, wenn er disabled wurde. Jedoch Reset er mir auch manchmal, wenn ich über die Einstelltaster hochtakte und dann auf den Start-Taster drücke, obwohl bei dieser Konstellation die Variable nicht gesetzt ist.

    Was mich auch interessieren würde => Ich möchte das der Summer bei 00 ertönt, jedoch unterbricht er in der jetzigen Situation alle Interrupts in der Warteschleife - sieht beim multiplexen der Segmente ein bisschen doof aus, wenn nur eine leuchtet

    Im Anhang findet ihr noch den Schaltplan.

    Ich freue mich auf eure Antworten

    Grüße Patrick
    Angehängte Dateien Angehängte Dateien

  2. #2
    Erfahrener Benutzer Roboter Experte
    Registriert seit
    15.01.2007
    Ort
    Göttingen
    Beiträge
    705
    Moin Patrick!

    Ich habe mich mal darauf beschränkt, mir die Timer-Befehle Deines Codes anzusehen (man muss ja auch nicht immer alles wissen und verstehen ).

    Ich glaube, Dein Denkfehler liegt hier:

    Disable Timer1 ' timer will be stopped and all variables are reset
    Mit enable und disable legst Du nur fest, ob der Timer-Interrupt aktiviert sein soll, d.h. ob die entsprechende ISR beim Überlauf ausgeführt werden soll oder eben nicht.
    Um den Timer zu stoppen bzw. wieder zu starten musst Du und "Stop TimerX" bzw. "Start TimerX" verwenden. Wobei Start TimerX quasi automatisch ausgeführt wird, wenn Du den Timer konfigurierst. Er läuft also nach der Config TimerX-Zeile automatisch los - und wenn er das nicht soll, musst Du gleich in die nächste Zeile Stop TimerX schreiben (und wenn der Zählinhalt besonders kritisch ist, auch noch TimerX = 0).

    Hoffe, das hilft

    Gruß,

    Daniel

  3. #3
    Erfahrener Benutzer Roboter Genie
    Registriert seit
    19.07.2007
    Alter
    53
    Beiträge
    1.080
    Wie Dr. Sauerbruch schon schrieb zum Timer... dazu noch:

    - Verträgt es dein Summer-Transistor auf Dauer, wenn er ohne Vorwiderstand direkt am µC hängt?
    - In deinem Listing fehlt die Angabe zu "Crystal", damit der Compiler ne Ahnung hat, wie lange er irgendwo herumschleifen muss, damit aus "Waitms 50" auch wirklich eine Pause von 50ms wird.

    Gruß und gutes Gelingen von MeckPommER
    Mein Hexapod im Detail auf www.vreal.de

  4. #4
    Neuer Benutzer Öfters hier
    Registriert seit
    29.04.2006
    Beiträge
    10
    Hall ihr Zwei,

    ich bedanke mich für die kompetente Hilfe. Ich habe bereits zuvor mit Stop Timer herumexperimentiert, jedoch immer ohne das Vorladen der Variablen. Jetzt funktioniert es wirklich optimal. Vielen Dank Sauerbruch. Im selben Atemzug natürlich auch einen Dank an MeckPommER für den Hinweis mit der Angabe zu "Crystal", so funktioniert die ganze Timing-Geschichte wirklich rund

    Zum Thema Summer und multiplexen habe ich mir nun quick und dirty beholfen indem ich einfach die Segmente abschalte, wenn der Summer ertönt Zwar keine wirkliche Lösung, tut es aber ohne Probleme

    Die Geschichte mit dem Fehlerkennen der Taster mit Start Timer und Reset tritt durch die richtige Zeitberechnung von waitms meines erachtens nicht mehr so stark auf. Würde ich also so mal als funktionierend erachten.

    Im folgenden nochmal der verbesserte Bascom-Code, sowie eine aktuelle Version des Schaltplans von heute. Habe alle Änderungen eingefügt. Das Projekt lag ja schon wieder 5 Monate in der Ecke Der Basiswiderstand ist im übrigen auf der Platine verbaut, war eine frühere Fassung des Plans als er noch in Entwicklung war

    Code:
    'Cooktimer Version 1.0 by Patrick Beck
    '-------------------------------------
    'Cooktimer is a cook clock on the base
    'of a ATMEL AVR Mega8 microcontroller.
    'Programming language is Bascom basic.
    '-------------------------------------
     
    $regfile = "m8def.dat"
    $framesize = 60
    $hwstack = 40
    $swstack = 32
     
    $crystal = 1000000                                          ' internal rc-oscillator of the mega8 on 1 Mhz
     
    Config Timer0 = TIMER , Prescale = 64                       ' multiplex timer
    ON Timer0 Timer0_isr
    CONST Timer0load = 178
     
    Config Timer1 = TIMER , Prescale = 1024                     ' one minute timer
    ON Timer1 Timer1_isr
    STOP Timer1
    CONST Timer1load = 6941
    Timer1 = Timer1load
     
    Ddrb = &B11111111                                           ' PORTB as output
    Ddrd = &B11111111                                           ' PORTD (7-segment) as output
    Ddrc = &B00000000                                           ' PINC (pushbutton) as input
    Portc = &B11111111                                          ' activate the pullup resistors of PINC
     
    DIM Onedigit AS Byte
    DIM Twodigit AS Byte
    DIM Timer1_active AS Byte
     
    Onedigit = 0
    Twodigit = 0
    Timer1_active = 0
     
    DO
     
       IF Pinc.1 = 0 THEN                                       ' when PINC.1 is pressed the digits will be activated
          Waitms 200                                            ' and shows 1 on the onedigit segment
          Enable Timer0                                         ' wait to detect only one signal of a push
          Enable Interrupts                                     ' enable timer and interrupts for segment multiplexing
          Incr Onedigit
          Portb.1 = 1
       END IF
     
       IF Pinc.0 = 0 THEN                                       ' when PINC.2 is pressed the digits will be activated
          Waitms 200                                            ' and shows 1 on the twodigit segment
          Enable Timer0                                         ' wait to detect only one signal of a push
          Enable Interrupts                                     ' enable timer and interrupts for segment multiplexing
          Incr Twodigit
          Portb.2 = 1
       END IF
     
       IF Onedigit = 10 THEN                                    ' when the onedigit variable reach 10 (9 on the segment) then set it to 0
          Onedigit = 0
       END IF
     
       IF Twodigit = 10 THEN
          Twodigit = 0                                          ' when the twodigit variable reach 10 (9 on the segment) then set it to 0
       END IF
     
       IF Pinc.2 = 0 AND Timer1_active = 0 THEN                 ' starts the timer if not started yet
          Waitms 200
          Disable Interrupts                                    ' switch the segments of and one - for a visual acception after the timer start
          Portb = 0
          Waitms 200
          Enable Interrupts
          Enable Timer1
          Start Timer1
          Timer1_active = 1
       END IF
     
     
       IF Pinc.0 = 0 AND Timer1_active = 1 THEN                 ' you can change the digits when the timer is running, timer will be stopped after a push
          Timer1_active = 0                                     ' you can start the timer with the Button PINC.2
          Disable Timer1                                        ' timer will be disabled
          STOP Timer1                                           ' timer will be stopped
          Timer1 = Timer1load                                   ' timer will be loaded with new value
          Incr Twodigit                                         'the digit will be increased in the same time (only one push essential)
          Waitms 200
       END IF
     
       IF Pinc.1 = 0 AND Timer1_active = 1 THEN                 ' the same for twodigit
          Timer1_active = 0
          Disable Timer1
          STOP Timer1
          Timer1 = Timer1load
          Incr Onedigit
          Waitms 200                                            ' detect only one push
       END IF
     
       IF Pinc.2 = 0 AND Timer1_active = 1 THEN                 ' when the timer is started you can reset the variables with the start timer button
          Waitms 200                                            ' detect only one push
          Timer1_active = 0
          Disable Timer1                                        ' timer will be disabled
          STOP Timer1                                           ' timer will be stopped
          Timer1 = Timer1load                                   ' timer will be loaded with new value
     
          GOTO 0
       END IF
     
    LOOP
    END
     
    Segmente:                                                   ' 7-Segment table to control the digit output
    '---------abc.degf--------
      DATA &B10110111                                           ' 0
      DATA &B00000110                                           ' 1
      DATA &B01110011                                           ' 2
      DATA &B01010111                                           ' 3
      DATA &B11000110                                           ' 4
      DATA &B11010101                                           ' 5
      DATA &B11110101                                           ' 6
      DATA &B00000111                                           ' 7
      DATA &B11110111                                           ' 8
      DATA &B11010111                                           ' 9
     
    Timer0_isr:
       Timer0 = Timer0load
     
       IF Portb.1 = 1 THEN
       Portd = Lookup(onedigit , Segmente)                      ' lookup in table with onedigit variable
       Portb = &B00000100                                       ' onedigit active
     
          ELSE
          Portd = Lookup(twodigit , Segmente)
          Portb = &B00000010                                    ' twodigit active
                                                                 ' lookup in table with twodigit variable
       END IF
    RETURN
     
    Timer1_isr:
       Timer1 = Timer1load
       IF Twodigit = 0 AND Onedigit = 1 THEN                    ' if all digits zero, then activate the buzzer
          Disable Timer1
          STOP Timer1
          Timer1 = Timer1load
          Timer1_active = 0
          Disable Interrupts                                    ' switch the segments of and the buzzer on
          Portb = &B00000001
          Waitms 800
          Enable Interrupts
       END IF
                                                                 ' if onedigit greater zero then decrease the onedigit variable
       IF Onedigit > 0 THEN
          Decr Onedigit
     
       ELSEIF Onedigit = 0 AND Twodigit > 0 THEN                ' if onedigit zero and twodigit greater then zero decrease twodigit
          Decr Twodigit                                         ' and set the ondigit variable to nine
          Onedigit = 9
       END IF
     
    RETURN
    Jetzt brauche ich nur noch ein Gehäuse und dann hat meine Mutter eine Küchenuhr In diesem Sinne Vielen Dank für die Hilfe.

    Als nächstes werde ich mir wohl nun mal einen LED-Cube anschauen, ist ja auch eine schöne Sache

    Grüße Patrick
    Angehängte Dateien Angehängte Dateien

Berechtigungen

  • Neue Themen erstellen: Nein
  • Themen beantworten: Nein
  • Anhänge hochladen: Nein
  • Beiträge bearbeiten: Nein
  •