Hallo! Ich habe hier folgendes Problem, ich hab hier ein µC Board und wenn ein Taster gedrückt wird, soll die Anzahl der Prellungen gemessen werden und am LCD ausgegeben werden. Leider warf uns der Lehrer ins kalte Wasser und ich hab keine Ahnung wie ich da vorgehen muss, hab gerade mal geschafft das Board zu installiern. Nun, wie schaut der Code dazu aus, kann mir jemand helfen? Danke vielmals MFG Elias
Hallo, ein Glück, daß er nur eine µC-Familie und da nur einen einzigen Typ auf der Welt gibt... Gruß aus Berlin Michael
Ungefähr so:
1 | cnt_prell = 0; |
2 | |
3 | while(1) |
4 | {
|
5 | zustand = TASTER_INPUT; |
6 | timeout = 0; |
7 | |
8 | while (zustand == TASTER_INPUT && timeout < 1000) timeout++; |
9 | if (timeout >= 1000) break; |
10 | cnt_prell++; |
11 | |
12 | }
|
Eine Softwarelösung ist die Zweitbeste Möglichkeit, ei-die-weil da in einem Zeitraster gesamplet wird. Besser ist es, das Prellen mit dem Counterinput zu zählen, z.B. auf der pos. Flanke.
Elias wrote: > Hallo! > > Ich habe hier folgendes Problem, ich hab hier ein µC Board und wenn ein > Taster gedrückt wird, soll die Anzahl der Prellungen gemessen werden und > am LCD ausgegeben werden. > Leider warf uns der Lehrer ins kalte Wasser und ich hab keine Ahnung wie > ich da vorgehen muss, hab gerade mal geschafft das Board zu installiern. > Nun, wie schaut der Code dazu aus, kann mir jemand helfen? Überleg dir einfach, was denn Prellen bedeutet. Dann sollte der Rest doch eigentlich klar sein. Wird eine Taste gedrückt, dann zählst du mit, wie oft du einen 1-0 Übergang (oder 0-1, je nachdem wie der Taster angeschlossen ist) detektieren kannst. Fertig. Dein Programm liegt in Lauerstellung und fragt ständig den Port Pin ab. Dies macht es solange, wie am Port Pin eine 1 sichtbar ist. Sobald eine 0 auftaucht, ist die Taste gedrückt worden. Jetzt kann aber das Signal noch eine Zeitliang prellen. Das Signal geht also wieder zurück auf 1, nochmal auf 0, wieder auf 1 und wieder auf 0. Dein Programm untersucht also ständig das Signal um diese Wechsel zu erkennen. Dazu vergleicht es einfach den jetzigen Pin Zustand mit dem Zustand des Pins im letzten Schleifendurchlauf. Sind beide gleich, dann hat kein Wechsel stattgefunden. Sind sie ungleich, dann hat das Eingangssignal gewechselt. Nach 1 Sekunde (beispielsweise, nach 1 Sekunde kann man schon davon ausgehen, dass sich das Signal stabilisiert hat) wird die Anzahl der 1-0 Übergänge ausgegeben. Ob das jetzt 1 Sekunde ist, oder ob das Programm einfach den Port 2000 oder 20000 mal abfrägt, spielt erst mal nicht so sehr die Rolle. Das ganze soll einfach nur eine Zeitsteuerung sein, damit man einen definierten Zeitpunkt hat andem die gemessene Anzahl ausgegeben wird. +-----------------+ v Ja | Pin == 1 ? ----------+ | | Nein, Ein Tastendruck hat begonnen v Zähler = 0 Prellzähler = 0 PinJetzt = 0 | v Ja +----> Pin == PinJetzt ? -------------+ | | Nein | | v Nein | | Pin == 0 ? -----+ | | | Ja | | | v | | | Prellzähler++ | | | | | | | |<-------------+ | | v | | PinJetzt = Pin | | | | | |<---------------------------+ | v | Zähler++ | | | Nein v +----- Zähler == 20000 ? | v Prellzähler ausgeben
Hallo ihr! Danke vielmals für euer interesse und eure Arbeit! Genaue so wie es Karl Heinz geschrieben hat sollte das Programm funktionieren, nur wie mach ich das am besten, wir können im moment nur c#, bei c hat er uns leider ins kalte wasser geworfen...
Elias wrote: > Hallo ihr! > > Danke vielmals für euer interesse und eure Arbeit! > Genaue so wie es Karl Heinz geschrieben hat sollte das Programm > funktionieren, nur wie mach ich das am besten, wir können im moment nur > c#, bei c hat er uns leider ins kalte wasser geworfen... Dann wirst du wohl schwimmen lernen müssen. Sorry. Aber du brauchst dazu nur das Wissen darüber, wie man auf deinem Board einen Eingangspin abfrägt. Dazu noch die Grundlagen über Variablen, Vergleiche und wie man Schleifen bildet. Oh, Ausgaben müsste man auch machen können. Und das wars dann schon. Irgendetwas muss euch euer Lehrer gezeigt haben. Zumindest wie man Ausgaben macht bzw. wie man einen Port Pin abfrägt. Und der Rest ist (mit Ausnahme der speziellen Rolle von main()) praktisch identisch zu C#
Schau dir ein paar C-Quellen aus Beispielprojekten an, die du im Internet findest. Dann noch ein Standardwerk zu C aus der Bibliothek und die Datenblätter des Atmega studiert. Dann kann es losgehen...
nein hat er eben nicht, er sagte wir hätten in den ferien genügend zeit uns selbst darum zu kümmern... na dann werden es ja tolle ferien... trotzdem danke
Elias wrote: > nein hat er eben nicht, er sagte wir hätten in den ferien genügend zeit > uns selbst darum zu kümmern... > na dann werden es ja tolle ferien... Gewöhn dich daran. In einem Betrieb hättest du für so eine Aufgabe (neues Board, neue Sprache) nicht viel mehr als 1 Tag Zeit um dir das Wissen zusammenzusuchen und diese Aufgabe zu lösen.
Schau dir fuer den Anfang einfach mal das AVR-(C)-Tutorial an: http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial
PS: Je nachdem wie pingelig euer Lehrer ist, kann man das Ganze auch noch sehr viel einfacher machen. Als Ausgabe reichen u.U schon 8 Led an einem Port an dem man eine Zahl als Binärzahl ausgibt. Und dann macht man ganz einfach ein Programm das mitzählt wie oft eine Taste gedrückt wird. Drückst du jetzt eine Taste, dann zählt die Ausgabe nicht um 1 hoch sondern beispielsweise um 5. Das bedeutet dann, dass neben dem eigentlichen Drücken, die Taste noch 4 mal geprellt hat. Ev. noch ein 2-ter Taster anschliessen, der den Zähler wieder auf 0 setzt und zumindest ich würde das dann schon als korrekte Lösung akzeptieren. Die Abfrage auf Tastendruck an der zu messenden Taste geschieht wieder durch Vergleich der Pegel. Für das 0-Setzen des Zählers würde mit bereits eine ganz normal Pegelerkennung ausreichen.
so, hab mich nun ein bisschen informiert und komm nun zu folgendem code, bringt mir aber im ein fehler bei meiner "messmethode": /*=================================================================== Projekt: Prellzähler Modul: prell.c Autor: xx 17.03.08 ===================================================================*/ //#define F_CPU 4000000UL // Taktfrequenz 4 MHz #include <io.h> #include <interrupt.h> #include <signal.h> //AVRStudio4.12 //#include <sig-avr.h> //AVRStudio3.56 #include <stdlib.h> #include <string.h> #include "LCD_4.h" #include "LCD_4.c" char Text1[]= "***Jueeergen**\0"; //Text1 in Flash-Ram char Text2[]= "**Run \0"; //Text1 in Flash-Ram char Leer[] = " \0"; //Leertext in Flash-Ram char Text[15]; char ADCText[5]; //ADC-Ergebnis char Null[] = {0x00}; char Zeichen, i; char *ZText; unsigned char x; unsigned int hui; #define i 0; #define counter 0; int main(void) { DDRD=0xff; //PortD als Ausgabe der Daten PD0-PD3 = D4-D7 PD4 = RS, PD5 = R/W, PD6 = Enable DDRC=0x00; //PortC als Eingabe, PC0 = Analog lcd_init(); lcd_home(); lcd_text(0x00,Text1); //Startadresse des Textes lcd_text(0x40,Text2); //Startadresse des Textes PORTC = 0x00; if (PINC & 0x04) { do { if (PINC & 0x04) { counter = counter + 1; } i = i + 1; } while(i<=1000); } for(;;) //Endlossschleife { hui=counter; //hui wird ausgegeben //Textausgabe utoa(hui,ADCText,10); //Ergebnis in String umwandeln strcat(ADCText,Null); //Endzeichen zum String hinzufügen lcd_text(0x46,Leer); //Startadresse des Textes lcd_text(0x46,ADCText); //Startadresse des Textes _delay_ms(50); } }
So wie Du das geschrieben hast wird der Taster genau einmal (beim Programmstart) abgefragt und dann nie wieder, das Ergebnis wird dann alle 50ms auf dem LCD ausgegeben. Versuch doch mal, die Abfrage des Tasters in die for(;;) schleife mit reinzunehmen und lass das _delay_ms(50) weg sonst "siehst" Du die Preller vermutlich nicht. Das sollte dann in etwa so aussehen:
1 | for(;;){ |
2 | |
3 | while( ! PINC & 0x04)LAST_STATE = PINC & 0x04; // Auf ersten Druck warten |
4 | counter = 0; |
5 | |
6 | while(i < 50000){ // Zeitschleife |
7 | STATE = PINC & 0x04; // Pin auslesen |
8 | if(LAST_STATE != STATE){ // Hat sich der Zustand geändert? |
9 | LAST_STATE = STATE; // Neuen Zustand sichern |
10 | if(STATE)counter++; // Wenn Taster zu, Zähler erhöhen |
11 | }
|
12 | }
|
13 | |
14 | Ausgeben(); |
15 | while(PINC & 0x04); // Warten bis das Ding wieder losgelassen wird. |
16 | }
|
> Gewöhn dich daran. In einem Betrieb hättest du für so eine Aufgabe > (neues Board, neue Sprache) nicht viel mehr als 1 Tag Zeit um > dir das Wissen zusammenzusuchen und diese Aufgabe zu lösen. Er befindet sich aber nicht in der Zukunft in einem Betrieb, sondern im hier und jetzt in einer Schule.
Ulli wrote: >> Gewöhn dich daran. In einem Betrieb hättest du für so eine Aufgabe >> (neues Board, neue Sprache) nicht viel mehr als 1 Tag Zeit um >> dir das Wissen zusammenzusuchen und diese Aufgabe zu lösen. > > Er befindet sich aber nicht in der Zukunft in einem Betrieb, sondern im > hier und jetzt in einer Schule. Na umso besser, wenn er sich dann jetzt schon daran gewöhnt. Dann ist der Schock beim Umstieg ins Berufsleben nicht so stark :-)
christian, denkst du das deine variante schnell genug ist um die prellungen zu zählen? danke vielmals elias
Elias wrote: > christian, denkst du das deine variante schnell genug ist um die > prellungen zu zählen? Probiers aus. Das was er da macht ist so ziemlich die einzige Möglichkeit einen Taster so schnell es nur irgendwie geht per Polling abzufragen. Wenn er damit ein Prellen nicht feststellen kann, dann wäre Prellen in einer Polling-Umgebung kein Problem.
> ...schnell genug ist um die prellungen zu zählen?
Keine Softwarevariante ist schnell genug um das Prellen zu zählen! Sowas
macht man mit der Hardware.
Siehe: 17.03.2008 10:31
so, im moment siehts so aus: /*=================================================================== Projekt: Prellzähler Modul: prell.c Autor: xx 17.03.08 ===================================================================*/ //#define F_CPU 4000000UL // Taktfrequenz 4 MHz #include <io.h> #include <interrupt.h> #include <signal.h> //AVRStudio4.12 //#include <sig-avr.h> //AVRStudio3.56 #include <stdlib.h> #include <string.h> #include "LCD_4.h" #include "LCD_4.c" char Text1[]= "**Prellzaehler**\0"; //Text1 in Flash-Ram char Text2[]= "**Run \0"; //Text1 in Flash-Ram char Leer[] = " \0"; //Leertext in Flash-Ram char Text[15]; char ADCText[5]; //ADC-Ergebnis char Null[] = {0x00}; char Zeichen, i; char *ZText; unsigned char x; unsigned int hui; int y=0; int counter=5; int LAST_STATE=0; int STATE=0; int k = 1; int main(void) { DDRD=0xff; //PortD als Ausgabe der Daten PD0-PD3 = D4-D7 PD4 = RS, PD5 = R/W, PD6 = Enable DDRC=0x00; //PortC als Eingabe, PC0 = Analog lcd_init(); lcd_home(); lcd_text(0x00,Text1); //Startadresse des Textes lcd_text(0x40,Text2); //Startadresse des Textes PORTC = 0x00; for(;;) //Endlossschleife { //Textausgabe utoa(counter,ADCText,10); //Ergebnis in String umwandeln strcat(ADCText,Null); //Endzeichen zum String hinzufügen lcd_text(0x46,Leer); //Startadresse des Textes lcd_text(0x46,ADCText); //Startadresse des Textes while(PINC & 0x04); // Warten bis das Ding wieder losgelassen wird do { LAST_STATE = PINC & 0x08; // Auf ersten Druck warten } while(LAST_STATE == 0); do { k = PINC & 0x08; } while (k == 1); counter = 0; do{ // Zeitschleife y++; STATE = PINC & 0x08; // Pin auslesen if(LAST_STATE != STATE) // Hat sich der Zustand geändert? { LAST_STATE = STATE; // Neuen Zustand sichern } if(STATE) { counter++; // Wenn Taster zu, Zähler erhöhen } } while(y < 5000); y = 0; LAST_STATE = 0; STATE = 0; } } leider zählt er immer sofort auf die 5000, oder zumindest auf eine sehr große zahl, aber warum?
Wie sind deine Taster angeschlossen? High aktiv oder Low Aktiv. (Was liefert der Pin, wenn der Taster nicht gedrückt ist)
Nochwas: konsequentes und richtiges Einrücken ist der Fehlersuche sehr zuträglich! do { // Zeitschleife y++; STATE = PINC & 0x08; // Pin auslesen if(LAST_STATE != STATE) // Hat sich der Zustand geändert? { LAST_STATE = STATE; // Neuen Zustand sichern } if(STATE) { counter++; // Wenn Taster zu, Zähler erhöhen } } while(y < 5000); Die Abfrage auf STATE muss innerhalb des Detektierens der Änderung erfolgen! Nur dann, wenn sich der Tastenzustand ändert und das Ergebnis dieser Änderung eine gedrückte Taste ist, hast du einen Prellvorgang
1 | do { // Zeitschleife |
2 | y++; |
3 | STATE = PINC & 0x08; // Pin auslesen |
4 | if(LAST_STATE != STATE) // Hat sich der Zustand geändert? |
5 | {
|
6 | LAST_STATE = STATE; // Neuen Zustand sichern |
7 | if(STATE) |
8 | {
|
9 | counter++; // Wenn Taster zu, Zähler erhöhen |
10 | }
|
11 | }
|
12 | } while(y < 5000); |
Preller wrote: >> ...schnell genug ist um die prellungen zu zählen? > > Keine Softwarevariante ist schnell genug um das Prellen zu zählen! Sowas > macht man mit der Hardware. > > Siehe: 17.03.2008 10:31 Da hast Du vollkommen recht, eigentlich sollte man sowas per Interrupt lösen. Und für jemanden der weiss was er tut ist das mit Sicherheit auch die Beste Lösung, aber ich denke das Elias mit der Polling-Methode schon zufrieden ist. Ausserdem merkt so der Lehrer nicht, daß er sich Hilfe geholt hat... :D Denkst Du denn, mein Vorschlag würde ein Prellen "übersehen" bei 4MHz Takt? (Die Frage ist wirklich aus Interesse, ich bin selbst noch ein Frischling auf dem Gebiet der µC...) Grüße, Christian
jungs... ich fürchte ihr werdet noch viel lehrgeld zahlen müssen bevor ihr versteht dass lernen etwas ist in das man zeit und mühe investieren muss... das sieht mir danach aus als wenn ihr euch die lösung der lehrfrage hier von gutmütigen forenmitgliedern auf dem silbertablett habt servieren lassen... na dann trozdem noch viel spaß beim basteln ;-) gruß r.
> Denkst Du denn, mein Vorschlag würde ein Prellen "übersehen" bei 4MHz
Takt?
Das ist es ja: Man weiss es nicht! Zählt das Polling nun ALLE Spices
oder verschluckt diese Methode einige.
Ich würde auch auf den Interrupt verzichten, da ja in der
Interrupt-Service-Routine auch Software sitzt. Die schnellste und
sicherste Methode ist hier der flankengesteuerte Zähleingang eines
Hardware-Counters.
Andererseits, wenn man mal von der strengen Aufgabenstellung des
Prellenzählens abgeht, so ist die von euch entwickelte Software ein
Lehr- und Übungsbeispiel an sich.
Preller wrote: >> Denkst Du denn, mein Vorschlag würde ein Prellen "übersehen" bei 4MHz > Takt? > > Das ist es ja: Man weiss es nicht! Zählt das Polling nun ALLE Spices > oder verschluckt diese Methode einige. Für alle würde ich meine Hand nicht ins Feuer legen. > > Ich würde auch auf den Interrupt verzichten, da ja in der > Interrupt-Service-Routine auch Software sitzt. Die schnellste und > sicherste Methode ist hier der flankengesteuerte Zähleingang eines > Hardware-Counters. Aber auch da könnten einige verloren gehen. Je nachdem wie schnell der Hardware Counter arbeitet > Andererseits, wenn man mal von der strengen Aufgabenstellung des > Prellenzählens abgeht, so ist die von euch entwickelte Software ein > Lehr- und Übungsbeispiel an sich. Ich denke man kann mal davon ausgehen, dass es das Bewusstsein für Prellen schärfen soll. Wenn das Prellen schneller erfolgt als eine µC Schaltung darauf reagieren kann, hätte dieses Wissen keinen praktischen Wert. Interessant ist das Prellen ja nur des- wegen, weil man etwas dagegen unternehmen muß. Ob da jetzt 1 Preller mehr oder weniger gezählt wird, wer will mir das nachweisen?
Du wirst mit ner Softwarezählung nicht glücklich werden. Ein einfaches Display-Clear, zufällig beim Tasten drücken und schon sind alle Preller vorbei. Taster ran an den T1 (als 16Bit-Zähler) und im Main den T1 einfach nur dezimal ausgeben, fertisch. Eventuell noch ne Rückstelltaste. Peter
Mal sehen, welchen Code der Elias nach den Ferien bei mir abgibt...
Übrigens hängt die Anzahl der gezählten Preller auch von der Eingangsbeschaltung ab. Wenn - wie üblich - ein stromsparender Pullup gegen den Taster arbeitet, bekommst Du garantiert eine maximal Pulswiederholrate, überschlägig: tau = ca. minimaler Pulsabstand = R x C = 100kOhm x 100pF = 10us. Das läßt sich prima in Software messen. Wenn aber nun jemand den Taster kapazitätsarm und niederohmig anschliesst, z.B. 1kOhm x 30pF = 30ns, sieht die Sache schon anders aus. Wie kurz ein konkreter Preller sein kann weiss ich nicht. Aber mir scheint, dass man das Signal mindestens in den Eingang eines Timers reinschieben muss, so wie der Peter gesagt hat. Ich sehe schon ein paar gelangweilte Entwickler an Ihren 10kEuro-Oszis Grundlagenforschung betreiben :-)
> = 30ns
Diese Preller werden aber nicht vom internen Counter einer MCU gezählt,
denn die max. Zählfrequenz der Timer/Counter ist vom MCU-Clock abhängig.
Mit ner externen HTC-Logik ist das alles kein Problem.
>Diese Preller werden aber nicht vom internen Counter einer MCU gezählt, >denn die max. Zählfrequenz der Timer/Counter ist vom MCU-Clock abhängig. Genau. "Versteckt" wird dann auch wieder gesampelt (nämlich bedingt durch die µC-interne Schaltung zwischen dem Pin und dem Zählregister), allerdings dann mit der für den µC maximal möglichen Frequenz (bei AVRs die Taktfrequenz). >Mit ner externen HTC-Logik ist das alles kein Problem. Wenn der Fragesteller die Aufgabe erfüllen soll, Tastenprellungen (nur) mit einem µC zu messen, hätte er bei Verwendung einer externen Logik sogar ein großes Problem.
Sicher, der Zähleingang der externen (HTC)Logik würde nur das Prellen um die Hi-Lo-TTL-Schwelle zählen. Um die kleineren Prellamplituden zu detektieren muss ein Vorverstärker, wie er in modernen Frequenzzählern eingesetzt wird, vorgeschaltet werden.
Hey Preller, hör' Dir die Meinung eines Schwurblers an: Es ist ja nicht so, dass der Taster ein veränderbarer Widerstand ist. In der Tat gelingt es einfach nicht in der kurzen Zeit des Prellens, die Leitungskapazität umzuladen. Daher: Runter mit der Leitungskapazität bzw. der Quellimpedanz und schon steigt die Amplitude Deines Signals.
>Kannst du dieses 'sehr große' Problem beschreibe?
Nicht 'sehr groß', nur 'groß'. Bitte genau zitieren... ;-)
Das angedeutete Problem ist nicht technischer Natur und tritt nur auf,
wenn der Fragesteller außer der genannten Aufgabe, Tastenprellen mit
einem µC zu messen, auch noch die (nicht genannte, aber didaktisch
eventuell sinnvolle) Forderung zu erfüllen hat, es ausschließlich mit
einem µC zu realisieren, d. h. ohne externe Zusatzhardware, weil die
Erlaubnis dazu der gewünschten Auseinandersetzung mit den verschiedenen
softwaremäßigen Möglichkeiten (per Polling / über externen
pegelgetriggerten Interrupt / durch Taktung von T/C1 durch die Taste)
abträglich wäre.
@preller: >Das ist es ja: Man weiss es nicht! Zählt das Polling nun ALLE Spices >oder verschluckt diese Methode einige. Das weiss man schon. Es ist sicher, dass Spitzen verschluckt werden. Eine Interruptlösung birgt diese 'Gefahr' ebenfalls. >Sicher, der Zähleingang der externen (HTC)Logik würde nur das Prellen um >die Hi-Lo-TTL-Schwelle zählen. Genau das ist auch interessant, oder? >Um die kleineren Prellamplituden zu detektieren muss ein Vorverstärker, wie >er in modernen Frequenzzählern eingesetzt wird, vorgeschaltet werden. Wozu? Es geht um Tastenprellen und dessen Auswirkungen auf die Ergebnisse der Abtastung der Zustände durch die MCU. Pegel, die im definierten Hi/Lo Bereich liegen, gelten sinngemäß als nicht prellend. Gruss, Edson
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.