Forum: Mikrocontroller und Digitale Elektronik LED nach x Testenschlägen x mal blinken lassen (x = variabel)


von Patrick H. (patrick_h_97) Benutzerseite


Lesenswert?

Hallo,

Gleich zu Anfang. Ich bin neu in der Microcontroller-Welt und stehe noch 
ganz am Anfang. Ich bringe mir die Programmierung von Microcontrollern 
durch lesen und mein Vorwissen in Java und C++ selbst bei.

Zu meinem "Problem". Ich habe einen ATMega 88P Microcontroller, an dem 
eine LED (PD4) und ein Taster (PD2) angeschlossen sind. Ich habe es 
hinbekommen zu programmieren, dass die LED blinkt, wenn ich den Taster 
drücke und, wenn ich den Taster dann wieder los lasse, dass dann die LED 
ebenfalls aus ist.

Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine 
Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und 
daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in 
dem Beispiel 5 mal).

Könnt ihr mir ein paar hilfreiche Tipps geben, mit welchen ich dann auf 
den richtigen Pfad komme?

Hier mal den Code, den ich geschrieben habe, dass das blinken auf den 
Tastenhalt reagiert:
1
int main(void)
2
{
3
  gpio_initGpio();
4
  
5
    while(1)
6
    {
7
    if(PIND & 0x8)
8
    {
9
      PORTD |= (1 << PD4); // port D4 setzen
10
    }
11
    else
12
    {
13
      PORTD |= (1 << PD4); // port D4 setzen 
14
      wait(65535);
15
      PORTD &= ~(1 << PD4); // port D4 loeschen
16
      wait(65535);  
17
    }
18
    }
19
}

Vielen Dank schonmal im Voraus
P. Herbst

von georg (Gast)


Lesenswert?

Patrick H. schrieb:
> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine
> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und
> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde

Die Beschreibung ist unvollständig oder unlogisch und kann daher nicht 
programmiert werden: woher soll der arme Controller denn wissen, dass 
nicht noch Tastendrücke folgen?

Du kannst natürlich nach jedem Tastendruck die LED 1mal blinken lassen, 
dann stimmt die Zahl - aber das ist trivial und wohl nicht das was du 
dir gedacht hast.

Georg

von Holger L. (max5v)


Lesenswert?

Du könntest nach dem ersten detektierten Tastendruck einen Timer bzw. 
den Watchdog starten, der nach x Zeit z.B. einer Sekunde das Ende der 
Eingabe festlegt.
Allerdings wirst du dich dafür noch mit Tastenentprellung auseinander 
setzen müssen da es sonnst zu Fehlern kommt.

Taste betätigt ->
Timer \ Watchdog starten ->
Taste innerhalb einer Sekunde betätigt ->
Timer \ Watchdog zurücksetzen ->
Taste innerhalb einer Sekunde nicht betätigt ->
Blinken ausführen.

P.S. : Die  "wait(65535);" Funktion sieht ein wenig merkwürdig aus ?!

von Georg M. (g_m)


Lesenswert?

Patrick H. schrieb:
> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine
> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und
> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in
> dem Beispiel 5 mal).

Wenn der Taster entprellt ist, kann das Programm die Anzahl der 
Tastendrücke in einer Variablen speichern und fürs Blinken benutzen. 
Aber wait/delay können in diesem Programm nicht mehr benutzt werden.

von Andreas B. (bitverdreher)


Lesenswert?

Hi,
Du machst die Tastatureingabe mit dem Code von Peter Danneger in einem 
Interrupt. Dort zählst Du die Tastendrücke in einer Variable x.
Im Hauptprogramm kannnst Du die LED blinken lassen, indem Du in einer 
Endlosschleife diese Variable x abfragst: Ist diese Null, dann tust Du 
nichts. Größer Null läßt einmal blinken und zählt die Variable x 
herunter.

Hauptschleife:

While (1){
  if (x>0) {
    LEDON;
    Wait(500);
    LEDOFF;
    Wait(500);
    x--;
  }
}

von MaWin (Gast)


Lesenswert?

Patrick H. schrieb:
> Zu meinem "Problem

Du hast keine Ahnung von Logik.

Wenn die LED an ist wenn man den Taster niederdrückt und aus ist wenn 
man ihn loslässt (braucht man keinen uC) leuchtete die LED genau so oft 
wie man den Taster drückte, dein Problem ist also schon gelöst.

Wenn du jedoch meintest, du drückst innerhalb einer Zeitspanne von sagen 
wir 10 Sekunden den Taster 1 bis 100 mal, dann soll nach dem Ablauf der 
10 Sekunden die LED ebenso oft an und aus gehen, z.B. mit einem Zeittakt 
von 0.5 Sekunden, dann ist dad eine ganz andere Aufgabenstellung.

Kaum denkt man selber richtig, löst sich ein Problem von alleine.

von Gerald B. (gerald_b)


Lesenswert?

