PBeck
04.02.2009, 21:29
Hallo,
bereits vor einiger Zeit habe ich mich mit dem Thema Küchenuhr beschäftigt.
Damals noch mit Logikbausteinen => https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26033&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 :))
'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
bereits vor einiger Zeit habe ich mich mit dem Thema Küchenuhr beschäftigt.
Damals noch mit Logikbausteinen => https://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26033&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 :))
'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