Hallo, erstmal zum Aufbau: Attiny2313 LEDs Button Ziel: Starten eines Programms durch drücken des Buttons und verlassen der Funktion (und der darin befindlichen Schleife) durch erneutes drücken. Meine Funktion lässt die LEDs in untersch. Reihenfolge aufleuchten und das als Schleife. Die Funktion starte ich indem ich den Button drücke. Aber wie ist es möglich die Funktion wieder durch drücken des Buttons zu verlassen? Mein Ansatz war: while (PIND & (1 << START)) Den Pin D2 habe ich Start genannt. Dieser ist über einen Button an Masse verbunden und wird vom Attiny als Pullup geschaltet. Das ganze funktioniert auch da ich ja meine Funktion durch drücken des Buttons starten kann. Also mit: if(!(PIND & (1 << START))) Hat da jemand einen Tipp ?
:
Bearbeitet durch User
Mario I. schrieb: > Ziel: > Starten eines Programms durch drücken des Buttons und verlassen der > Funktion (und der darin befindlichen Schleife) durch erneutes drücken. Wo liegt denn da das Problem? mfg Klaus
Klaus R. schrieb: > Wo liegt denn da das Problem? Na es funktioniert nicht ? Wie oben geschrieben habe ich es über eine while Schleife versucht deren Bedingung ist das das der Button nicht gedrückt ist: while (PIND & (1 << START)) Das ganze funktioniert aber nicht.. Muss man das anders formulieren oder geht das so "einfach" nicht ?
>drücken des Buttons und verlassen der >Funktion (und der darin befindlichen Schleife) durch erneutes drücken. Erst ne WHILE, um zu warten, bis der Knopf gerückt wurde, dann ne WHILE um zu warten, bis er los gelassen wurde und dann ne WHILE um zu warten, bis er zum zweiten Mal gedrückt wurde. Da Taster prellen, sollte man nach jedem WHILE etwa 50ms warten. Das wäre der einfachste Weg. Etwas komplizierter aber viel viel eleganter und besser wenn das Programm komplexer wird: In einer Task (1ms, 10ms) den Taster abfragen. Zählen zum Entprellen. Flag setzen beim "Drücken" und "Loslassen erkannt". Und dann noch ein Flag für beide Flanken. Ein gutes Programm hat kein WHILE (bzw. nur ein einziges zentrales) und kein DELAY.
Danke aber kannst du das mal als Code schreiben? Kann damit nicht so viel anfangen bin recht neu in dem Thema.. Wär super wenn du das mal als Beispielcode zeigen könntest! Also aktuell hab ich ne While Schleife mit einer if Anweisung. Wenn der Button gedrückt wird ist diese erfüllt und startet meine LED-Funktion die in einer While läuft die beendet werden soll wenn der Button nochmal gedrückt wird.
Mario I. schrieb: > Hat da jemand einen Tipp ? Zeige eine vollständige, auf das Grundproblem reduzierte Version deines Programms
Wolfgang schrieb: > Mario I. schrieb: >> Hat da jemand einen Tipp ? > > Zeige eine vollständige, auf das Grundproblem reduzierte Version deines > Programms hier int main: while(1) { if(!(PIND & (1 << START))) { if(PINB & (1 << PB1)) {Modus1();} //wenn Schieberegler auf Modus1 steht, später kommen noch 4-5 Programme dazu und er führt dann immer das aus auf dem der Schieberegler steht. else{PORTD |= (1 << LEDR);} } drücke ich den button springt es in die Funktion Modus1: while (PIND & (1 << START) || s==5) { PORTA |= (1 << LEDG); PORTD |= (1 << LEDR); _delay_ms(5000); PORTA &= ~(1 << LEDG); PORTD &= ~(1 << LEDR); //der Vorläufer zum Programm das 5 mal wiederholt wird for(s=0; s<5; s++) { //Programmablauf von den LEDs.. }
:
Bearbeitet durch User
Jim M. schrieb: > Mario I. schrieb: >> _delay_ms(5000); > > > Mal probiert den Taster 5 Sekunden lang gedrückt zu halten? Was soll das bringen? Die Passage die du zitierst soll genau das machen..die LEDs für 5 Sekunden anschalten und dann ausschalten. Darauf folgt dann eine Abfolge die sich 5 mal wiederholt. Die 5sek. dienen als eine Art Ankündigung das der Modus gestartet wird.
Von AVR hab ich keinen Plan. Mario I. schrieb: > PIND Was is'n dat, was steht da drin? Sicher das ein Bitweiser Vergleich Not tut? Probier mal einen Logischen Vergleich (&&).
Teo D. schrieb: > Von AVR hab ich keinen Plan. > > Mario I. schrieb: >> PIND > > Was is'n dat, was steht da drin? > Sicher das ein Bitweiser Vergleich Not tut? Probier mal einen Logischen > Vergleich (&&). PinD ist die Pingruppe D und den Pin PD2 hab ich als "Start" definiert. Ich verstehe nicht ganz was du mit dem logischen Vergleich meinst. Worauf beziehst du das auf welchen Teil ? Und was meinst du damit ?
_delay_ms(5000) blockiert 5 lang. In dieser Zeit wird der PIN mit dem Taster nicht abgefragt. Wenn du innerhalb dieser 5s den Taster kurz drückst, bemerkt die Abbruchbedingung der Schleife dies nicht.
Michal schrieb: > _delay_ms(5000) blockiert 5 lang. In dieser Zeit wird der PIN mit dem > Taster nicht abgefragt. Wenn du innerhalb dieser 5s den Taster kurz > drückst, bemerkt die Abbruchbedingung der Schleife dies nicht. Ja das hab ich mir auch schon gedacht, aber wie löst man das ? Also wie lass ich die Bedingung Prüfen während die LED für 5 sek aus bleibt?
Teo D. schrieb: > Was is'n dat, was steht da drin? > Sicher das ein Bitweiser Vergleich Not tut? Probier mal einen Logischen > Vergleich (&&). PIND wird ein Register mit 8 Bit sein, dass den Zustand von den 8 IO-Pins am Port D wiederspiegelt. Da ist es schon gut, das Bit/den Pin, an dem der Taster hängt, rauszumaskieren.
Beitrag #5336694 wurde vom Autor gelöscht.
Wolfgang schrieb: > PIND wird ein Register mit 8 Bit sein, dass den Zustand von den 8 > IO-Pins am Port D wiederspiegelt. Da ist es schon gut, das Bit/den Pin, > an dem der Taster hängt, rauszumaskieren. Ojemine, ich sollts lieber gleich ganz lassen. Das dauert aber auch immer länger, bis der Kalk rieselt. :)
Warum nutzt man bei so einer aufgsbe keinen Interrupt? ZB Pin Change Interrupt?
Mario I. schrieb: > Ja das hab ich mir auch schon gedacht, aber wie löst man das ? Also wie > lass ich die Bedingung Prüfen während die LED für 5 sek aus bleibt? Am besten so, wie Quadrat das beschrieben hat: Quadrat schrieb: > In einer Task (1ms, 10ms) den Taster abfragen. Zählen zum Entprellen. > Flag setzen beim "Drücken" und "Loslassen erkannt". Und dann noch ein > Flag für beide Flanken Einen task könnte man mit einem Timerinterrupt erzeugen, der alle 10ms ein Interruptroutine aufruft. Falls dir das nichts sagt, könntest du zunächst probieren, eine LED gesteuert von einem interrupt blinken zu lassen. Beispiele dafür gibt es im Netz oder vielleicht auch im Kurs auf mikrocontroller.net
Michal schrieb: > Einen task könnte man mit einem Timerinterrupt erzeugen, der alle 10ms > ein Interruptroutine aufruft. Läuft dann das delay() trotzdem noch sauber weiter?
duck&wech schrieb: > Läuft dann das delay() trotzdem noch sauber weiter? Klar, ist aber Ressourcen Verschwendung, wenn man eh schon einen Timer-Tick (Flag) hat. While(pause - TimmerTick) TimmerTick=0; Geschickt programmiert, sind damit aber Pausen, die das Programm anhalten, dann nicht mehr nötig.
Soooo..damit Leute die das selbe suchen wie ich nicht dumm sterben: Das ganze wurde von mir jetzt mit einem Interrupt gelöst. Da ich nicht wusste was das ist konnte ich ja schlecht danach suchen..nach dem Hinweis hier hab ichs dann mal gesucht und bin auf ein lehrreiches YT Video gestoßen: https://youtu.be/vl5H_Q1slYY Für den Attiny2313 muss das aber so aussehen -> In der Main den Taster (der am Pin PD2 (INT0) hängt) so definieren: DDRD &= ~(1 << PD2); PORTD |= (1 << PD2); In der Funktion die unterbrochen werden soll muss folgendes stehen: GIMSK = (1<<INT0); //Eingang INT0 als Interrupt definieren sei(); // das muss auch darunter.. Dann muss eine Funktion erstellt werden in die das Programm beim Interrupt durch den Taster springt: ISR(INT0_vect) { // Hier kann man dann zb die Hauptfunktion aufrufen das er wieder auf Anfang springt..oder was man da eben ausführen will.. } ACHTUNG: Schreibt man das jetzt einfach so hin wie ich dann ist das Programm schneller als man den Taster wieder loslassen kann und das Programm "spinnt". Hier hab ich dann mit dem delay Befehl gearbeitet um den Taster zu entprellen. Also einfach in der interrupt Funktion ein kurzes Delay von 300ms einbauen und es sollte genügen. Das man das ganze profesioneller lösen kann kann ich mir denken. Für mich funktioniert die Lösung aber sehr sehr gut da mein Programm alles andere als komplex ist. Vielen Dank an die die mir hier geholfen haben und mich darauf gestoßen haben!
:
Bearbeitet durch User
Mario I. schrieb: > Hier hab ich dann mit dem delay Befehl gearbeitet um > den Taster zu entprellen. Also einfach in der interrupt Funktion ein > kurzes Delay von 300ms einbauen und es sollte genügen. Wenn du dich jetzt noch mit Timer beschäftigst, kannst du das/die Delays auch rausschmeißen. zB: Den durch den Taster ausgelösten Interrupt 300ms sperren, anstatt das Programm zu stoppen. Oder statt eines Pin-Interrupt regelmäßig (zB.300ms wie du gerade wartest) pollen, einlesen -> Nennt sich Polling. :) https://de.wikipedia.org/wiki/Polling_(Informatik)
Schau dir mal das Standard-Werk an - die "Peter Dannegger-Methode" ist (nahezu :-)) unbestritten. https://www.mikrocontroller.net/articles/Entprellung
Dieter F. schrieb: > Schau dir mal das Standard-Werk an - die "Peter Dannegger-Methode" ist > (nahezu :-)) unbestritten. Wer bestreitet da was? Was gibts da zu bekritteln? (Außer ein paar nicht zu beseitigende Missverständnissen, bei der Kommunikation:) "Der hats drauf" würde man da nur sagen.
Dieter F. schrieb: > Schau dir mal die Threads dazu an - dann weisst Du es :) Muss ich glaube nicht, hab mir schon gedacht, das da seine Empfindlichkeit herrührt. :(
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.