Kann man auch mit einem up/down Counter, wie z.B. dem 74(HC)193 
realisieren. Den (entprellten) Taster zum Befüllen des Zählers nutzen 
und sowie ein Zählerstand ungleich Null erkannt wird, wird ein 
Logikgatter freigegeben, das den Takt zum Abwärtszählen liefert. Bei 
Null stoppt sich das Konstrukt dann von selber.
Wenn mehr als 15 Impulse zu erwarten sind, dann 2 Zähler kaskadieren.
Der freigegebene Takt zum Abwärtszählen steuert gleichzeitig die Lampe 
an ;-)

von Peter D. (peda)


Lesenswert?

georg schrieb:
> Die Beschreibung ist unvollständig oder unlogisch und kann daher nicht
> programmiert werden: woher soll der arme Controller denn wissen, dass
> nicht noch Tastendrücke folgen?

Muß er auch nicht.
Er fängt einfach das Blinken an, sobald der Zähler >0 ist.

von Rolf M. (rmagnus)


Lesenswert?

MaWin schrieb:
> Patrick H. schrieb:
>> Zu meinem "Problem
>
> Du hast keine Ahnung von Logik.

Vielleicht hast du es auch nur nicht richtig gelesen?

> Wenn du jedoch meintest, du drückst innerhalb einer Zeitspanne von sagen
> wir 10 Sekunden den Taster 1 bis 100 mal, dann soll nach dem Ablauf der
> 10 Sekunden die LED ebenso oft an und aus gehen, z.B. mit einem Zeittakt
> von 0.5 Sekunden, dann ist dad eine ganz andere Aufgabenstellung.

Also irgendwie lese ich (abgesehen von den von dir eingefügten 
Beispielwerten) genau das aus folgenden Abschnitt:

Patrick H. schrieb:
> Jetzt würde ich gerne realisieren, dass sich der Microcontroller meine
> Tastendrücke merkt und zusammenaddiert (z.B. 5 Tastenschläge). Und
> daraufhin soll die LED sooft blinken, wie der Taster gedrückt wurde (in
> dem Beispiel 5 mal).

Der µC soll sich also zuerst merken, wieviele Tastendrücke kamen, und 
dann die LED so oft blinken lassen. Und nicht:

MaWin schrieb:
> Wenn die LED an ist wenn man den Taster niederdrückt und aus ist wenn
> man ihn loslässt (braucht man keinen uC) leuchtete die LED genau so oft
> wie man den Taster drückte, dein Problem ist also schon gelöst.

: Bearbeitet durch User
von Paper (Gast)


Lesenswert?

Blatt Papier Bleistfit, PAP oder Strukturgramm.

Kennt das keiner mehr?

