Hallo zusammen.
Ich habe nun Urlaub und somit ist mir eine Idee gekommen, um die Zeit
auch "sinnvoll" zu nutzen :)
Ich habe mit einen ATmega8 eine kleine Schaltung mit 3 LEDs aufgebaut,
die ich auch einwandfrei einzeln ansteuern kann. Nun kamen heute Abend
Taster hinzu, die folgendes bewirken sollen:
Für meine Modelleisenbahn habe ich einen Weihnachtsbaum in der
Landschaft aufgestellt, der mittels eines ATmega8 angesteuert werden
soll.
Dafür habe ich 4 Taster, die für jeweils einen anderen "Blinkintervall"
ausgelegt werden sollen. Eine fünfte Taste soll den Blinkrhythmus
komplett ausschalten ("reseten").
Bsp.:
Blink-Rhythmus 1) an (3 sec.) aus (1 sec.)
Blink-Rhythmus 2) an (1 sec.) aus (5 sec.)
Blink-Rhythmus 3) an (10 sec.) aus (5 sec.)
Blink-Rhythmus 4) ...
Nun gibt es aus meiner Sicht einige Fragen.
Zunächst dachte ich mir, die einzelnen Taster einfach an "die vielen"
Interrupt-Eingänge zu hängen. Denn die würden ja darauf lauern, dass
jemand eine Taste betätigt und daraufhin die jeweilige Funktion
aufrufen.
Nun hat aber der Atmega8 nur zwei Interrupt-Eingänge.
Dann versuchte ich, in einer while-Schleife die einzelnen Pins (Taster)
abzufragen, a la:
1
...
2
while(1)
3
{
4
if(PINC&(1<<PINC0)){show_rhythmus_1();}
5
if(PINC&(1<<PINC1)){show_rhythmus_2();}
6
...
7
}
Dabei wusste ich wiederum nicht, wie ich diese am einfachsten
softwaremäßig entprellen könnte UND einen "neuen" Tastendruck wahrnehme,
während ich in einer anderen Rhythmusfunktion bin.
(z.B. drücke ich anfangs Taste-1 für Rythmus-1. Während die Funktions
für Rhythmus-1 aufgerufen wird, könnte ja die nächste Taste gedrückt
werden und die Anforderung "Rhythmus-2" kommen).
Ich habe im Tutorial hier dankend bereits die Entprellroutinen gefunden.
Diese werde ich austesten. Allerdings zweifle ich derweil noch an meiner
"Architektur".
Könntet ihr mir helfen, dieses triviale Projekt umzusetzen?
Vielen lieben Dank und ein frohes Fest,
Johann!
Achja immer wieder die "Schnellstarter" :-P
Tu Dir einen Gefallen und lese hier einfach alle AVR Tutorials durch und
auch die FAQ von Karl-Heinz.
Dann und ERST dann wenn Du damit nicht weiter kommst stelle
Verständnisfragen dazu.
Taster werden NICHT via IRQ ausgewertet, sondern gepollt und entprellt.
Zeitvorgaben werden via TIMER erledigt und zwar in einem IRQ der Dir die
Zeit hochzählt.
Hi!
>Taster werden NICHT via IRQ ausgewertet, sondern gepollt und entprellt.
Ok, das weiß ich. Polling wäre ja wie in meinem Beispiel beschrieben
eine Schleife, in der nacheinander immer wieder die einzelnen Zustände
der Eingänge des AVRs abgefragt wird.
Wie der Timer funktioniert weiß ich.
Mein größtes Verständnisproblem liegt darin, dass ich nicht weiß, wie
man aus Unterprogramm-1 in Unterprogramm-2 springt, wenn z.b. von
Rhythmus-1 in Rhythmus-2 gesprungen werden soll.
Das gleiche Szenario eben auch "von Rhythmus-X auf alle LEDs
ausschalten".
Sobald eine Taste gedrückt wurde, verharre ich doch bis zur
Unendlichkeit in dieser Funktion und bekomme weitere Tastendrücke nicht
mit?!
Gruß
Für deine Anforderung brauchst du doch weder (externen)Interrupt noch
Entprellung.
Du machst einfach einen Timer Interrupt der alle 100ms(oder 10ms)
in der IRQ Routine abfragt welche Taste gedrückt ist,
bei Taste 1 setzt du ein TastenFlag auf 1, bei Taste 2 auf 2, usw
wenn keine Taste gedrückt ist machst du nichts.
Und im Programm lässt du dann je nach Flaginhalt entsprechend warten.
Ist zwar Quick&Dirty aber wenn das Programm nichts anderes machen soll
dann reicht das doch.
Johann schrieb:> Hi!>>>Taster werden NICHT via IRQ ausgewertet, sondern gepollt und entprellt.>> Ok, das weiß ich. Polling wäre ja wie in meinem Beispiel beschrieben> eine Schleife, in der nacheinander immer wieder die einzelnen Zustände> der Eingänge des AVRs abgefragt wird.>
Ja und PeDa hat hier eine sehr mächtige Entprellroutine eingestellt die
keine Wünsche übrig läßt.
Einfach mal danach suchen.
> Wie der Timer funktioniert weiß ich.>
Das heißt Du kannst die Sekunden ausgeben ?
> Mein größtes Verständnisproblem liegt darin, dass ich nicht weiß, wie> man aus Unterprogramm-1 in Unterprogramm-2 springt, wenn z.b. von> Rhythmus-1 in Rhythmus-2 gesprungen werden soll.>
Was Du haben willst ist eine Statemachine, das macht man i.d.R. mit
einer globalen Variable die den aktuellen Zustand definiert und dann im
Hauptprogramm mittels switch/case umgestellt wird.
Wenn Du allerdings noch nicht weißt wie Funktionen in C programmiert
werden solltest Du erstmal ein C Buch hernehmen und Dich durcharbeiten.
> Das gleiche Szenario eben auch "von Rhythmus-X auf alle LEDs> ausschalten".> Sobald eine Taste gedrückt wurde, verharre ich doch bis zur> Unendlichkeit in dieser Funktion und bekomme weitere Tastendrücke nicht> mit?!
Deswegen Statemachine, Du mußt von einem Zustand zum nächsten wechseln.
Nimm Dir ein Blatt Papier und male Dir alle für Dein Projekt relevanten
Zustände auf und zeichne dann Pfeile ein die die Zustände wechseln und
an die Pfeile schreibst Du die Übergangsbedingung.
In C macht man sowas üblicherweise so:
>Du machst einfach einen Timer Interrupt der alle 100ms(oder 10ms)
Ok. Das ist eine gute Idee! Danke!
>Das heißt Du kannst die Sekunden ausgeben ?
Ja, über den Prescaler heruntergeteilt komme ich genau auf eine Sekunde
(habe damit eine LED blinken lassen).
>Wenn Du allerdings noch nicht weißt wie Funktionen in C programmiert werden
Doch, das weiß ich! :)
>Verstehst Du was das Programm macht ?
Aus meiner Sicht wird der Reihe nach jede case-Anweisung "gepolt".
Johann schrieb:>>>Verstehst Du was das Programm macht ?> Aus meiner Sicht wird der Reihe nach jede case-Anweisung "gepolt".
Was meinst Du mit "gepolt" ?
Hast Du mal Deine ganzen Zustände wenigstens aufgeschrieben ?
Wie wertest Du Deine Taster aktuell aus, wenn sie nicht entprellt sind ?
Wie ist der Zusammenhang Deiner Zustände mit den Tastern ?
Was ist Dein Startzustand ?
So und nu überlege mal ;-)
Johann schrieb:> Habe nun mal eine Skizze angefertigt.>> Aber wirklich helfen tut mir das auch nicht :-(
Dann schreibe mal die im Bild zu sehenden einzelnen Zustände in einer
Liste auf.
Überlege Dir welcher Zustand in welchen übergehen soll und was die
Bedingung dazu ist (d.h. Du hast an die Pfeile noch nichts geschrieben
...).
Außerdem hast Du das Prinzip noch nicht ganz verstanden, lies mal das
hier durch:
http://de.wikipedia.org/wiki/Endlicher_Automat
Kleiner Tipp wofür ist denn Dein RESET Knopf gedacht, welcher Zustand
soll damit erreicht werden ?
Na klingelt's ?
>wofür ist denn Dein RESET Knopf gedacht
Der ist dazu da, den momentanen State (welcher es auch immer sein mag)
zu unterbrechen und alle LEDs auszuschalten.
Den endlichen Automaten habe ich von Wiki als eine Hilfe hergenommen.
>Na klingelt's ?
NEIN. Sonst hätte ich hier nicht gefragt.
Johann schrieb:>>wofür ist denn Dein RESET Knopf gedacht>> Der ist dazu da, den momentanen State (welcher es auch immer sein mag)> zu unterbrechen und alle LEDs auszuschalten.> Den endlichen Automaten habe ich von Wiki als eine Hilfe hergenommen.>>>Na klingelt's ?>> NEIN. Sonst hätte ich hier nicht gefragt.
Schwere Geburt, was ist also Dein Grundzustand ?
Johann schrieb:> Mein Grundzustand ist reset? ;)
Nein das ist Dein Übergang !
Wieviele einzelne FSM hast Du insgesamt ?
Schau mal in Deine Zeichnung was fällt Dir dabei auf ?
Vergleiche die mal mit den Beispielen aus dem WiKi ...
Also.
>kopfkratzer=quälmeister
Könnte sich vielleicht jemand bemühen, mir zu helfen?
Ich weiß nicht mehr darüber als ich geschrieben habe.
Schließlich ist das Forum ja nicht da, um jemanden ständig zu eröffnen,
wie dumm er doch eigentlich ist.
Hallo zusammen.
Habe nun noch folgendes programmiert, aber irgendwie tut das nicht was
es soll.
Könntet ihr mir helfen?
Ich habe nun einen Timer (Timer0), der alle x ms den Zustand der Taster
erfragt und die globale Variable "Taster" entsprechend mit einem Wert
beschreibt.
In der Endlosschleife in main() wird dann entsprechend ausgewertet,
welcher Taster gedrückt wurde und letztlich das "Blinkmuster"
aufgerufen.
Hier der Code:
kopftisch
Was steht in diesem Post was Du erstmal tun solltest:
Beitrag "Re: Weihnachts-Blinklicht - AVR"
Letzter Versuch:
1. Welches Schlüsselwort braucht eine Variable die in einer IRQ
verändert wird ?
2. Wie werden Tasten entprellt und wo/wie sollte das geschehen ?
3. Wofür ist der Timer da ?
Geh erstmal hin und lasse EINE LED mit hilfe eines Timers im
Sekundentakt blinken OHNE delay !
Wenn das dann geht erweiterst Du das Programm um EINEN Taster der
erstmal nur die blinkende LED an- und ausschaltet.
Hallo Johann,
wie wäre es denn, wenn du dir die vier Schalter nimmst und jeden an
einen normalen Port anschließt. Desweitern schließt du an jeden Schalter
eine Diode an und verbindest dann die Dioden. Diese verbundenen Dioden
schließt du dann an einen Interupteingang an. Wenn nun irgendeiner der
Schalter gedrückt wird wird der Interrupt aktiviert. In der
Interruptroutine schaust du dann, welcher der vier anderen Ports, an
denen je einer deiner Schalter hängt, seinen Zustand auf high geändert
hat.
MfG Maximilian
>1. Welches Schlüsselwort braucht eine Variable die in einer IRQ>verändert wird ?
volatile
>2. Wie werden Tasten entprellt und wo/wie sollte das geschehen ?
Laut " Chr. Messener" benötigt man hierfür keine Entprellung.
Das hat man mir zumindest so gesagt.
>3. Wofür ist der Timer da ?
Zielst du auf die _delay_ms() ab?
Oder auf den Timer, der die Tastenzustände "überwacht"?
Johann schrieb:> case TASTER_1:
ich kann zwar nur sehr wenig c, aber sollte hier dann nicht stehen:
case 1:
Die "Taster" Variable wird in deinem Programm wohl nie den Wert "PINC1"
enthalten.
>Die "Taster" Variable wird in deinem Programm wohl nie den Wert "PINC1"
enthalten
Wenn Taster_1 gedrückt wird (entspricht PINC1), dann wird anhand der
ISR() der Wert der Variablen Taster auf 1 gesetzt, oder?
Die defines sind ja nur alias. Anstelle von PINC1 schreibe ich im
weiteren Code "Taster_1" um -im Falle einer Pinänderung- nur die Define
ändern zu müssen.
Chr. Messener schrieb:> Johann schrieb:>> case TASTER_1:>> ich kann zwar nur sehr wenig c, aber sollte hier dann nicht stehen:> case 1:
Ja, oder besser
Johann schrieb:> wird anhand der> ISR() der Wert der Variablen Taster auf 1 gesetzt, oder?
eben, die Variable "Taster" hat dann den Inhalt "1"
Du fragst in der case abfage aber ab ob die Variable
den Inhalt "TASTER_1" hat.
Und durch das #define hast du dem Compiler die Anweisung gegeben
alle "TASTER_1" durch "PINC1" zu ersetzen.
Also fragst du in der case "hat die Variable Taster den Inhalt PINC1?
dann mach ..."
Du musst aber fragen "hat die Variable Taster den Inhalt 1? dann mach
..."
Zum enprellen: wenn der Taster hier prellt macht das nichts,
weil wenn gerade im gedrückt Zustand abgefragt wird dann setzt
es den richtigen Wert und wenn die IRQ-Routine gerade das "nicht
gedrückt prellen" erwischt dann passiert halt nichts.
Wenn oft genug abgefagt wird ist die Chance den gedückt Zustand zu
verpassen doch recht klein, und wenn die Variable mehrmals auf den
gleichen Wert gesetzt wird ist das auch egal.
Wie sieht denn deine Schaltung aus? Hast du irgendwo Pullup- oder
Pulldown-Widerstände? Die internen benutzt du ja nicht - oder kann ich
nicht gucken? Wenn du die internen Pullup's benutzt, musst du die Taster
natürlich auf logisch '0' prüfen. Ansonsten wurde ja schon alles
(vieles) gesagt..
Siehe "case: 1:"
-Dirk-
Hallo zusammen.
Hier möchte ich euch noch meine Schaltung schicken, so wie ich es
aufgebaut habe.
Das Relais (rechts) schaltet den Verbraucher (in meinem Fall eine
Glühlampe). Habe das Lampensymbol nicht gefunden, deshalb ein
Lautsprecher ;-)
Stimmt die Schaltung denn überhaupt so? Nicht dass ich bereits darin
einen Fehler habe?!
Danke und Gruß
- Das 5V-Relais K1 darf nicht in Serie mit der LED1 und dem
Vorwiderstand R3 sein. Der Strom wird zu klein sein für das Relais. Das
Relais muss parallel mit der LED1 und Vorwiderstand sein und dann
gemeinsam zum Transistor.
- Der Basiswiderstand R2 muss kleiner für sein (330 - 1k) damit der
BC548 gut durchschaltet.
- Für die Eingänge der Taster S1 -S5 müssen Pullup-Widerstände eingebaut
oder im ATmega eingschalten werden.
- Der 7805L ist zu klein. Vorallem weil auch noch das Realais daran
hängt. Nimm ein 7805 im T220, sonst wird der zu heiss.
Und poste doch nochmal (aber als Anhang ) den letzten compilierbaren
Code.
Hallo Markus,
danke für deine Hilfe!
>Das 5V-Relais K1 darf nicht in Serie mit der LED1 und dem>Vorwiderstand R3 sein
Ich habe nun die LED mit Vorwiderstand aus der Schaltung entfernt.
-War eine Schnapsidee von mir.
>Der Basiswiderstand R2 muss kleiner für sein (330 - 1k)
Ich habe ihn nun auf 330 Ohm in der Schaltung abgeändert
>Für die Eingänge der Taster S1 -S5 müssen Pullup-Widerstände eingebaut>oder im ATmega eingschalten werden
Ich habe im Code die internen Pullups des ATmega8 eingeschaltet.
>Nimm ein 7805 im T220
Ok, werde ich mir besorgen.
Der abgeänderte Schaltplan und der compilierbare Code ist im Anhang.
Könntest du nochmal einen Blick auf beides werfen?
Vielen Dank schon mal! :-)
Gruß
Johann
Johann schrieb:>>Nimm ein 7805 im T220> Ok, werde ich mir besorgen.
Sollte TO-220 heissen, sorry.
Johann schrieb:> Ich habe nun die LED mit Vorwiderstand aus der Schaltung entfernt.
Schalte die LED ruhig dazu parallel, so siehst du was genau passiert:
Und deine Status LEDs kanns du auch gleich noch einschalten, so siehst
du in welchem Mode du dich befindest.
Das
1
#define F_CPU 8000000
noch vor die Includes verschieben.
Deine Taster werden auf High-Pegel (1) abgefragt.
Sie sind aber LOW-Aktiv, d.h. du musst sie überprüfen ob sie == 0 sind.
(Und nur um die Taster so abzufragen, braucht es die ISR eigentlich
nicht, weil mit dem Delays alles blockiert wird. Die Überprüfung könnte
genauso gut im Main-Loop stattfinden. Der Timer-ISR wäre anstelle des
Delay sinnvoll. Aber lass das erst mal. Das wäre das nächste Projekt
Blinkschaltung mit Timer.)
Ok vielen Dank! :)
Habe nun noch den Schaltplan entsprechend abgeändert (Kollektor -> LED)
und die Status-LEDs programmiert.
Im Anhang noch mal der kompilierbare Code und der Schaltplan.
Jetzt müsste es doch stimmen, oder? :)
Danke Dir!