Hallo,
ich habe an einem Atmega8 4 Taster an einem AD-Wandler.
Ich drücke immer nur einen Taster also nie mehrere gleichzeitig,
Entprellen habe ich über eine einfache Warteschleife realisiert. Reicht
aus und funktioniert.
Wenn ich einen der 4 Taster drücke, ändert sich der Widerstand und das
kann ich am AD-Wandler des Atmega8 auswerten welcher Taster gedrückt
wurde. So brauche ich nur 1 Port für 4 Taster. Siehe dazu auch
angehängtes Bild.
Nun würde ich gerne meine Schaltung mit Batterien oder Akkus betreiben
und eine möglichst lange Laufzeit erreichen. Dafür würde ich den Atmega8
gerne in eine SleepMode versetzen und über den Druck auf einen der 4
Taster wieder aufwecken.
Meine Frage:
Die Schaltung für die 4 Taster habe ich bereits, funktioniert auch, ich
würde die Schaltung gerne so ändern, dass ich über einen Druck auf einen
der vier Taster den Atmega8 aufwecke und dann sofort über den AD-Wandler
auslese welche Taste gedrückt wurde.
Da ich nicht so sehr elektronisch bewandert bin weiß ich nicht, wie ich
den WakeUp-Interrupt-Pin des Atmega8 und meine jetzige Schaltung
verbinden muss damit das funktioniert.
Brauche da mal eure Hilfe, vielen Dank schonmal!
T.Baumbach schrieb:> Die Schaltung für die 4 Taster habe ich bereits, funktioniert auch
Dann muß sie sich aber recht stark von der unterscheiden, deren Plan du
gepostet hast. Denn diese funktioniert garantiert NICHT.
> Nun würde ich gerne meine Schaltung mit Batterien oder Akkus betreiben> und eine möglichst lange Laufzeit erreichen. Dafür würde ich den Atmega8> gerne in eine SleepMode versetzen und über den Druck auf einen der 4> Taster wieder aufwecken.
Kann man machen. Wenn man das Widerstandsnetzwerk sinnvoll auslegt,
sollte diese Zusatzfunktionalität mit nur vier Tastern noch relativ
problemlos möglich sein.
Hi c-hater,
ja hast recht, habe meinen Schaltplan zu schnell ab gezeichnet - sorry.
Hier die (hoffentlich) korrekte Version, siehe angehängte Datei.
Wie muss ich die nun erweitern, um über den Interrupt den Atmega8
aufzuwecken und dann den ADC auswerten zu können welche Taste gedrückt
wird?
Danke nochmals!
T.Baumbach schrieb:> Hier die (hoffentlich) korrekte Version, siehe angehängte Datei.
Ja, das sieht schon viel besser aus, diese Schaltung kann immerhin
funktionieren. Sie ist allerdings schon für den ursprünglichen Zweck
ziemlich suboptimal. Und für den neuen Zweck, Energie zu sparen, ist sie
leider ziemlich unbrauchbar, auch wenn die grundsätzliche Funktion damit
realisierbar ist.
> Wie muss ich die nun erweitern, um über den Interrupt den Atmega8> aufzuwecken und dann den ADC auswerten zu können welche Taste gedrückt> wird?
Einfach den 10k-Widerstand Richtung GND deutlich vergrößern, z.B. auf
33k.
Damit verringern sich allerdings die ohnehin bescheidenen Unterschiede
für die einzelnen Taster weiter.
Die Alternative wäre, statt dessen den 10k-Widerstand Richtung Vcc zu
verkleinern, z.B. auf 3,3k. Damit erhöhen sich die Unterschiede zwischen
den Tastern etwas, aber es fließt im Schlafzustand noch mehr Strom
sinnlos.
Grundsätzlich kannst du das Problem nur durch eine Modifikation der
Schaltung lösen. Die kann dann erstens dafür sorgen, daß im
Schlafzustand garkein Strom mehr durch das Taster-R-Netzwerk fließt und
zweitens auch noch dafür, daß die Taster im Wachzustand sehr viel
zuverlässiger unterscheidbar sind als bisher.
c-hater schrieb:> T.Baumbach schrieb:>> Wie muss ich die nun erweitern, um über den Interrupt den Atmega8>> aufzuwecken
Ooops, ich habe jetzt erst gesehen, daß es um einen Methusalem von
Controller geht, der noch keinen PCINT für jeden Pin beherrscht. Für den
ist natürlich zusätzlich ein freier interruptfähiger Pin nötig, um das
zu realisieren. Dieser Pin muß dann einfach mit an den verwendeten
ADC-Eingang geschaltet werden. Und in diesem Fall fällt auch die
Variante mit der Erhöhung des Widerstands Richtung Vcc aus.
Wenn Du unbedingt beim ATmega8 bleiben möchtest, mußt Du parallel zum
ADCx-Eingang noch einen INTx-Eingang verwenden, der auf negative Flanken
reagiert. Besser ist es allerdings einen ATmega48/88 mit PCINT-Option zu
verwenden.
Mein Vorschlag: ein Pullup-Widerstand (100k) von ADCx nach VCC. Von ADCx
werden einzelne Widerstände (68k, 33k, 15k, 0R0) mit den Tastern gegen
GND geschaltet.
Bei offenen Tastern fließt kein Strom. Sobald ein Taster geschlossen
wird, sinkt die Spannung an ADCx/INTx deutlich unter VCC/2, was zur
Flankenerkennung notwendig ist und den µC aufweckt.
Man kann auch größere Widerstände einsetzen (220k, 100k, 47k, 0R0),
wobei bei den Werten >=68k noch ein 1nF Kondensator parallel geschaltet
werden muß, damit der INTx-Eingang kurzzeitig auf kleiner 0,4 x VCC
gebracht wird, um den Interrupt auszulösen. Anstelle des 0R0, kann man
auch 6k8 bzw. 22k vorsehen und damit auch mehrere Taster gleichzeitig
erkennen.
Oder man nimmt eine Reihenschaltung von 3 x 22k, deren Abgriffe nach GND
geschaltet werden. Dadurch erhält man eine Priorität der Taster: der
Taster 'gewinnt', der am nächsten zu ADCx geschlossen ist. Als
Widerstände ergeben sich dann 0R0, 22k, 44k oder 66k.
Für geringe Stromaufnahme sollte BOD ausgeschaltet sein. Ferner sollten
die Taster möglichst vergoldete Kontakte aufweisen, womit kleine Ströme
zuverlässig geschaltet werden können.
Hallo,
danke erstmal für die Tipps. Ich muss nicht unbedingt einen Atmega8
nehmen, hatte den nur gerade da. Ich denke mal ich nehme in meiner
finalen Schaltung einen Attiny26.
Hinsichtlich möglichst geringem Stromverbrauch macht es da überhaupt
Sinn über den ADC die Tasten auszuwerten?
Oder spare ich mehr Strom, wenn ich einen anderen Prozessor nehme (evtl.
Attiny2313?) und dann für z.B. 16 Tasten ein 4x4 Keypad an 4 Zeilen / 4
Spalten nehme und dafür 8 Portpins 'opfere'? Wäre diese Version
stromsparender als die ADC-Variante?
T.Baumbach schrieb:> 16 Tasten ein 4x4 Keypad an 4 Zeilen / 4> Spalten nehme
Warum willst Du 16 Tasten nehmen, wenn Du nur vier brauchst?
Die Stromaufnahme steht im Datenblatt und liegt unter 1µA, wenn man den
µC richtig schlafen legt.
Fang einfach an!
Hallo m.n.,
danke nochmal, die Schaltung mit den 4 Tastern war (eigentlich) zum
'lernen' gedacht. In meiner finalen Schaltung brauche ich aber 16
Taster.
Macht es hinsichtlich Stromaufnahme dann eher Sinn die 4x4 Keypad-Lösung
zu nehmen?
T.Baumbach schrieb:> Ich denke mal ich nehme in meiner> finalen Schaltung einen Attiny26.
Bessere Wahl.
> Hinsichtlich möglichst geringem Stromverbrauch macht es da überhaupt> Sinn über den ADC die Tasten auszuwerten?
Solange du nicht vorhast, dauerhaft Tasten zu drücken, sondern das immer
ein vergleichsweise kurzes Ereignis bleibt, was die übliche Nutzung
wäre, spricht nichts gegen die ADC-Variante, sofern sie in etwa so
umgesetzt wird wie von "m.n." vorgeschlagen. Strom fließt da nämlich,
abweichend von deiner ursprünglichen Schaltung, nur dann, wenn
tatsächlich eine Taste gedrückt wird.
> Wäre diese Version> stromsparender als die ADC-Variante?
Ja, aber nur in irrelevanter Größenordnung. So lange dir ca. 8 Taster
oder weniger reichen, kannst du getrost bei der ADC-Variante bleiben.
Hi c-hater,
>Ja, aber nur in irrelevanter Größenordnung. So lange dir ca. 8 Taster>oder weniger reichen, kannst du getrost bei der ADC-Variante bleiben.
Ich brauche 16 Taster, aber immer nur einer gedrückt, nie zwei oder
mehrere zusammen!
Wenn immer nur einer gedrückt wird dann ist es doch egal wieviele Taster
ich habe - oder? Ich meine hinsichtlich Stromaufnahme.
Hi,
der ADC selber braucht ja auch Strom. Kann ich denn den ADC erst
einschalten lassen, wenn ich den Mikrocontroller aufgeweckt habe?
Das würde dann noch mehr Strom sparen - oder?
Also der Mikrocontroller schläft, in Low-Pegel auf einem Interrupt-Pin
weckt den Mikrocontroller auf. Der geht in die Interruptroutine und
schaltet den ADC ein der dann auswertet welche Taste gedrückt wurde -
ginge das?
Aufbauen würde ich das Teastenfeld wie m.n. es beschrieben hat:
>Oder man nimmt eine Reihenschaltung von 3 x 22k, dere>n Abgriffe nach GND>geschaltet werden. Dadurch erhält man eine Priorität der Taster: der>Taster 'gewinnt', der am nächsten zu ADCx geschlossen ist. Als>Widerstände ergeben sich dann 0R0, 22k, 44k oder 66k.
Ich weiß aber nicht wie ich die Schaltung erstellen muss, um den
Interrupt an einem Pin auszulösen, der den Mikrocontroller aufweckt.
Das soll ja eine der 16 Tasten machen. Wie muss ich die Tasten und den
Interrupt-Pin beschalten, damit zuerst der Interrupt ausgelöst wird (um
den Mikrocontroller aufzuwecken) und dann über den Widerstandswert und
den ADC ausgewertet wird welche taste gedrückt wurde.
Danke nochmal, bin wie gesagt nicht so fit in Elektronik, bin für jede
Hilfe dankbar. Ein Schaltplan wäre super!
T.Baumbach schrieb:> Ich brauche 16 Taster, aber immer nur einer gedrückt, nie zwei oder> mehrere zusammen!> Wenn immer nur einer gedrückt wird dann ist es doch egal wieviele Taster> ich habe - oder? Ich meine hinsichtlich Stromaufnahme.
Nein.
Das Problem ist, zuverlässig zu unterscheiden, welcher Taster nun
gedrückt ist. Das wird umso schwerer, je mehr Taster es sind, denn damit
werden logischerweise die zu messenden Unterschiede immer kleiner. Diese
Unterscheide müssen aber immer deutlich größer bleiben als das Rauschen.
Das führt dazu, daß man die Tasterschaltung umso niederohmiger auslegen
muß, je mehr Taster zu erfassen sind. Geringere Widerstände ziehen aber
leider auch höhere Ströme nach sich.
Und hier kommt bezüglich der Aufwachfunktion noch hinzu, daß sie den für
die Tasterwerte verfügbaren Messbereich etwa halbiert, was das Problem
weiter verschärft.
Also bei 16 Tastern mit Aufweckfunktion würde ich mich ganz klar pro
Matrix und kontra ADC entscheiden. Das spart einen Haufen Ärger.
T.Baumbach schrieb:> der ADC selber braucht ja auch Strom. Kann ich denn den ADC erst> einschalten lassen, wenn ich den Mikrocontroller aufgeweckt habe?
Das machst du automatisch, wenn du den µC in den Tiefschlaf schickst,
damit hältst du sämtliche Takte an, auch den des ADC.
> Ich weiß aber nicht wie ich die Schaltung erstellen muss, um den> Interrupt an einem Pin auszulösen, der den Mikrocontroller aufweckt.
Da brauchst du keine extra Schaltung für zu erstellen, sondern bloß
Software.
Im Minumum eine leere ISR für den verwendeten PCINT-Interrupt und den
Code zur Aktivierung des PCINT für den gewünschten Pin (ADC-Tastatur)
bzw. für die Eingangs-Pins der Matrix im Falle einer Matrixtastatur.
Bei der Matrix ist noch eine Vorkehrung mehr nötig, hier muß direkt vor
dem Einschlafen das normale Multiplexing zur Abfrage stillgelegt und
durch einen konstanten "aktiven" Pegel auf allen angesteuerten Leitungen
der Matrix ersetzt werden. Dementsprechend muß dann beim Aufwachen die
Sache wieder in den Normalzustand zurückversetzt werden. Dafür bietet
sich dann die (ansonsten ja völlig ungenutzte) ISR des PCINT an.
Hi c-hater,
danke nochmals. Ich denke dann werde ich wohl eher mit der 4x4 Matrix
arbeiten.
Habe dazu folgendes gefunden (leider erst jetzt ;-)):
http://www.atmel.com/Images/doc1232.pdf
Werde mich da mal ranwagen ;-)
Danke nochmals an all hier!
Hi,
habe mir die Schaltung die Atmel vorschlägt gerade mal angesehen.
Die Widerstande R1-R4 sind doppelt in der Zeichnung.
Einmal links an den Dioden (siehe rote Umrahmung) und einmal in den
Widerständen an den Portpins PB7-PB4.
PB7-PB4 sind 470 Ohm, aber wie muss ich die vier Widerstände an den
Dioden dimensionieren?
Die sollen den Interrupt-Pin PD2 auf low ziehen um den Mikrocontroller
aufzuwecken.
Danke für Eure Hilfe!
c-hater schrieb:> Also bei 16 Tastern mit Aufweckfunktion würde ich mich ganz klar pro> Matrix und kontra ADC entscheiden. Das spart einen Haufen Ärger.
Nur unter uns und nichts für Anfänger: wenn ich es bräuchte, wäre ich
mutig und würde es auch bei 16 Tastern mit ADC machen.
Ein Pullup 100k || 10nF von ADCx nach Vref (bzw. VCC) und dann eine
Reihenschaltung von 16 x 10k Widerständen, wobei jeder 4.-5. Abgriff mit
100nF nach ADCx die Aufweckfunktion ermöglicht. Alle Taster schalten
gegen GND; die Schaltung selbst kannst Du sicherlich im Kopf
nachvollziehen.
Bezogen auf einen 10Bit-ADC ergeben sich rein rechnerisch folgende Werte
für die einzelnen Taster:
1-8: 93, 170, 236, 292, 341, 383, 421, 455
9-16: 485, 512, 536, 558, 578, 597, 614, 640
Die kleinste Änderung ergibt sich am Ende der Tabelle und beträgt 16
Schritte (640-614), was 2,5% entspricht. Mit einer 1% Widerstandskette
läßt sich hinreichende Genauigkeit erreichen, wobei sich das
Toleranzband durch 4 x 22k Widerstände am Ende noch vergrößern ließe.
Eine fertige Tabelle (ggf. auch mit nur 8 Bit), die die Schwellwerte
zwischen den Stufen enthält, erleichtert die schnelle Auswertung.
Wie gesagt, nichts für Anfänger aber machbar, wenn nur ein freier
ADC-Eingang zur Verfügung steht.
Hi c-hater,
danke für Deine Mühe. Aber da ich mich eher zu den Anfänger zähle, fange
ich wohl besser mit der Matrix-Lösung an.
Wer kann mir denn nun sagen, wie ich die 4 Widerstände an den Dioden
dimensionieren muss?
Hi c-hater,
rein interessehalber und um deine Schaltung mit ADC und 16 Tastern zu
verstehen wie wird denn da die Aufweckfunktion realisiert?
Brauche ich da einen zusätzlichen Interrupt Pin oder wird der
Mikrocontroller durch eine Tastendruck (eine der 16 Tasten) am ADC
aufgeweckt?
Wenn das so ist hiße das doch, dass der ADC laufen muss und strom
verbraucht - oder?
Wäre meine Idee nicht sinnvoller den Mikrocontroller in den SleepMode zu
versetzen, also auch der ADC ist komplett abgeschaltet. Ein Tastendruck
(auf irgendeine der 16 Tasten) würde den Mikrocontroller aufwecken und
in der Interuptroutine den ADC starten der dann den Taster auswertet?
Wie sieht denn dann die Schaltung aus? Also wie sorgt man dafür dass
beim Drücken einer Taste der Interruptpin auf low gezogen wird und
gleichzeitig der entsprechende Widerstandswert am ADC-Pin anliegt?
Danke nochmal!
T.Baumbach schrieb:> habe mir die Schaltung die Atmel vorschlägt gerade mal angesehen.
Die ist Mist (im Sinne von: für einen modernen AVR unnötig aufwendig).
Bei einem modernen AVR brauchst du für eine Tastenmatrix mit
Aufweck-Funktionalität exakt garkeine Bauelemente (außer den Tastern
selber natürlich). Alles andere wird per Software und mit Hilfe der in
den AVR bereits eingebauten Hardware erledigt.
Für eine 4x4 Matrix nimmst du z.B. einfach alle 8 Pins eines Ports,
sagen wir mal den PortA eines Tiny26. Nehmen wir an, die
Spaltenleitungen der Matrix hängen an PA0..3 und die Zeilenleitungen an
PA4..7. Wobei Spalten und Zeilen nur eine Frage der Definition sind,
prinzipiell sind die natürlich austauschbar.
Wie auch immer, die Spalten-Pins, also PA0..3, programmierst du als
Eingang mit aktivem Pullup. Die werden später im Normalbetrieb gelesen
und es sind auch die Pins, die das Wecken auslösen werden. Nach der
Initialisierung liest du an allen vier Pins erstmal dauerhaft High, also
eins, weil die Pullups sie an Vcc legen.
Die Zeilen-Pins, also PA4..7, programmierst du auch erstmal als
Eingänge, allerdings ohne Pullup. Sie sind also hochohmig, machen
erstmal garnix.
Das normale Auslesen der Matrix funktioniert nun so: Eine der
Leitungen PA4..7 wird als Ausgang umprogrammiert. Der entsprechende Pin
liegt dadurch auf Low. Wenn nun in der Matrix irgendeine (oder auch
mehrere) der vier Tasten gedrückt sind, die an der entsprechenden Zeile
hängen, wird an den mit den Tasten korrespondierenden Spaltenanschlüssen
der Pegel von High auf Low gezogen. Du brauchst also bloß PA0..3 zu
lesen und kennst den Status der ersten vier Tasten der Matrix, jedes
gelesene 0-Bit entspricht der Tatsache, daß die zugehörige Taste
gedrückt ist. Nun merkst du dir die gelesene Zeile.
Nun willst du auch noch den Status der anderen Tasten wissen. Nichts
einfacher als das. Die zuvor auf Ausgang geschaltete Zeilenleitung wird
wieder auf Eingang (also hochohmig) geschaltet und die nächste wird auf
Ausgang geschaltet. Damit kannst du dann wieder PA0..3 lesen, die
diesmal den Zustand der Taster der zweiten Zeile wiederspiegeln.
Das Verfahren setzt du jetzt analog fort, bis du alle Zeilen durch hast.
Damit hast du jetzt den Zustand aller 16 Tasten gelesen.
Nun kommt das beliebte Entprellen. Das realisiert man dadurch, da man
oben beschriebene Operation für jede Zeile in der ISR eines geeignet
konfigurierten Timers laufen läßt und sich immer zwei Sätze von
Tastenstati merkt, das zuletzt vollständig gelesene und das aktuelle.
Ist auch das aktuelle vollständig, geht man an's Vergleichen der beiden
Datensätze, wurde zweimal hintereinander der gleiche Zustand für eine
Taste
gelesen, wird der wohl gültig sein und kann akzeptiert werden. Will man
daraus noch ein Ereignis generieren, im Sinne von "Taste(n) haben sich
geändert", nimmt man einfach noch einen dritten Datensatz zu Hilfe und
vergleicht den mit den als gültig erkannten Zuständen, gibt es
Unterschiede, hat sich der Zustand mindestens einer Taste geändert.
So, nun gehst du schlafen. Das machst du, indem du alle Zeilenleitungen
auf Ausgang programmierst, für die vier Spaltenleitung den
PCINT-Interrupt aktivierst und dann sleep ausführst. Das Teil schläft
jetzt ein.
Vorsicht: Oft ist es nötig, weitere Maßnahmen zu treffen, bevor man
einschlafen kann. Leuchtet da z.B. noch irgendeine LED, wird sich der
Stromspareffekt des Schlafmodus in Grenzen halten...
Bleiben wir aber bei der Tastatur: Wird jetzt irgendeine Taste der
Matrix gedrückt, ändert irgendeine Spaltenleitung ihren Zustand von
High auf Low. Tritt nun so ein Pegelwechsel ein, wacht das Teil wieder
auf und durchläuft als erstes die ISR des PCINT-Interrupt. Dort
deaktivierst du den PCINT-Interrupt und setzt alle Zeilenleitungen
wieder auf Eingang (also hochohmig=inaktiv). Der nächste Interrupt des
Polltimers wird dann wieder eine davon auf Ausgang legen und alles geht
wieder seinen normalen Gang. Maximal für einen Abfragezyklus ergeben
sich falsche Tastenwerte für eine Zeile, das bügelt aber die Entprellung
weg.
Was bleibt ist die zum Aufwachen verwendete Taste. Die kann man garnicht
so schnell wieder loslassen, daß die normale Tastaturabfrage nicht
mitbekommen würde, daß sie gedrückt und wieder losgelassen wurde. Um
dieses Problem muß sich deine Software selber kümmern, das erledigt die
normale Entprellung nicht mit.
Hi c-hater,
wow, danke für die ausführliche Info und deine Mühe!
Dann wird meine Schaltung ja wesentlich einfacher. Hoffe dass ich den
C-Code hinbekomme.
Dann mache ich mich mal an die Arbeit, leider ist das Wochenende nun
schon rum, werde es wohl auf nächste Woche verschieben. Mache mir dazu
eine Platine (mit Target 3001) und ätze die dann...
Nochmal vielen lieben Dank!