Ich müsste einen Atmega 8 Programieren , wenn ich auf einen Taster
Drücke soll ein ausgang einschalten für 1 sec wenn ich noch mal auf den
gleichen Taster Drücke soll wieder ein anderer eingang für 1 sec
eingehen usw.
Kann mir jemand helfen wie ich sowas Programiere?
Danke schon im Voraus!
welche Programmiersprache hast du dir denn vorgestellt?
Welche Entwicklungsumgebung (auch: Programmieradapter etc) ist
vorhanden?
welche Hardware verwendest du (fertiges board, LOchrasterplatine?)
Die Anforderung selbst ist nicht allzu kompliziert. Zeig doch mal was du
schon hast, dann kann man dir auch besser helfen wo es noch klemmt....
Entweder über einen Timer und einen externen Interrupt (was die schönere
Variante ist) oder du Pollst die ganze Zeit deinen Taster-Pin und wenn
sich der Zustand ändert, schaltest du den gewünschten Pin auf Hi, machst
ein Delay von einer Sekunde und schaltest den Pin wieder auf Low.
Ja ich weiss es nicht ich kenn mich ein wenig mit bascome aus mehr
nicht!
Ja das Bord von Pollin Evolutions borad.
Er kommt in einen Sockel der in Einer Lochrasterplatine Verlötet ist!
Kannst du mir so einen Code geben den ich nur noch einwenig Verändern
muss?
Ja ich will Richtig progrmieren Lerrnen aber ich Brauch sowas so schnell
wie möglich und kann nicht Lange Darauf Warten.
Kannst du mir damit weiter helfen?
Bitte
Zu Basecom kann ich dir leider gar nichts sagen. Ich mache das immer in
C.
Wenn du noch ganz am Anfang stehst mit deiner Programmiererfahrung,
würde ich dir auch eher zur 2. Variante mit dem Pollen raten, da
brauchst du keine Timer konfigurieren und keine Interrupt-Routinen.
Dann ist das auch von einem Anfänger ganz gut zu bewerkstelligen...
Kannst du mir so einen Code sagen?
Bitte
Das Problem ist das wegen so einen Teil einen Wichtige maschiene in
einer Fleischerei Steht und somit der Halbe betrieb nicht Richtig
Arbeiten kann.
Bitte sieh dir den Thread
"Attiny mit Timer und Taster"
an.
Da geht es um genau die gleiche Aufgabenstellung und (im Moment) ganz
unten hab ich ausgeführt, wie man das macht.
Patrick Reichhold schrieb:> Bitte Helft mir Weiter es geht hierbei auch um Viel!> Bitte um Code?
Ganz sicher nicht.
Du willst das lernen?
Dann programmier auch.
Radfahren lernt man nicht, indem man andere bitte für einen zu fahren.
Auf die Schnauze zu fallen gehört dazu. Dann muss man sich aufrappeln
und es noch mal versuchen.
Am besten in Basecome da kenn ich mich ein wenig damit aus!
countdown = 0
timer starten
interrupt enable
do
if( Taste gedrückt ) then
Ausgang ein schalten
countdown = 5
end if
loop
OnTimer
if countdown > 0 then
countdown = countdown - 1
if countdown = 0 then
Ausgang aus schalten
endif
endif
return
In Was ist der countdown angegeben?
Patrick Reichhold schrieb:> Am besten in Basecome da kenn ich mich ein wenig damit aus!>>> countdown = 0> timer starten> interrupt enable>>> do>> if( Taste gedrückt ) then> Ausgang ein schalten> countdown = 5> end if>> loop>> OnTimer> if countdown > 0 then> countdown = countdown - 1> if countdown = 0 then> Ausgang aus schalten> endif> endif> return>> In Was ist der countdown angegeben?
countdown ist eine Variable.
Die 'Einheit' hängt davon ab, wie der Timer eingestellt wurde - wie
schnell der läuft.
Stellt man den so ein, dass er alle 1 Millisekunde die OnTimer Interrupt
Routine aufruft, dann sind das eben Millisekunden. Stell ich den so ein,
dass OnTimer alle 1 Sekunden aufgerufen wird, dann sind das eben
Sekunden. Stell ich den so ein, dass OnTimer alle 0.5 Sekunden
aufgerufen wird, dann sind es eben halbe Sekunden.
Das was ich dort gemacht habe, ist eine Programmskizze, die das
prinzipielle Vorgehen zeigen soll und kein korrektes BASCOM Programm.
Da du dich aber mit BASCOM 'ein wenig auskennst' sollte das dann auch
kein Problem sein, die Skizze in korrekten BASCOM-Code umzusetzen.
FAQ: Timer
Patrick Reichhold schrieb:> Countdown =5?
Die 'Einheit' hängt davon ab, wie der Timer eingestellt wurde - wie
schnell der läuft.
Stellt man den so ein, dass er alle 1 Millisekunde die OnTimer Interrupt
Routine aufruft, dann sind das eben Millisekunden. Stell ich den so ein,
dass OnTimer alle 1 Sekunden aufgerufen wird, dann sind das eben
Sekunden. Stell ich den so ein, dass OnTimer alle 0.5 Sekunden
aufgerufen wird, dann sind es eben halbe Sekunden.
Patrick Reichhold schrieb:> Kannst du mir so einen Code sagen?> Bitte> Das Problem ist das wegen so einen Teil einen Wichtige maschiene in> einer Fleischerei Steht und somit der Halbe betrieb nicht Richtig> Arbeiten kann.
Dann bezahl einen Profi, der das kann.
Wenn du Wasserrohrbruch hast, aber keine Ahnung von Klempnerei hast,
rufst du auch den Klempner und gehst nicht in den Baumarkt "BItte helft
mir".
Es gibt Leute, die die Dinge von der Pieke auf gelernt haben und ihre
Brötchen damit verdienen, etwas zu können was andere nicht können. Sowas
nennt man "Dienstleister".
Was für eine Maschine wird denn da mit einem Atmega8 auf einem
Pollin-Board gesteuert? Na ja, egal.
Wenn du schon einmal ein Lauflicht erstellt hast, sollte das alles in
allem ja kein großes Problem sein (zwar nicht mit Timern und Interrupts,
aber es geht ja auch ohne).
Ich kenne mich jetzt zwar nicht mit Basecom aus, aber eigentlich sollte
das ja von den Abläufen so sein wie bei C auch.
Als erstes musst du die Pins initialisieren. Taster auf Input und
Ausgänge logischerweise auf Output.
Wenn es immer die gleiche Abfolge ist, in der die Outputs geschaltet
werden sollen, erstellst du ein Array mit den Ausgängen in der
entsprechenden Reihenfolge.
Dann brauchst du noch eine Zählervariable, die du beispielsweise 'z'
nennst, die du mit 0 initialisiert.
Nun baust du dir eine Funktion, die den Pin Array[z] auf Hi schaltet,
einen Delay von einer Sekunde macht, den Pin Array[z] wieder auf Low
shaltet, überprüft, ob 'z' der Anzahl der Elemente im Array -1 (!)
entspricht und wenn das nicht der Fall ist, addiert sie zu 'z' eins
hinzu. Sollte 'z' gleich der Anzahl der Elemente im Array -1 sein (-1,
weil das erste Element im Array mit 0 und nicht mit 1 angesprochen
wird), setzt sie 'z' wieder auf 0.
Nun brauchst du noch eine Endlosschleife in der der Taster-Pin abgefragt
wird. Wenn der Taster gedrückt wird, rufst du die eben erstellte
Funktion auf.
Fertig
Karl Heinz schrieb:> Dominik R. schrieb:>>> Fertig>>> Genau so macht man das nicht, wenn man sein Handwerk gelernt hat.>> Delay ist selten die Lösung. Aber oft das Problem.
Mir ist auch klar, dass ein Timer und ein Taster-Interrupt da die
bessere Wahl wären, aber das ist für einen Anfänger schon ziemlich
kniffelig. Deshalb von mir die Poll-Lösung mit Delay...
Dominik R. schrieb:> Karl Heinz schrieb:>> Dominik R. schrieb:>>>>> Fertig>>>>>> Genau so macht man das nicht, wenn man sein Handwerk gelernt hat.>>>> Delay ist selten die Lösung. Aber oft das Problem.>> Mir ist auch klar, dass ein Timer und ein Taster-Interrupt da die> bessere Wahl wären, aber das ist für einen Anfänger schon ziemlich> kniffelig.
In BASCOM sind Timer recht einfach zu handhaben. Viele der klassischen
Fallen in C gibt es dort nicht. Alles was er tun muss, ist sich einen
Vorteiler zu wählen und davon ausgehend ausrechnen, in welchen
Zeitabständen die zum Timer gehörende OnTimer Funktion aufgerufen wird.
BASCOM hat hier zwar einen etwas höheren Overhead, aber von der
Benutzbarkeit sind Timer um einiges leichter zu handhaben. Des ganze
Gefummel mit Konfigurationsregistern und zu setzenden Bits fällt dort
alles weg.
Der Rest ist ein wenig Arbeit mit dem Taschenrechner und die Strategie.
Die hat er ja schon.
Karl Heinz schrieb:> In BASCOM sind Timer recht einfach zu handhaben. Viele der klassischen> Fallen in C gibt es dort nicht.
Dann ist das mit dem Delay wirklich überflüssig. Wie gesagt, ich hab
keinen Plan von Basecom...
Dominik R. schrieb:> Karl Heinz schrieb:>> In BASCOM sind Timer recht einfach zu handhaben. Viele der klassischen>> Fallen in C gibt es dort nicht.>> Dann ist das mit dem Delay wirklich überflüssig. Wie gesagt, ich hab> keinen Plan von Basecom...
Ist schon ok. Sieh selbst
In BASCOM sieht eine einfache Timer-Benutzung so aus
1
...
2
Config Timer0 = Timer , Prescale = 1024
3
On Timer0 OnTimerOverflow
4
5
Enable Timer0
6
Enable Interrupts
7
8
do
9
.....
10
Loop
11
12
13
OnTimerOverflow:
14
...
15
return
und ich finde: noch weiter abstahieren kann man das schon fast nicht
mehr. Weder muss er mit diversen Bits in Konfigurationsregistern
rumfuhrwerken, noch muss er sich raussuchen, welche für einen bestimmten
Vorteiler zu setzen sind, noch kann er sich im Namen der ISR vertun,
weil er den selbst vergibt.
Ok, wenn man im Config angeben könnte, in welchen Zeitabständen die
OnTimerOverflow aufgerufen werden soll, dann wären sogar mathematische
Analphabeten glücklich, der Rest muss eben ein wenig mit dem
Taschenrechner rechnen. Aber so schwer sollte das dann auch nicht sein,
die Taktfrequenz durch 1024 zu teilen und das was rauskommt noch mal
durch 256 und davon dann den Kehrwert nehmen. Wenn man verstanden hat,
wie Timer funktionieren, ist das recht naheliegend und schlüssig.
Ich wette 50€, dass er mit dem sehr guten ausführlichen Post von Dominik
nicht zurecht kommt und dass dieser Thread noch mindestens 100 Beiträge
erreicht vor Anbruch des Wochenendes.
cybmorg schrieb:> Karl Heinz schrieb:>> Delay ist selten die Lösung. Aber oft das Problem.>> Wo siehst du in diesem Fall das Problem mit delay?
Es ist im Grunde immer das gleiche Problem.
Für einfache Sache, wie ein Blinklicht, ist delay eine Lösung. Es ist
etwas, mit dem ein Neuling schnell eine Lösung hinkriegt.
In dem Moment aber, in dem ein Programm mehrere Dinge "gleichzeitig"
machen soll, wie zb Blinklicht UND zusätzlich noch einen Taster
überwachen, werden die delay Lösungen schnell unbrauchbar. Klar, man
kann das so hinkriegen. Aber der Aufwand dafür wächst auch sehr rasch.
Nimm noch eine 3-te Aktion mit dazu, und es wird nicht mehr ohne
massiven Aufwand beherrschbar.
Delay-Lösungen skalieren in dieser Beziehung schlecht.
Eine Umstellung der Denkweise, weg von Zeitdauern und hin zu
Zeitpunkten, realisiert durch einen Timer, ist schon bei 2 Aktionen
einfacher (Beispiel: 2 LED blinken in unterschiedlichen Frequenzen) ohne
dass es dazu erheblichen Mehraufwand im Vergleich zu delay Lösungen
kommt. Und der Aufwand wird dann auch nicht größer, die Methodik
skaliert wesentlich besser mit der Anzahl der 'gleichzeitigen' Aufgaben.
Daher ist es wichtig, diese Technik zu beherrschen. Sie ist nicht
kompliziert und wir benutzen sie im realen Leben ja auch. Kein Mensch
bleibt 2 Stunden beim Ofen stehen, um Schweinebraten zu machen. Wir
stellen uns einen Wecker, der alle halbe Stunde klingelt und daran
erinnert, den Braten zu übergiessen. Und in der Zwischenzeit macht man
eben was anderes. Nichts anderes ist die Timerlösung: viele Wecker,
deren Klingeln daran erinnern, dass es Zeit ist eine bestimmte Aktion zu
machen. Nur das man halt die vielen Wecker durch lediglich ein einziges
Uhrwerk realisiert. Aber das ist ja kein Problem.
Der TO hat ein konkretes Problem. Die Loesung mit delay ist einfach und
deckt alle Anforderungen ab. Und sie ist fuer den TO leichter zu
verstehen, als die Timer-Loesung. Deine Fachkenntnis in allen Ehren,
aber manchmal heisst es einfach nur: Problem -> Loesung -> Fertig.
Karl Heinz schrieb:> Daher ist es wichtig, diese Technik zu beherrschen. Sie ist nicht> kompliziert
Ganz konkret zb so
2 LED sollen blinken, wobei die eine LED alle 3 Sekunden umschalten
soll, die andere LED alle 5 Sekunden.
Klar das kann ich mit delays machen, indem ich mir eine Timeline mache,
alle Blinker eintrag, und die Zeiten dazwischen als delay nehme
1
0000000000111111
2
0123456789012345
3
4
LED1 v v v v v v v v
5
|---------------------------
6
LED2 ^ ^ ^ ^
7
8
| |
9
+--------------+
10
Periode
11
nach der sich alles
12
wiederholt
aus der Timeline kann man ablesen, das man nach 15 Sekunden wieder im
Urzustand angelangt ist und sich ab da die Delay-Zeiten wiederholen
werden. Die Delays an denen Aktionen notwendig sind, kann man aus der
Timeline erhalten
1
bei 0 beide umschalten
2
bei 3 LED1 umschalten
3
bei 5 LED2 umschalten
4
bei 6 LED1 umschalten
5
bei 9 LED1 umschalten
6
bei 10 LED2 umschalten
7
bei 12 LED1 umschalten
8
bei 15 beide umschalten - weiter gehts wie nach 0
daraus ergeben sich die delays zwischen den Aktionen, indem man die
Differenzen zwischen den Zeitpunkten nimmt:
1
do
2
beide umschalten
3
delay 3
4
Led1 umschalten
5
delay 2
6
Led2 umschalten
7
delay 1
8
Led1 umschalten
9
delay 3
10
Led1 umschalten
11
delay 1
12
Led2 umschalten
13
delay 2
14
Led1 umschalten
15
delay 3
16
loop
das ist eine Delay-Lösung, die genau das geforderte macht. Die LED
blinken mit den vorgegebenen Zeiten
Aber der Aufwand, musst du selbst zugeben, war schon enorm. Ändere die 5
auf 7 und der Aufwand geht wieder von vorne los.
Die andere Annahme war, dass die Aktionen vergleichsweise wenig Zeit
benötigen. Das Umschalten von Led fällt da zweifellos darunter. Aber
nimm einfach nur mal an, dass die Umschaltung der Led2 aus irgendeinem
Grund selbst 0.1 Sekunden brauchen würde. Spätestens jetzt wird das
ganze ekelhaft.
Wie macht man das mit einer Timerlösung?
So:
Das ist das Grundgerüst
1
Config Timer0 = Timer , Prescale = 8
2
On Timer0 OnTimerOverflow
3
4
Enable Timer0
5
Enable Interrupts
6
7
do
8
.....
9
Loop
10
11
12
OnTimerOverflow:
13
...
14
return
Ich geh mal von 1Mhz Taktfrequenz aus. Den Vorteiler hab ich auf 8
gesetzt, damit wird die OnTimerOverflow Funktion über den Daumen gepeilt
alle 2 Millisekunden aufgerufen. (1 / ( 1000000/8/256 ) = 0.002048). Das
soll für meine Zwecke genau genug sein. (und lässt sich mit einfachen
Mitteln auch verbessern - Stichwort CTC Modus, aber lass mich das mal
ignorieren und einfach mal die 2 Millisekunden als gegeben annehmen)
Für jede LED führe ich einen 'Wecker' ein. Das ist einfach nur ein
Zähler, der von einer Start-'Zeit' runterzählt und wenn er bei 0 ist,
dann 'klingelt' er und stellt die LED um. Bei 2 Millisekunden
Basisticken bedeutet das, das der Wecker für Led1 von 1500 auf 0 zählen
muss, der für Led2 macht dasselbe mit einem Startwert von 2500
d.h. für Led1 gibt es eine Variable
1
DIM TimeLed1 as Integer
und in meinem 'Uhrwerk', zählt der (diesmal in Richtung 0, also
Countdown)
1
OnTimerOverflow:
2
3
TimeLed1 = TimeLed1 - 1
4
5
...
6
return
und wenn der 'Wecker abgelaufen ist', schaltet er die Led
1
OnTimerOverflow:
2
3
TimeLed1 = TimeLed1 - 1
4
if TimeLed1 = 0 then
5
toggle LED1
6
TimeLed1 = 1500
7
endif
8
...
9
return
dasselbe nochmal für Led2 und 2500 statt der 1500.
d.h.
das Programm sieht so aus
1
DIM TimeLed1 as Integer
2
DIM TimeLed2 as Integer
3
4
Config Timer0 = Timer , Prescale = 8
5
On Timer0 OnTimerOverflow
6
7
Enable Timer0
8
Enable Interrupts
9
10
TimeLed1 = 1500 - 1
11
TimeLed2 = 2500 - 1
12
13
do
14
.....
15
Loop
16
17
18
OnTimerOverflow:
19
20
TimeLed1 = TimeLed1 - 1
21
if TimeLed1 = 0 then
22
toggle LED1
23
TimeLed1 = 1500
24
endif
25
26
TimeLed2 = TimeLed2 - 1
27
if TimeLed2 = 0 then
28
toggle LED2
29
TimeLed2 = 2500
30
endif
31
32
return
Ist das komplizierter?
Auf den ersten Blick: Ja, das ist komplizierter.
Aber: Ich kann die 5 Sekunden der LED2 ändern, ohne die komplette
Sequenz für Led1 durcheinander zu bringen. Anstalle der 2500 schreibe
ich einfach 3500 rein (für 7 Sekunden). Sonst ändert sich nichts.
Des weiteren: nimm eine 3.Led mit dazu, die alle 8.4 Sekunden umschalten
soll. Mit der delay-Lösung artet das jetzt schon aus. Denn erst mal
musst du die Zeitachse so lange weiter verfolgen, bis du irgendwo den
Zustand entdeckst, an dem die Umschaltvorgänge aller 3 LED wieder auf 1
Zeitpunkt zusammenfallen. Bei 3, 5 und 8.4 dürfte das nicht so schnell
der Fall sein. Dementscprechend viele einzelne Umschaltvorgänge und
delays dazwischen gibt es dann auch.
Wie ist das bei der Timer Lösung?
Da ist das trivial. Für die 3. Led kommt ein weiterer Wecker dazu (1
Variable mehr), in die ISR kommt ein weiterer Fall für die 3.te LED
rein, ich rechne mir noch aus, dass 8.4 Sekunden 4200 Aufrufen der ISR
entsprechen, und fertig bin ich: eine 3 Aktion ist ins Programm mit
reingekommen, ohne dass ich einen Haufen delays habe überarbeiten müssen
oder sonst irgendwie grossartig viel Aufwand hatte.
Das ist gemeint mit 'skaliert besser'. Kommen zusätzliche Anforderungen
hinzu, dann ist es einfach die mit dazuzunehmen, ohne dass alles
auseinander fällt oder überarbeitet werden muss.
Und Hand aufs Herz: sooooo aufwändig ist der Timer-Ansatz dann auch
wieder nicht. Ja, er ist erst mal mehr Aufwand. Aber nicht so viel mehr.
cybmorg schrieb:> Der TO hat ein konkretes Problem. Die Loesung mit delay ist einfach und> deckt alle Anforderungen ab.
Dann würde ich vorschlagen du liest dir seine Aufgabenstellung noch
einmal aufmerksam durch.
An keiner Stelle sagt er, dass die Brennzeit einer LED bereits
abgelaufen sein soll, wenn ein weiterer Tastendruck die nächste LED
einschaltet.
Patrick Reichhold schrieb:> wie möglich und kann nicht Lange Darauf Warten.
Bei dem Wissensstand würde ich mal die Hoffnung nach einer
schnellen Lösung zumindest infrage stellen. So was kann man
machen wenn man zumindest etwas Erfahrung in der Materie hat.
Klingt zwar nicht sonderlich optimistisch, dafür ist es eher
realistisch.
Wie schauts aus? Läuft die fleischproduktion wieder? :)
Bin auch soeben stundenlang vorm Pc gesesen um mir einen Timer zurech zu
bauen. Meiner läuft! :) Wie schauts bei dir aus?