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
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.
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 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.
> 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 :-)
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?
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?
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
Ü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