von Lothar M. (Firma: Titel) (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Rolf M. schrieb:
> Vielleicht hast du es auch nur nicht richtig gelesen?
Ja, Ratestunde. Oder andersrum: ohne eine definierte Aufgabenstellung 
(am besten mit einem Timingdiagramm, das mehrere Beispiele enthält) ist 
jeder Vorschlag gleich gültig.

Patrick H. schrieb:
> Ich bringe mir die Programmierung von Microcontrollern durch lesen und
> mein Vorwissen in Java und C++ selbst bei.
Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn 
die blockieren den uC und verhindern, dass du mehrere Sachen "parallel" 
machen kannst. Am Vorhandensein solcher 
Verzögerungen/Rechenzeitvernichter erkennt man ein schlechtes Programm.

von Rolf M. (rmagnus)


Lesenswert?

Lothar M. schrieb:
> Rolf M. schrieb:
>> Vielleicht hast du es auch nur nicht richtig gelesen?
> Ja, Ratestunde. Oder andersrum: ohne eine definierte Aufgabenstellung
> (am besten mit einem Timingdiagramm, das mehrere Beispiele enthält) ist
> jeder Vorschlag gleich gültig.

Soll er gleich noch ein 50-seitiges Lastenheft schreiben, um hier eine 
Frage stellen zu dürfen? Ich finde die Frage hinreichend klar.

> Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn
> die blockieren den uC und verhindern, dass du mehrere Sachen "parallel"
> machen kannst. Am Vorhandensein solcher Verzögerungen/Rechenzeitvernichter > 
erkennt man ein schlechtes Programm.

Prinzipiell ja, aber für die ersten "Gehversuche" ist es ok. Interrupts 
und Timer müssen nicht unbedingt die allerersten Dinge sein, mit denen 
man sich beim Erlernen der Grundlagen der µC-Programmierung beschäftigt. 
Ein bischen "Pinwackeln" geht auch noch mit Delays.

von pegel (Gast)


Lesenswert?

Für diesen Fall bietet sich ein Timer Interrupt aber wirklich an.
Z.B. 10ms Timer.
Darin lassen sich durch einfache Variablen und if Abfragen sowohl die 
Tastenentprellung, Zählung der Tastendrücke und auch Leuchtdauer der LED 
durch Nachdenken realisieren.

von Andreas B. (bitverdreher)


Lesenswert?

Rolf M. schrieb:
>> Dann vergiss schnellstmöglich diese wait() oder delay() Funktionen. Denn
>> die blockieren den uC und verhindern, dass du mehrere Sachen "parallel"
>> machen kannst. Am Vorhandensein solcher Verzögerungen/Rechenzeitvernichter >
> erkennt man ein schlechtes Programm.
>
> Prinzipiell ja, aber für die ersten "Gehversuche" ist es ok. Interrupts
> und Timer müssen nicht unbedingt die allerersten Dinge sein, mit denen
> man sich beim Erlernen der Grundlagen der µC-Programmierung beschäftigt.
> Ein bischen "Pinwackeln" geht auch noch mit Delays.

Daher habe ich die LED in meinem Beispiel auch mit wait (bzw. Delay) 
blinken lassen damit es für den Anfang etwas einfacher wird.Nächster 
Schritt wäre dann ein Blinken mittels extra Timer. Wenn das klappt, das 
Blinken in den Timer für die Tastaturabfrage mit reinpacken.

Ganz ohne Timer geht es für dieses Beipiel auch nicht. Dafür braucht er 
die Tastenentprellung von Peter D. nur hier aus dem Forum abzupinseln.

Also ehrlich gesagt, so unverständlich war die Anforderung des TO 
wirklich nicht. Fals er es doch nicht sofort blinken lassen will, 
sondern erst auf den letzten Tastendruck warten will, dann muß 
allerdings noch definiert werden wie lange er auf den letzten 
Tastendruck warten soll. Das kann man dann immer noch einbauen.
Also: Schöne Programmierübung. Mehr soll es vermutlich auch nicht sein.

von Patrick H. (patrick_h_97) Benutzerseite


Lesenswert?

Vielen Dank für eure hilfreichen Ansätze, damit kann ich auf jeden Fall 
weiterversuchen.

Andreas B. schrieb:
> Also: Schöne Programmierübung. Mehr soll es vermutlich auch nicht sein.

Genau das soll es sein.

von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

Andreas B. schrieb:
> Ganz ohne Timer geht es für dieses Beipiel auch nicht. Dafür braucht er
> die Tastenentprellung von Peter D. nur hier aus dem Forum abzupinseln.

Doch, geht !

Auch wenn mit Timer und Interrupts das eine bessere Lösung ist, so kann 
das einen Anfänger überfordern.

Im Anhang habe ich mir mal den Spaß gegönnt wie man die 
"Aufgabenstellung" ohne Timer und Interrupt codieren kann.

Prinzipiell sollte man den funktionalen Teilen wie Taster und LEDs (und 
später andere angeschlossene Hardware) Namen vergeben und im Programm 
mit diesen Namen arbeiten.

Das angehängte Beispielprogramm ist absichtlich "zu ausführlich" 
kommentiert, vllt. wollen andere Anfänger auch daraus lernen.

von Georg M. (g_m)


Lesenswert?

Ralph S. schrieb:
> ohne Timer

Wenn #include <util/delay.h>, dann geht es auf wunderbare Weise 
tatsächlich völlig absolut ohne Timer.

von Ralph S. (jjflash)


Angehängte Dateien:

Lesenswert?

_delay_ms aus delay.h zählt ja nur Prozessortakte (meines Wissens).

prinzipiell hätte man auch so etwas machen können:
1
void delay(uint32_t anz)
2
{
3
  volatile uint32_t i;
4
5
  for (i= 0; i< anz; i++);
6
}

Um sich dann selbst irgendeine Verzögerungszeit zu generieren.

Um es klar zu stellen, ich bin kein Freund und auch kein Feind von 
delay, in vielen Fällen braucht es nicht immer zwingend Timer und 
Interrupt und es ist einfacher etwas mit Verzögerungsschleifen zu 
machen.

Wenn ich zu Beginn meinen Auszubildenden gleich etwas von Interrupts 
erzähle wenn sie gerade erst am Anfang stehen, machen die gleich "zu".

Aber, um den Feinden des delays zu begegnen: Die Version des 
Blinkprogramms mit Interruptbetrieb im Anhang.

(wird vllt. noch überarbeitet und von mir dann als Lehranschauung wohl 
verwendet, von daher Danke an den Threaderöffner)

von Rolf M. (rmagnus)


Lesenswert?

Ralph S. schrieb:
> _delay_ms aus delay.h zählt ja nur Prozessortakte (meines Wissens).

Ja.

> prinzipiell hätte man auch so etwas machen können:
> void delay(uint32_t anz)
> {
>   volatile uint32_t i;
>
>   for (i= 0; i< anz; i++);
> }
>
> Um sich dann selbst irgendeine Verzögerungszeit zu generieren.

Ja, wobei das keinerlei Vorteil gegenüber der Nutzung vorhandener 
Delay-Funktionen hat. Wenn man "irgendeine" Zeit will, reicht es aber. 
Soll's dann einigermaßen genau sein, wird das in C aber schwierig.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.