Forum: Mikrocontroller und Digitale Elektronik qtouch - sekt oder selters


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Ben (Gast)


Lesenswert?

beim download des aktuellen avr studios ist mir der eintrag qtouch 
aufgefallen. hat sich schon jemand mit dieser technologie beschäftigt. 
ist es ein muss oder nur einen neue sau die durchs dorf getrieben wird?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ich schalte das Licht in der Dusche mit einem hinter den Fliesen 
angebrachten TouchPad. Die Routinen habe ich nach einem Besuch beim 
QTouch-Seminar nochmal nachempfunden und in einen Mega88 geflasht, die 
Libraries von ATMEL benutze ich nicht, weil falsche Programmiersprache 
;-). Ich empfinde die Touch-Technik als nützlich, gerade im "IP67 oder 
besser Bereich".

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Ich hab mir letztens die QTouch Libs angesehen (mit AVR GCC) und musste 
feststellen, dass die Messung eines Touchsensors etwas unempfindlich 
ist. Oder ich hab die falschen Einstellungen getroffen (keine Ahnung).

Jedenfalls ist die Technik ja relativ leicht nachprogrammiert und 
funktioniert bei mir jetzt auch besser (empfindlicher). Hab aber noch 
keine Driftkompensation drinnen wie es in der Atmel Lib drinnen ist.

mfg
Andreas

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Die Driftkompensation ist nichts weiter als ein Tiefpaß, der den 
Mittelwert als Differenz für die Meßwerte stetig anpaßt (etwa um einen 
Meßwert pro Sekunde) wenn kein Touch ausgelöst ist. Nach Toucherkennung 
wird der Mittelwert nicht verändert, bis der Touch wieder weg ist oder 
ein Timeout von, sagen wir mal, 15 Sekunden verstrichen ist.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Ja, so hab ich mir das auch gedacht! Sehr viel anders lässt sich das mit 
einfachen Mitteln ja auch nicht implementieren denk ich mal.

von Peter D. (peda)


Lesenswert?

Ich habe bisher nur gesehen, daß zwar die tollsten Erklärungen für die 
Sensor-ICs gemacht werden, aber es letztendlich auf eine 
Kapazitätsmessung hinausläuft.
Es kochen also alle nur mit Selters.


Peter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Nee, Peter. Es ist keine Kapazitätsmessung sondern eine 
Charge-Transfer-Messung. Gegenüber der reinen Kapazitätsmessung mit 
einer an einem Pin angeschlossenen Meßplatte ist diese Version mit 
definierter Paketladung über einen Transferkondensator über 2 Pins 
empfindlicher und reproduzierbarer.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

@Travel Rec.:
Hast du dir für deine Anwendung eine Platine machen lassen?? Wenn ja, 
wie sieht da deine "Touch-Fläche" aus?? Vorallem würde mich 
interessieren, wie groß die Fläche ist und ob du im Layer darunter eine 
Massefläche hast?!

Achja... und das funktioniert bei dir noch hinter den Fliesen?! Ich hab 
schon Probleme, wenn ich bisschen Kunststoff oder Papier drüber hab.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Andreas Auer schrieb:
> @Travel Rec.:
> Hast du dir für deine Anwendung eine Platine machen lassen??

Ja, von mir selber ;-)

> Wenn ja,
> wie sieht da deine "Touch-Fläche" aus??

Ist eine mit kurzem Kabel abgesetzte, einseitig kupferkaschierte 
Hartpapier-LP in der Größe eines 2-EUR Stücks, vielleicht ein wenig 
größer.


> Vor allem würde mich
> interessieren, wie groß die Fläche ist

Wie gesagt...


> und ob du im Layer darunter eine
> Massefläche hast?!

Natürlich NICHT!


> Achja... und das funktioniert bei dir noch hinter den Fliesen?! Ich hab
> schon Probleme, wenn ich bisschen Kunststoff oder Papier drüber hab.

Ja. Geht durch 1cm Keramik und 1.25cm Rigips.

von Peter D. (peda)


Lesenswert?

Travel Rec. schrieb:
> Nee, Peter. Es ist keine Kapazitätsmessung sondern eine
> Charge-Transfer-Messung.

Gibt es irgendwo ne verständliche Beschreibung und Schaltplan mit 
Dimensionierung?
Braucht man die speziellen ICs dazu oder reicht ein normaler MC?
Ich bin von den Flyern und Werbung auf der Atmel Seite schon ganz 
wuschig im Kopf. Nirgends findet man was sinnvolles.


> Gegenüber der reinen Kapazitätsmessung mit
> einer an einem Pin angeschlossenen Meßplatte ist diese Version mit
> definierter Paketladung über einen Transferkondensator über 2 Pins
> empfindlicher und reproduzierbarer.

Läßt sich das irgendwie belegen?
Ich denke mal, daß auch diese Methode eine Art Kalibration durchführen 
muß, um auf Empfindlichkeit zu kommen.


Peter

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Peter Dannegger schrieb:
> Gibt es irgendwo ne verständliche Beschreibung und Schaltplan mit
> Dimensionierung?
> Braucht man die speziellen ICs dazu oder reicht ein normaler MC?
> Ich bin von den Flyern und Werbung auf der Atmel Seite schon ganz
> wuschig im Kopf. Nirgends findet man was sinnvolles.

Es gab mal einen Thread da hat Travel Rec. selbst seinen Code und 
Schaltplan gepostet. Mit dem war es mir möglich das ganze 
nachzuvollziehen und in C zu implementieren.

Beitrag "Quantum Chips"

Die Atmel Seite ist in diese Richtung in der Tat etwas unübersichtlich.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> Braucht man die speziellen ICs dazu oder reicht ein normaler MC?
> Ich bin von den Flyern und Werbung auf der Atmel Seite schon ganz
> wuschig im Kopf. Nirgends findet man was sinnvolles.

Die Touch-ICs liefern fertige Schaltsignale und lassen sich geringfügig 
von außen konfigurieren. Beim µC kann man die Libraries benutzen oder 
selber loslegen. Bedingung ist, daß de µC abschaltbare PullUps hat, 
sonst funktionieren die Meßbursts nicht. Touch funktioniert also u.a. 
auf allen neueren AVRs und XMegas und den AVR32-Controllern.

von Roland Z. (roland77)


Angehängte Dateien:

Lesenswert?

Hallo,

ich klinke mich an der Stelle mal ein. :-)

Leider habe ich bezüglich der QTouch-Sache ein wenig ein Brett vor dem 
Kopf.

Ich verstehe das funktionsprinzip anhand der Zeichnung im Anhang (die 
ist aus dem Atmel-Datasheet) folgendermaßen:

1. Zu beginn wird die Sensorplatte entladen indem PB1 als Eingang und 
auf "0" geschaltet wird.
2. PB1 wird nun zur Bursterzeugung kurz auf "1" geschaltet, danach wird 
der Pin umkonfiguriert als Eingang, Pull-Ups sind generell 
ausgeschaltet.
3. Das ganze Spiel unter 2. wiederholt sich bis der Pin wenn er als 
Eingang geschaltet ist als logisch "1" gelesen wird. Die Anzahl der 
notwendigen Ladezyklen wird dabei gezählt.
4. Steigt die Anzahl der notwendigen Ladezyklen auf einmal stark an, 
geht der Chip davon aus das einer Seine Flossen vor den Sensor hält. Die 
Auslöseschwelle wird natürlich ständig langsam nachgeführt (Stichwort 
Tiefpass)

Was ich nicht ganz kapiere, für was braucht man den Kondensator Cs? 
Warum der eine Verbindung zu PC1 hat und nicht nach GND kapiere ich 
nicht so ganz.
Es schwirren viele Infos und Codeschnipsel im Netz rum, auch hier im 
Forum, aber eine einfache Erklärung des Funktionsprinzips habe ich bis 
jetzt noch nicht gefunden. "Charge Transfer" hört sich zwar interessant 
an, aber an klaren Erklärungen mangelt es mir zur Zeit irgendwie. ;-)
Vielleicht kann mir jemand Erklären wie das mit dem Kondensator im 
ganzen funktioniert. Für irgendwas muss Cs ja gut sein...

Nachtrag: Ich vermute das durch das Umladen der einen Seite des 
Kondensators, etwas Ladung auf die "andere" seite des Kondensator 
geschaufelt wird. Stimmt das ?

Nachtrag2: Gehe ich recht in der Annahme das man zum das QTouch Prinzip 
zu realisieren keinen ADC benötigt, dies also rein mit den normalen 
Pins, wie auch mit den kleineren Tinys, oder dem Tiny2313 der keinen ADC 
hat, klappt?


Roland

von Peter D. (peda)


Lesenswert?

@Travel Rec.

Die Eingänge werden digital eingelesen, d.h. eine Drift der 
Eingangsschwelle spielt keine Rolle?

Die Eingänge werden eingelesen, wenn alles tristate ist, muß das dann 
nicht sauempfindlich gegen HF-Störungen sein?
Und der Eingang, der später eingelesen wird, müßte störempfindlicher 
sein.
Sollte man nicht besser erst die SBIS-Befehle machen und danach das 
ADIW?

Könnte man die Schleife nicht schon abbrechen, wenn beide Eingänge low 
sind?

Können die 33nF Keramik sein?
Wenn ja, die haben ja große Toleranzen und Drift, wirkt sich das auf die
Werte der beiden Tasten aus?
D.h. können die stark unterschiedlich sein?

Die Ausgänge TOUCH1A/2A werden nirgends gesetzt, müssen sie low sein, 
oder ist das egal?


Vom Prinzip her erinnert mich das an nen DAC mit geschalteten 
Kondensatoren. Der Unterschied ist nur, daß beide Kondensatoren nicht 
gleich groß sind, sondern stark unterschiedlich.
Das Prinzip hat man früher auch als Rampengenerator verwendet (ein 
kleiner Kondensator lädt kleine Ladungen auf einen großen).

Letztendlich ist also auch eine Kapazitätsmessung. Die Frage ist nur, 
welcher Unterschied sich bezüglich Bauelementedrift und Störspannungen 
gegenüber anderen Meßmethoden ergibt.


Peter

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

@Roland:
Ich weiß nicht, ob die Beschreibung von Peter jetzt ausreicht um deine 
Fragen zu beantworten, da er doch sehr stark auf die Implementierung von 
Travel Rec. eingeht.

Ich hab das ganze so implementiert:

1. definierten Zustand für die Kondensatoren herstellen. D.h. PB1 und 
PC1 als Ausgänge schalten und auf low ziehen um alles Cs zu entladen 
(genügend lange warten).

2. PB1 auf high und PC1 auf low schalten (aber immernoch als Eingänge)

3. PB1 als Ausgang schalten und kurze Zeit (z.B. 5us) warten bis der 
unbekannte Touchkondensator geladen ist.

4. PB1 wieder als Eingang schalten und PC1 als Ausgang schalten. Damit 
liegt jetzt der "Sampling Kondensator Cs" quasi parallel zum 
Touchkondensator und es müssen sich die Ladungen so umverteilen, dass 
beide die gleiche Spannung haben (Parallelschaltung). D.h. es wird Cs 
leicht geladen, da dieser ja viel größer ist.

5. Überprüfe ob PB1 schon als high eingelesen wird. Wenn nicht, dann 
beginne wieder bei Punkt 3 und erhöhe einen Zähler. Wenn PB1 bereits 
high ist, dann ist der Zählerstand ein Maß für die Anzahl der 
Ladezyklen.

Der Endstand des Zählers wird sich verändern, wenn du mit dem Finger auf 
den Touchsensor greifst.

Als C code sieht das so aus:
1
static int sense(void)
2
{
3
    unsigned char i=0; 
4
    DDRC  = 0x00;
5
    PORTC = 0x00;
6
    
7
    DDRC |= _BV(PC1);
8
    DDRC |= _BV(PC0);
9
    _delay_us(5);
10
    DDRC &= ~_BV(PC1);
11
    DDRC &= ~_BV(PC0);
12
13
    PORTC |= _BV(PC0);
14
    for(i=0; i<255 && !(PINC & _BV(PC0)); i++)
15
    {
16
        DDRC |=  _BV(PC0);
17
        _delay_us(5);
18
        DDRC &= ~_BV(PC0);
19
        DDRC |=  _BV(PC1);
20
        _delay_us(20);
21
        DDRC &= ~_BV(PC1);
22
    } 
23
    DDRC |= _BV(PC1);
24
    DDRC |= _BV(PC0);
25
    PORTC = 0x00;
26
    
27
    return i;
28
}

von Roland Z. (roland77)


Lesenswert?

Andreas Auer schrieb:
> @Roland:
> Ich weiß nicht, ob die Beschreibung von Peter jetzt ausreicht um deine
> Fragen zu beantworten, da er doch sehr stark auf die Implementierung von
> Travel Rec. eingeht.
>
> Ich hab das ganze so implementiert:
>
> 1. definierten Zustand für die Kondensatoren herstellen. D.h. PB1 und
> PC1 als Ausgänge schalten und auf low ziehen um alles Cs zu entladen
> (genügend lange warten).

Habe ich, soweit kein Problem

>
> 2. PB1 auf high und PC1 auf low schalten (aber immernoch als Eingänge)

Aha, dann beide Pins als Eingänge Konfigurieren. Aber wie soll ich dann 
High und Low schalten? Ist das eventuell ein Schreibfehler deinerseits 
und sollte Ausgang (also für die Konfig der Pins) heißen?

>
> 3. PB1 als Ausgang schalten und kurze Zeit (z.B. 5us) warten bis der
> unbekannte Touchkondensator geladen ist.
>

Hier komme ich gar nicht mehr mit, was macht dann PC1? Ist das immer 
noch ein Ausgang und auf Low?

> 4. PB1 wieder als Eingang schalten und PC1 als Ausgang schalten. Damit
> liegt jetzt der "Sampling Kondensator Cs" quasi parallel zum
> Touchkondensator und es müssen sich die Ladungen so umverteilen, dass
> beide die gleiche Spannung haben (Parallelschaltung). D.h. es wird Cs
> leicht geladen, da dieser ja viel größer ist.
>

Sorry jetzt komme ich nicht mehr mit, PC1 als Ausgang kapiere ich aber 
was für einen Pegel, High oder Low?

> 5. Überprüfe ob PB1 schon als high eingelesen wird. Wenn nicht, dann
> beginne wieder bei Punkt 3 und erhöhe einen Zähler. Wenn PB1 bereits
> high ist, dann ist der Zählerstand ein Maß für die Anzahl der
> Ladezyklen.
>
> Der Endstand des Zählers wird sich verändern, wenn du mit dem Finger auf
> den Touchsensor greifst.
>
> Als C code sieht das so aus:
>
1
> static int sense(void)
2
> {
3
>     unsigned char i=0;
4
>     DDRC  = 0x00;
5
>     PORTC = 0x00;
6
> 
7
>     DDRC |= _BV(PC1);
8
>     DDRC |= _BV(PC0);
9
>     _delay_us(5);
10
>     DDRC &= ~_BV(PC1);
11
>     DDRC &= ~_BV(PC0);
12
> 
13
>     PORTC |= _BV(PC0);
14
>     for(i=0; i<255 && !(PINC & _BV(PC0)); i++)
15
>     {
16
>         DDRC |=  _BV(PC0);
17
>         _delay_us(5);
18
>         DDRC &= ~_BV(PC0);
19
>         DDRC |=  _BV(PC1);
20
>         _delay_us(20);
21
>         DDRC &= ~_BV(PC1);
22
>     }
23
>     DDRC |= _BV(PC1);
24
>     DDRC |= _BV(PC0);
25
>     PORTC = 0x00;
26
> 
27
>     return i;
28
> }
29
>


Könntest du vielleicht mal das Funktionsprinzip genauer erklären oder 
den genauen Status der Pins darstellen? Der C-Code ist zwar interessant 
aber ich würde gerne das Funktionsprinzip generell verstehen, also wo 
die Ladungen hingehen usw.
Leider fehlen bei deiner Erklärung auch einige Teile die zum Verständnis 
notwendig sind, sprich ich verstehe das nicht komplett.


Roland

von Peter D. (peda)


Lesenswert?

So, hier mal mein Beispiel, vorausgesetzt, ich habe das Prinzip richtig 
verstanden:
1
#include <atomic.h>
2
#include "mydefs.h"
3
4
#define MAX_CYCLE       1000
5
6
#define SENSKEY_A0      SBIT( PORTB, 0 )        // connect to senspad
7
#define SENSKEY_A0_DDR  SBIT( DDRB,  0 )
8
9
#define SENSKEY_B0      SBIT( PORTB, 1 )        // connect to cap to A0
10
#define SENSKEY_B0_DDR  SBIT( DDRB,  1 )
11
#define SENSKEY_B0_PIN  SBIT( PINB,  1 )
12
13
/*
14
A0      B0      B0_PIN
15
0       0               full discharge
16
loop:
17
Z       Z               gap
18
Z       1               partial charge over pin A0 and senspad
19
Z       Z               gab
20
0       Z               partial charge over pin B0 only
21
0       Z       1       end
22
*/
23
24
uint16_t read_senskey( void )
25
{
26
  uint16_t i = MAX_CYCLE + 1;
27
28
  SENSKEY_A0 = 0;
29
  SENSKEY_A0_DDR = 1;
30
  SENSKEY_B0 = 0;
31
  SENSKEY_B0_DDR = 1;           // discharge cap
32
33
  ATOMIC_BLOCK(ATOMIC_FORCEON){
34
    do{
35
      SENSKEY_A0_DDR = 0;       // A0 = tristate
36
      SENSKEY_B0 = 1;           // B0 = weak high
37
      SENSKEY_B0_DDR = 1;       // B0 = strong high
38
      SENSKEY_B0_DDR = 0;       // B0 = weak high
39
      SENSKEY_B0 = 0;           // B0 = tristate
40
      SENSKEY_A0_DDR = 1;       // A0 = strong low
41
      if( --i == 0 )
42
        break;                          // timeout
43
    }while( SENSKEY_B0_PIN == 0 );      // until charged
44
  }
45
  SENSKEY_B0_DDR = 1;           // discharge cap
46
  return MAX_CYCLE - i;         // big value = key touched or timeout
47
}

Ich habe es etwas geändert.
Es wird der Pin eingelesen, der nicht mit dem Pad verbunden ist und 
während das Pad auf low gezogen wird. Damit können Störungen auf dem Pad 
nicht die Lesung beeinflussen.


Das Prinzip ist das eines Treppengenerators, wie er z.B. früher zum 
Erzeugen des Fernsehtestbildes verwendet wurde. Interessant, wie man für 
altbekannte Schaltungen neue Einsatzfelder findet.


Peter

von Roland Z. (roland77)


Lesenswert?

@Peter Danneger,

heißt das du wertest die durch den Kondensator transportierte Ladung 
aus, bzw lässt den Ladezyklus so lange laufen bis der Pin als Logisch 1 
gelesen wird.
Klingt interessant, somit hat man keine Probleme bei Störverseuchter 
Umgebung auf die das Pad wie eine Antenne wirken würde....

Roland

von Joe (Gast)


Lesenswert?

@Roland:

Wird eigentlich alles schön in entsprechenden Dokumenten erklärt, wozu 
und wie das funktioniert, zb. in der TouchLib Doku:

The QTouch™ acquisition method charges an electrode of unknown 
capacitance to a known potential. The resulting charge is transferred 
into a measurement capacitor (Cs). The cycle is repeated until the 
voltage across Cs reaches a voltage. The signal level is the number of 
charge transfer cycles it took to reach the voltage. Placing a finger on 
the touch surface introduces external capacitance that increases the 
amount of charge transferred each cycle, reducing the total number of 
cycles required for Cs to reach the voltage. When the signal level 
(number of cycles) goes below the present threshold, then the sensor is 
reported as in detect.


Aber am besten wenn man sich erstmal das Design Guide reinzieht. QMatrix 
ist da natürlich viel robuster.

http://www.atmel.com/dyn/resources/prod_documents/doc10620.pdf

http://www.atmel.com/dyn/products/app_notes_touch.asp?family_id=697

Und immer schön das Routing beachten ;-)

von Roland Z. (roland77)


Lesenswert?

@Joe,

Das Design Guide habe ich gelesen, würde ich das genaue Funktionsprinzip 
verstehen, würde ich hier ja nicht fragen. Mir will einfach nicht in den 
Kopf wie der verdammte Kondensator Cs funktioniert, also wie das mit der 
Ladungsmengenmessung funktioniert. Auf welcher seite des Kondensators 
messe ich die Ladung und wie kommt die dahin? Sinn würde es ja nur 
machen wenn man an PC1 (auf mein obriges Bild bezogen) Messen würde, nur 
wie muss sich dieser Pin während des Ladezyklus verhalten? Dauernd als 
Eingang Schalten und warten bis er logisch 1 wird? Meine Frage ist wie 
und wo kommt die Ladung in den Kondensator und an welchem Pin messe ich 
das.
Dein zitierter Text von Atmel ist etwas allgemein gehalten, es wird 
nicht darauf eingegangen wie die Ladung in den Kondensator kommt und 
welche Zustände die beteiligten Pins einnehmen.
Es geht mir um das GENAUE Funktionsprinzip, nicht um das allgemeine, da 
ich das Verstehen will. ;-)

Nachtrag: Mit dem Routing hast du recht, habe mal bei der Verwendung des 
QT100 seltsame Fehler in der Schaltung gehabt. Schlussendlich lags am 
Routing, waren zwei "heisse" Leiterbahnen zu dicht beisammen... So kanns 
gehen.

Roland

von Tim (Gast)


Lesenswert?

Habe die Schaltung gerade mal aufgebaut und es funktioniert.
Dank an Andreas Auer (und alle anderen).

@Roland Z.:
Im Prinzip hast du 2 Kondesatoren:
Cs als Speicher und die "Touch" Electrode gegen Erde.
Am Anfang werden beide entladen.
In einer Schleife wird dann zuerst der Touch Kondensator
über PB1 aufgeladen (Hat nur wenige pf). Der Port PC1
ist als Eingang geschaltet damit in den Cs kein Strom
fließen kann. Es wird kurz gewartet.
PB1 wird als Eingang konfiguriert und PC1 als Ausgang mit
0V. Jetzt wandert die Ladung aus dem Touch Kondensator
in Cs (welcher viel grösser ist und sich nur gering auflädt).
Es wird gewartet damit die Elektronen wandern können.
Wenn die Spannung am Cs ausreicht um vom AVR als 1 gelesen
zu werden wird die Schleife beendet.
Wenn nicht PC1 wieder als Eingang konfigurieren (Cs in die
Luft hängen) und Schleife von vorne.

Mit dem Touch Kondensator wird also Cs aufgepumpt.
Die Anzahl der Pumpvorgänge hängt von der "Größe"
des Touch Kondensator ab. Und die wiederum von seiner
Umgebung (Finger).

Man darf aber nur die Änderungen des Schleifenzählers auswerten und
nicht den Absoluten Wert, der ist nicht langzeit stabil.

Wichtig ist das die Pullups des AVR AUS sind (siehe SFIOR).

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Peter Dannegger schrieb:
> @Travel Rec.
>
> Die Eingänge werden digital eingelesen, d.h. eine Drift der
> Eingangsschwelle spielt keine Rolle?

Durch den implementierten Tiefpaß spielt das keine Rolle.

> Die Eingänge werden eingelesen, wenn alles tristate ist, muß das dann
> nicht sauempfindlich gegen HF-Störungen sein?

Nö. Ich werte die Spannung im Cs aus, da gibt´s keine HF

> Und der Eingang, der später eingelesen wird, müßte störempfindlicher
> sein.
> Sollte man nicht besser erst die SBIS-Befehle machen und danach das
> ADIW?

Konnte keinen Unterscheid feststellen, müßte man mal mit noch mehr 
Tasten testen.

>
> Könnte man die Schleife nicht schon abbrechen, wenn beide Eingänge low
> sind?

Ja, aber das verändert die Laufzeit des Programms bei jedem Zyklus. So 
kann man die Meßzyklen quasi auch als Timer für die nachgeschalteten 
Tiefpässe nehmen -> starre Kopplung.

> Können die 33nF Keramik sein?
> Wenn ja, die haben ja große Toleranzen und Drift, wirkt sich das auf die
> Werte der beiden Tasten aus?
> D.h. können die stark unterschiedlich sein?

Kein Problem. Tiefpaß und dynamische Auswertung der Abweichung vom 
Mittelwert rechnen Toleranzen heraus. Zwischen 22n und 47n gab es keinen 
nennenswerten Unterschied.

> Die Ausgänge TOUCH1A/2A werden nirgends gesetzt, müssen sie low sein,
> oder ist das egal?

Die sind immer low. Sorry.


> Vom Prinzip her erinnert mich das an nen DAC mit geschalteten
> Kondensatoren. Der Unterschied ist nur, daß beide Kondensatoren nicht
> gleich groß sind, sondern stark unterschiedlich.
> Das Prinzip hat man früher auch als Rampengenerator verwendet (ein
> kleiner Kondensator lädt kleine Ladungen auf einen großen).

Ja, kann man so sagen.

> Letztendlich ist also auch eine Kapazitätsmessung. Die Frage ist nur,
> welcher Unterschied sich bezüglich Bauelementedrift und Störspannungen
> gegenüber anderen Meßmethoden ergibt.

Meinen Langzeittest hat die Schaltung schon überstanden. Läuft seit 
August in unserem Badezimmer ;-)


>Ich habe es etwas geändert.
>Es wird der Pin eingelesen, der nicht mit dem Pad verbunden ist und
>während das Pad auf low gezogen wird. Damit können Störungen auf dem Pad
>nicht die Lesung beeinflussen.

Mache ich doch auch :-)

von Joe (Gast)


Angehängte Dateien:

Lesenswert?

Im Prinzip wurde es eigentlich schon erklärt, hier nochmal zum 
Nachvollziehen:

Cs >> Cx : z.B. Cs = 10nF, Cx = 10pF  (1000:1 ratio)
S1,S2 und S3 sind ja CMOS IO pins. Wenn man S1,S2 und S3 richtig 
kontrolliert, kann man die Ladung in den Cx über Cs transferrieren. 
Indem man das einige Male wiederholt, kann man Cx messen. Wobei messen 
hier heißt eine relative Messung z.b. Änderung in Cx (delta Cx). Die 
TouchLib wird hier z.b. so eingestellt, das ein delta Cx von 10 
ausreicht, um ein Touch zu erkennen.

Jetzt gehts tiefer ins Detail:

1. S1: closed, S2: open, S3: closed -> Cx und Cs entladen
2. S1: open,   S2: open, S3: open   -> Float Cs
3. S1: open,   S2: closed, S3: open -> Charge transfer
4. S1: open,   S2: open, S3: open   -> Float Cs / erlaubt settling time
5. S1: closed, S2: open, S3: open   -> Vcs messen und Cx entladen
Nun wird bei 2 weitergemacht.

#1: Initialisierung, start der Akquisation (braucht etwas Zeit)
#2: Verhindert Durchfluß zwischen P und N-Kanal Transistor in der IO 
Zelle
    Sog. "Cross conduction ist ein Desaster für die Konservierung der 
Ladung im Cs!
#3 Steigende Flanke am SNS Pin treibt die Ladung durch den Cs in den Cx
    Das Kirchoffsche Gesetzt sagt, das derselbe Strom durch Cs und Cx 
fließen muß, also ist die Ladung in beiden C dieselbe
#4 Wie bei 2
#5 Entladen des Cx durch das Einspannen des SNSK zu GND, der Vcs auf dem 
SNS pin wird gemessen. Cs Ladung hat sich erhöht und wurde 
"konserviert".
Die Wiederholung führt nun dazu dass die Ladung aus dem Cx in den Cs 
gepumpt wird. Man stellt sich einfach einen großen Behälter vor, einen 
kleinen Behälter füllt man nun mit Wasser und gießt das Wasser aus dem 
kleinen Behälter in den großen. Das wiederholt man nun ein paar male.

Wenn man nun die Sensorfläche berührt, werden weniger Pulse benötigt, 
die "burst time" ist kürzer. Wenn das Delta groß genug ist, wird ein 
Touch als "erkannt" gemeldet.

Fangfrage: Was passiert wenn man etwas Wasser auf die Sensorfläche 
drübergießt? ;-)

von Roland Z. (roland77)


Lesenswert?

@Joe,

ahhhh, danke für die Ausfühliche Erklärung, jetzt hats bei mir "klick" 
gemacht. Wenn man das mal Verstanden hat ist es eigentlich sehr einfach 
das Prinzip. Maximaler Effekt bei wenig externen Bauteilen... Da haben 
bei Qantum sicherlich etlichen Entwicklern Wochenlang die Köpfe geraucht 
als die das Prinzip erstellt haben... ;-)

Zur Fangfrage mit dem Wasser:
Ich könnte mir vorstellen das der Sensor dann "betätigt" meldet, da das 
Wasser ja auch die Kapazität der Sensorplatte erhöht. Liege ich richtig?

@Tim,

auch dir Danke für die Erklärung, die hat mir geholfen das ganze mal zu 
Testzwekcne in einen Tiny13 zu integrieren (zwei-Kanalig). Ist zwar noch 
ne Baustelle aber "gut Ding will weile haben" frei Nach Brösels Werner. 
:-))

Roland

von Peter D. (peda)


Lesenswert?

Nachdem nun die Wirkungsweise des Qtouch klar ist, stellt sich immer 
noch die Frage, welche und warum sie Vorteile gegenüber anderen Methoden 
der Kapazitätsmessung haben soll?

Sie hat zumindest einige Nachteile:
- es werden 2 IO-Pins benötigt
- es erfolgt eine größere Störaussendung auf den Sensor
- die Messung dauert länger und muß unter Interruptsperre erfolgen.

Wenn man sich die verschiedenen Applikationen bei Atmel ansieht, fällt 
auch auf, welchen entscheidenden Einfluß der mechanische und elektrische 
Aufbau auf die Eigenschaften hat. Warscheinlich ist dieser viel größer, 
als der Einfluß der Meßmethode.
Ich hätte z.B. nicht vermutet, daß eine LED nahe dem Sensor die Messung 
stören kann.


Peter

von Simon K. (simon) Benutzerseite


Lesenswert?

Noch eine Frage. Der Kondensator Cx, wo genau befindet der sich? Ist das 
der menschliche Körper? Oder ist der Körper die eine Platte des 
Kondensators und die Kontaktfläche die andere Platte?
Wenn der Charge Transfer stattfindet, wird ja die Ladung "ausgeglichen", 
sodass beide Kondensatoren die gleiche Ladung haben. Wenn dann die 
Kondensatoren wieder auf hochohmig geschaltet werden, wer lädt dann Cx 
wieder auf? Der menschliche Körper?

Der Vorteil liegt denke ich mal darin, dass man nicht zwingend das 
Gebilde als Schalter nutzen muss, sondern auch zum Beispiel als Touchpad 
nutzen kann (Indem man die Ladung im Cs misst und nicht auf einen 
Komparator gibt).
Oder man kann so Ipod-Like Slider damit machen.

von Peter D. (peda)


Lesenswert?

So, ich hab mal beide Methoden ausprobiert, die Ladungspumpe (Qtouch) 
und die Messung der Entladezeit über einen Widerstand.
Im Prinzip gehen beide, aber die Qtouch-Methode ist deutlich 
störunempfindlicher, d.h. die Auslesungen sind sehr stabil.
Bedingt wird das durch die Tiefpaßwirkung des Integrationskondensators 
und durch die Abtastung bei kurzgeschlossenem Sensorpad.

Ich hab die Schaltung allerdings auch unter verschärften Bedingungen 
getestet, am Notebook, welches keinen Schukostecker hat, d.h. die ganze 
Schaltung liegt auf 115V 50Hz gegen Erde (durch die Filter-Kondies vorm 
Schaltnetzteil).

Das Qtouch ist also doch nicht nur Selters.

Ich hab 2 * 1,8k und nen 10nF genommen. Die Sensorfläche sind 4*4 Pads 
einer Rasterplatine, Berührung auf der Bestückungsseite.
Es ergeben sich 382 Counts ungedrückt und 352 Counts gedrückt.


Peter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Mit einem größeren Integrations-C bekommst Du noch etwas weiter 
auseinanderliegende Auslesungen für Touch und kein Touch, 22...33nF sind 
optimal für 10Bit Auflösung. Hierbei können die Sensorflächen auch 
größer sein.

von Waldgichtel (Gast)


Lesenswert?

Guten Mittag,

sorry dass ich dieses Thema hier nochmal rausziehe nur eine Frage habe 
ich noch. Das Funktionsprinzip habe ich glaube ich soweit verstanden.
Nur hat es eine besondere Bewandniss dass für die beiden Pins zwei 
unterschiedliche Ports verwendet werden?
Würde das gerne auf einem Atiny25 programmieren, da habe ich nur einen 
Port zur Verfügung.

Vielen Dank schonmal.

Toni

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ist einfacher anzusprechen, wenn die Pinne auf demselben Bit liegen, 
geht natürlich auch mit einem einzigen Port.

von Björn (Gast)


Lesenswert?

Wie kann man auf einer Lochrasterplatine einen Einfachen Touchsensor 
nachempfinden? Bekommt man auch einen Slider hin?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Um sicher zu gehen, sollte man die Design-Guides von ATMEL/Quantum 
befolgen.

von Björn (Gast)


Lesenswert?

@Peter Dannegger:
Wie sieht denn dein SBIT Makro aus?

von Peter D. (peda)


Lesenswert?

Björn schrieb:
> @Peter Dannegger:
> Wie sieht denn dein SBIT Makro aus?

Z.B.:

Beitrag "AVR-GCC Power-Down Tutorial"


Peter

von Björn (Gast)


Lesenswert?

Danke.

Ich habe ein Pad aus 3x3 Lochrasterpunkten gemacht.


uC ------ 1K ---- Pad
     |
     |
    22nF
     |
     |
uC ---

Den 1k Widerstand und den 22nF habe ich als SMD Bauteile nahe ans Pad 
gemacht und dann per Freiluftverdrahtung an den Controller 
angeschlossen.
Am empfindlichsten ist die Fläche zwischen Pad und den beiden Bauteilen.
Auch die Leitung ist touchsensitiv, aber das steht ja schon in der 
Appnote.
Mal sehen, ob man das so für irgendwas verwenden kann...

von Waldgichtel (Gast)


Angehängte Dateien:

Lesenswert?

Guten Abend,

hab mich die letzten Tage auch nochmal daran versucht ... aber ich komme 
auf keinen grünen Zweig :(. Ich wollte das ganze mit einem 
Timerinterrupt programmieren, damit ich nicht die vielen delays 
verwenden muss.

Habe mich dazu an die Beschreibung von Roland Z und  Andreas Auer 
gehalten. Nach dieser Beschreibung habe ich auch das Prinzip verstanden.

Jetzt frag ich mich bzw euch: wo habe ich den Fehler gemacht :) .. die 
einzelden Schritte macht mein asm Programm in der Simulation genau 
gleich wie der obige C-Code :/. Habe versucht alles möglichst 
ausführlich zu kommentieren  ...  viel. entdeckt von euch jeamnd einen 
Fehler :/ Mir gehen langsam die Ideen aus.

Die anzahl der Pulse beträgt immer 1 :/ ich versteh beim besten willen 
nicht warum :(.

Schönen Abend noch.

Toni

von Peter D. (peda)


Lesenswert?

Ich glaube nicht, daß das mit nem Timerinterrupt funktioniert.
Das sind ja nur sehr kleine Ladungen, wenn man da zu langsam schaltet, 
ist die Selbstentladung zu hoch.

Es reichen die Delays durch die Ausführungszeit der Meßloop vollkommen 
aus, um die wenigen pF umzuladen.
Nur für die Entladung des 33nF bis zur nächsten Messung sollte man etwas 
Zeit lassen.

Hier noch ein Beispiel für 3 Tasten:
1
#include <avr\io.h>
2
#include <util\atomic.h>
3
4
5
#define SK_A0   (1<<5)
6
#define SK_B0   (1<<4)
7
#define SK_A1   (1<<2)
8
#define SK_B1   (1<<3)
9
#define SK_A2   (1<<0)
10
#define SK_B2   (1<<1)
11
12
#define SK_A012 (SK_A0 | SK_A1 | SK_A2)
13
#define SK_B012 (SK_B0 | SK_B1 | SK_B2)
14
15
16
#define MAX_CYCLE       2000
17
18
19
uint16_t keys[3];
20
21
22
void read_senskey( void )
23
{
24
  uint16_t i = MAX_CYCLE;
25
  uint8_t a, b, x, y;
26
27
  ATOMIC_BLOCK(ATOMIC_FORCEON){
28
    a = DDRA  & ~(SK_A012 | SK_B012);
29
    b = PORTA & ~(SK_A012 | SK_B012);
30
    y = SK_B012;                        // input mask
31
    do{
32
      DDRA = a;                         // tristate
33
      PORTA = b | SK_B012;
34
      DDRA = a | SK_B012;               // Bx = strong high
35
      DDRA = a;                         // tristate
36
      PORTA = b;
37
      DDRA = a | SK_A012;               // Ax = strong low
38
      if( --i == 0 )                    // timeout
39
        break;
40
      x = y & PINA;                     // not immediately after set DDRA !!!
41
      if( x ){
42
        if( x & SK_B0 )
43
          keys[0] = i;
44
        if( x & SK_B1 )
45
          keys[1] = i;
46
        if( x & SK_B2 )
47
          keys[2] = i;
48
      }
49
      y ^= x;                           // clear processed input
50
    }while( y );                        // all inputs done
51
    DDRA = a | SK_A012 | SK_B012;       // discharge
52
  }
53
}


Peter

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Hi,

hab mir jetzt mal eine Platine gemacht mit 3 Touchelementen (ca. 
15x15mm² Touchfläche pro Element, 33n Messkondensator, 1k 
Serienwiderstand zur Touchfläche) drauf. Funktioniert grundsätzlich 
auch. Sehr gut funktioniert es natürlich wenn man direkt die durch 
Lötstopplack geschützten Flächen berührt. Jedoch sinkt die 
Empfindlichkeit drastisch, wenn man die Touchfläche hinter anderen 
Materialien anbringt, sodass es kaum mehr möglich ist die Berührung zu 
detektieren.

Deshalb wollt ich euch mal fragen wie eure Erfahrungen sind. Ich hab 
gestern mal die Wirkung meines Fingers durch ein paar Materialien 
untersucht (ein paar Seiten Papier, Cover einer CD) und war etwas 
enttäuscht, da ich meist nur noch eine ganz geringe Änderung (Delta im 
Bereich von 1 oder 2) messen konnte.

Ich wollte die Platine eigentlich hinter einer dünnen Plexiglasscheibe 
montieren. Hat jemand sowas schonmal gemacht?? Wäre für jeden Tipp zur 
Verbesserung dankbar!

mfg
Andreas

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Andreas Auer schrieb:
> Deshalb wollt ich euch mal fragen wie eure Erfahrungen sind. Ich hab
> gestern mal die Wirkung meines Fingers durch ein paar Materialien
> untersucht (ein paar Seiten Papier, Cover einer CD) und war etwas
> enttäuscht, da ich meist nur noch eine ganz geringe Änderung (Delta im
> Bereich von 1 oder 2) messen konnte.
>
> Ich wollte die Platine eigentlich hinter einer dünnen Plexiglasscheibe
> montieren. Hat jemand sowas schonmal gemacht?? Wäre für jeden Tipp zur
> Verbesserung dankbar!

Beitrag "Re: qtouch - sekt oder selters"

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Versteh ich nicht, warum das bei mir durch ein Stück Kunststoff schon 
nicht mehr klappt. Wie groß ist dein Kondensator??

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

33nF.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Also gleiche Kapazität wie ich... interessant...

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Und du hast auch einen Serienwiderstand zum Touchpad drin!? Bzw. deine 
Schaltung sieht wie folgt aus??

                             ------           ----
PORTx   -----------+--------|______|---------|    | Touchpad
                   |           R             |____|
                 ----- C
                 -----
                   |
PORTy   -----------+

Danke,
Andreas

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Nicht ganz. Ich habe noch ein zusätzliches R zwischen Portx und C, Wert 
ist 2.2k. Der Widerstand zum Touchpanel ist bei mir 10k.

von Stefan V. (vollmars)


Lesenswert?

Hi all,

bin gerade auf diesen Thread gestoßen und gleich eine Frage:

Travel Rec. schrieb:
> Nicht ganz. Ich habe noch ein zusätzliches R zwischen Portx und C, Wert
> ist 2.2k. Der Widerstand zum Touchpanel ist bei mir 10k.

Wozu dient dieser Widerstand, Strombegrenzung beim Entladen?

Gruß Stefan

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Der Widerstand macht den nutzbaren Bereich  bei der Zeit-/Pegelmessung 
größer. Zu viel R verringert aber die Empfindlichkeit.

von Peter D. (peda)


Lesenswert?

Die Widerstände dienen hauptsächlich zur Verringerung von 
Störaussendung.
Es müßte auch ganz ohne Widerstände gehen, d.h. 0 Ohm.


Peter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Natürlich geht es ohne die Widerstände. Aber durch den niedrigen 
Portinnenwiderstand ist der Transfer-C dann sehr schnell aufgeladen und 
es traten mehr Rauschanteile im Meßsignal aus. Das R zwischen Port und C 
brachte sehr viel mehr Ruhe und eine größere Meßauflösung. Das R zur 
Taste ist zum Dämpfen der Störaussendung und Verhindern von statischen 
Entladungen in die Portpins gedacht. Wie gesagt.

von Kr2 K. (kr2)


Angehängte Dateien:

Lesenswert?

Hallo,

ich hab das ganze mal aufgebaut und mit dem code von  Andreas Auer 
versucht. Das hat nicht funktioniert, nach einigen messungen und kleinen 
anpassungen wurd es schon besser.

Mein problem ist ich bekomme nur einen unterschied von 1 bei berührung.

Mein erster aufbau war mit bedrahtetetn bauelementen, um das 
auszuschliesen habe ich jetz das ganze in smd aufgebaut, was leider 
keine verbesserung brachte.

Wenn ich den code ohne abruchbedingung (code zeile 111 sieht dann so aus 
}while(i<510); ), laufen lasse und mir das ganze am osziloskop ansehe 
ändert sich die Kurve bei berührung nur sehr gering.


noch kurtz zum aufbau:
- µC: Atmega8
- Touch fläche: ca. 15x15 mm mit tesa abgeklebt.
- Die messungen in den bildern habe ich zwischen GND und dem im 
Schematic eingezeichnetetn messpunkt gemacht.
- Auf dem Osziloskop ist die untere kurve PB1 und kurzz nach der 
steigenden flanke wird TA ausgewertet.

Nun meine frage hat jemand eine idee an was das liegen könnte?

Danke im voraus.

mfg
kr2

von Peter D. (peda)


Angehängte Dateien:

Lesenswert?

Hier mal meine Testschaltung.

Software:

Beitrag "Re: qtouch - sekt oder selters"

Dimensionierung, Ergebnisse:

Beitrag "Re: qtouch - sekt oder selters"

Berührt wird auf der Oberseite (rotes Klebeband), d.h. durch die Platine 
hindurch.


Peter

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Ich finde die Peaks ziemlich breit, mehr als 200ns sollten sie nicht 
sein, sonst ist der Speicherkondensator zu schnell voll. Deshalb ergibt 
sich eine relative Unempfindlichkeit. Du brauchst mindestens 256 Pulse 
(8-Bit) Auflösung, bis der Kondensator so weit geladen ist, daß der Pin 
kippt. Die Pausen zwischen den Peaks ist auch recht lang, so daß sich 
eine unnötig lange Meßzeit ergibt.

von Peter D. (peda)


Lesenswert?

Ob das Timing kritisch ist, kann man überprüfen, indem man den CPU-Takt 
halbiert (CLKPR entsprechend setzen).
Die Zählwerte dürfen sich nur wenig ändern.


Peter

von Lutz Koppe (Gast)


Lesenswert?

Hi,

sehe ich das richtig, das man für dieses Projekt

1 Atmega8,
2 Kondensatoren von 22nF,
1 10K Widerstand und
eine Touchfläche von 15x15mm

benötigt.

Und ist der Code in C oder Bascom geschrieben. Wie gesagt habe ich noch 
nicht viel am Hut mit proggen usw.

Wieviel Strom wird bei der Schaltung benötigt? Wären da auch mehrere 
Flächen möglich. Habe irgendwo mal gehört, das der Mega nur einen 
gewissen Strom aufnimmt (abgibt)von ca 100mA.

LG Lutz

von Sebi (Gast)


Lesenswert?

hallo allerseits, ich würde gerne ein touch wheel verwirklichen und
wollte mal fragen ob irgendjemand ein layout zur verfügung stellen
könnte...
habe hier nur eine datei gefunden wo schon die fertigen gerberdaten
vorhanden waren.... wäre echt super
schönen gruß sebi

von Thorsten S. (thosch)


Lesenswert?

Moin,

Du hast schon Gerberdaten? Wo ist dann das Problem?
Das nach einem Gerber-Plot im Layoutprogramm der Wahl nachzubauen, 
sollte doch nicht wirklich schwierig sein.
ggf. lassen sich die Daten sogar auf irgendeinem Weg als Vektorsymbol 
ins Layoutprogramm importieren...

Zusätzlich würde ich noch einen Blick in das 
Touch_Sensors_Design_Guide von Atmel werfen: 
http://www.atmel.com/dyn/resources/prod_documents/doc10620.pdf
die gehen darin auch auf Probleme wie den ESD-Schutz ein.

Nachtrag: Für EAGLE gibts ein Tool, um Grafikdaten in diversen Formaten 
(auch Gerber) zu importieren: EAGLE PCB Power Tools V5.06 -> 
http://www.cadsoft.de/cgi-bin/download.pl?page=/home/cadsoft/html_public/download.htm.de&dir=eagle/userfiles/misc

Gruß,
Thorsten

von Sebi (Gast)


Lesenswert?

danke für die schnelle antwort, dachte nur dass jemand dass vl als pcb 
layout hat...
das mit dem importieren klappt dann wohl bei mir nicht da ich nicht mit 
eagle arbeite...
dann muss ich es wohl selbst zeichnen...
gruß sebi

von Martin (Gast)


Lesenswert?

... wäre echt super ...

Was ist mit deiner Shifttaste?

von Arne G. (kywalda)


Lesenswert?

Hier der Versuch, die qtouch-Variante in Bascom umzusetzen.
1
$regfile = "m8def.dat"
2
$crystal = 8e6
3
$baud = 9600
4
5
$hwstack = 32                 ' default use 32 for the hardware stack
6
$swstack = 32                 ' default use 10 for the SW stack
7
$framesize =                  ' default use 40 for the frame space
8
9
Dim Cycles As Byte
10
11
'PC5--- 2K2 ---+---- 100K ---- Touchpad
12
'              |
13
'             ---
14
'             --- 22n
15
'              |
16
'PC4-----------+
17
18
Do
19
Cycles = 0
20
21
'Alles Entladen
22
'beide out - beide low
23
Ddrc.5 = 1 : Portc.5 = 0
24
Ddrc.4 = 1 : Portc.4 = 0
25
26
'auf vollstaendige Entladung warten
27
Waitus 5
28
29
   Do
30
31
   'beide als tristate inp schalten, damit keine Ladung abfliessen kann
32
   Ddrc.5 = 0 : Portc.5 = 0
33
   Ddrc.4 = 0 : Portc.4 = 0
34
   Waitus 5
35
36
   'PC4 Out und high schalten, um C aufzuladen
37
   Ddrc.4 = 1 : Portc.4 = 1
38
   Waitus 2
39
40
   'und wieder aus
41
   Ddrc.4 = 0 : Portc.4 = 0
42
43
   'Die Ladung aus C jetzt nach PD5 auf GND abfuehren
44
   Ddrc.5 = 1 : Portc.5 = 0
45
46
   'messen, ob Ladung schon fuer eine 1 an PD4 reicht, sonst von vorn
47
   If Pinc.4 = 1 Then Goto Printout
48
   Incr Cycles
49
50
   Loop Until Cycles >= 254        'wiederholen und im Zweifel beenden
51
52
Printout:
53
Print Cycles
54
Waitms 100
55
56
Loop

Es ergeben sich Werte zwischen 15 und 25 ungedrückt und 40 - 80 gedrückt 
(Direkter Kontakt).

Als Sensor verwende ich eine Kotflügelscheibe mit 30mm Durchmesser.

Allerdings ergibt sich bei Verwendung einer isolierenden Folie kaum noch 
ein messbarer Ausschlag.

lg,
arne

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

ich hab das ganze grade mal schnell aufgebaut.

ein kurzes video findet man auf Youtube:
http://www.youtube.com/watch?v=z3nLNGeyadU

Aufbau:
- Schaltung auf der Rückseite von einer Lochrasterplatine
- Vorderseite Tastenlayout mit Papier beklebt
                             ------           ----
PORTx   -----------+--------|______|---------|    | Touchpad 4x4 
Lötraster
                   |        R = 1Kohm        |____|
                 -----
                 -----  C = 33nF
                   |
PORTy   -----------+

Code von peter Dannegger:
1
include <avr\io.h>
2
#include <util\atomic.h>
3
4
#define SK_A0   (1<<5)
5
#define SK_B0   (1<<4)
6
#define SK_A1   (1<<2)
7
#define SK_B1   (1<<3)
8
#define SK_A2   (1<<0)
9
#define SK_B2   (1<<1)
10
#define SK_A012 (SK_A0 | SK_A1 | SK_A2)
11
#define SK_B012 (SK_B0 | SK_B1 | SK_B2)
12
#define MAX_CYCLE       2000
13
14
uint16_t keys[3];
15
16
void read_senskey( void )
17
{
18
  uint16_t i = MAX_CYCLE;
19
  uint8_t a, b, x, y;
20
21
  ATOMIC_BLOCK(ATOMIC_FORCEON){
22
    a = DDRA  & ~(SK_A012 | SK_B012);
23
    b = PORTA & ~(SK_A012 | SK_B012);
24
    y = SK_B012;                        // input mask
25
    do{
26
      DDRA = a;                         // tristate
27
      PORTA = b | SK_B012;
28
      DDRA = a | SK_B012;               // Bx = strong high
29
      DDRA = a;                         // tristate
30
      PORTA = b;
31
      DDRA = a | SK_A012;               // Ax = strong low
32
      if( --i == 0 )                    // timeout
33
        break;
34
      x = y & PINA;                     // not immediately after set DDRA !!!
35
      if( x ){
36
        if( x & SK_B0 )
37
          keys[0] = i;
38
        if( x & SK_B1 )
39
          keys[1] = i;
40
        if( x & SK_B2 )
41
          keys[2] = i;
42
      }
43
      y ^= x;                           // clear processed input
44
    }while( y );                        // all inputs done
45
    DDRA = a | SK_A012 | SK_B012;       // discharge
46
  }
47
}

Funktioniert super!!

Es funktioniert auch, wenn ich zwischen den Tasten und meinem Finger 
noch eine 3mm Plexiglasscheibe lege.
Die Scheibe sollte dafür mit auf die Lochrasterplatine geklebt sein --> 
also kein Luftspalt, wegen Ladungsausbreitung

Eine genaue Beschreibeung folgt dann auch noch bald.

martin

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

noch'n Bild :-)

von Fred (Gast)


Lesenswert?

Hi Martin,

tolle Sache dein Touchfeld.
Könntest du bitte deinen Quellcode (auch den Rest) zeigen, denn 
irgendwie will das ganze bei mir nicht so recht funktionieren. Mit 
welchem Takt läuft dein System?

MFG Fred

von Martin J. (bluematrix) Benutzerseite


Angehängte Dateien:

Lesenswert?

Das hier ist der Code für die Auswertung der 3 tasten.

hat jemand eine Idee wie man am besten und einfachsten solch ein 
Touch-Scrollrad sinnvoll auswerten kann?
Die einzelnen Sensoren funktionieren.
Ist ein Sensorfeld betätigt, also aktiv, so wird bei der Abfrage eine 1 
zurückgegeben, ansonsten eine 0.

Das Scrollrad besteht aus 9 einzelnen Touchsensoren.

Ich habe mir zwar schon einige Gedanken gemacht, aber so richtig bin ich 
auf noch keine Idee gekommen, wie es am besten gehen könnte.

Danke martin

von Fred (Gast)


Lesenswert?

Hallo Martin,

vielen dank für den Code.
Hat mir sehr geholfen, es läuft jetzt.

MFG Fred

von Patrick (Gast)


Lesenswert?

Hat jemand schon das Altium Touch Design Package für QTouch im Einsatz? 
Hat zwar einen stolzen Preis, ist aber für den professionellen Einsatz 
bestimm interessant.

http://www.altium.com/atmel-touch/en/atmel-touch_home.cfm

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

is mir dann doch etwas zu teuer ;-)

aber ne idee zum auswerten von solch einem Touch Scrollrad hat wohl 
keiner?
--> Das Scrollrad besteht aus 9 einzelnen Touchsensoren.Ist ein 
Sensorfeld
    betätigt, also aktiv, so wird bei der Abfrage eine 1 zurückgegeben,
    ansonsten eine 0.

Ich hab grade noch eine Autokallibrierung für Touchsensoren hinzugefügt.
Die Basis bildet eine gleitende Mittelwertberechnung der Sensorwerte, 
wenn der Sensor nicht aktiv ist.

--> Sensor aktiv = Messung > kallibrier_Mittelwert + 20;

Code muss ncoh bisschen überarbeitet werden.

Bis dann

über Ideen zu dem Scrollrad würd ich mcih freuen.

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

wegen dem nicht grad aussagekräftigen Namen habe ich einen neuen Thread 
aufgemacht...
Beitrag "kapazitiver Touch Sensor - Slider - Wheel"

von Johnny B. (johnnyb)


Lesenswert?

Hallo zusammen

Hab gerade die Sache auf einem MSP430 zum laufen gekriegt und endlich 
mal das "eZ430-F2013 Development Tool" einsetzen können, welches schon 
seit Jahren im Schrank verstaubt...

Dankeschön an alle die ihre Erfahrungen hier geteilt haben!

Habe übrigens auch die Schaltung mit dem 1k Widerstand und 33n 
Kondensator verwendet.

von Andi (Gast)


Lesenswert?

Hier mal in Bascom geht durch 2mm Glas
1
$regfile = "m8def.dat"
2
$crystal = 8000000
3
$hwstack = 54                                               ' default use 32 for the hardware stack
4
$swstack = 20                                               'default use 10 for the SW stack
5
$framesize = 40                                             'default use 40 for the frame space
6
7
8
Senskey_a0 Alias Portb.0
9
Senskey_a0_ddr Alias Ddrb.0
10
11
Senskey_b0 Alias Portd.7
12
Senskey_b0_ddr Alias Ddrd.7
13
Senskey_b0_pin Alias Pind.7
14
15
16
17
Initlcd
18
19
20
Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.4 , Db6 = Portc.3 , Db7 = Portc.2 , E = Portc.1 , Rs = Portc.0
21
Config Lcd = 16 * 2
22
23
24
25
Cursor Off
26
Cls
27
Disable Interrupts
28
29
Wait 4
30
31
32
33
34
Dim Cycles As Byte
35
'Pb0--- 1K ---+-------- Touchpad
36
' |
37
' ---
38
' --- 22n
39
' |
40
'Pd7-----------+
41
Do
42
Cycles = 0
43
'Alles Entladen
44
'beide out - beide low
45
Senskey_a0_ddr = 1
46
Senskey_a0 = 0
47
  'Senskey_a0_ddr = 1
48
  Senskey_b0_ddr = 1
49
  Senskey_b0 = 0
50
51
'auf vollstaendige Entladung warten
52
'Waitus 5
53
Do
54
'beide als tristate inp schalten, damit keine Ladung abfliessen kann
55
      Senskey_a0_ddr = 0
56
      Senskey_b0 = 1
57
      Senskey_b0_ddr = 1
58
      Senskey_b0_ddr = 0
59
      Senskey_b0 = 0
60
      Senskey_a0_ddr = 1
61
62
'Waitus 5
63
                                                    'PC4 Out und high schalten, um C aufzuladen
64
'Ddrd.7 = 1 : Portd.7 = 1
65
'Waitms 25
66
'und wieder aus
67
'Ddrd.7 = 0 : Portd.7 = 0
68
'Die Ladung aus C jetzt nach PD5 auf GND abfuehren
69
70
'Ddrb.0 = 1 : Portb.0 = 0
71
'messen, ob Ladung schon fuer eine 1 an PD4 reicht, sonst von vorn
72
If Senskey_b0_pin = 1 Then Goto Printout
73
Incr Cycles
74
'cls
75
'Lcd Cycles ; "     "
76
Loop Until Cycles >= 254                                    'wiederholen und im Zweifel beenden
77
Printout:
78
Cls
79
Lcd Cycles ; "    "
80
Waitms 100
81
Senskey_b0_ddr = 1
82
Loop
83
84
End

von Marius (Gast)


Lesenswert?

Hab den Bascom-Code vom Andi mal auf meinem Atmega8 überspielt. Leider 
funktioniert das Ganze bei mir nicht.
Kann es sein, dass in dem Code viel zu viel auskommentiert wurde? z.b. 
wurden sämtliche Wartezeiten auskommentiert, was sicherlich nicht 
richtig sein kann. Nach dem Entladen muss man doch immer warten.

von Marius (Gast)


Lesenswert?

Muss mich korrigieren. Der Bascom-Code läuft ganz hervorragend. 
Allerdings musste ich "Cycles" als word deklarieren, weil es ungedrückt 
ca 410 ist.
Ansonsten dickes Dankeschön.

von Roger T. (elromeo)


Angehängte Dateien:

Lesenswert?

Ich habe die application notes und design guides von Quantum gelesen und 
habe nicht herausgefunden, ob man ohne weiteres auch multiplexer 
verwenden kann. Hat hier jemand erfahrungen gemacht?

Es geht mir vor allem darum auf einem grösseren Board Leiterbahnen 
einzusparen. Das PCB ist sehr lange, aber schmal und es sollten doch 
etwa 15 Tasten realisiert werden :-). Was passiert wohl mit dem Signal 
wenn ich 2 Mux hintereinander schalte, aber immer mit denselben Pins 
auslese?

Ich habe noch ein Symbolbild angehängt, MCU wäre ganz rechts auf dem 
PCB, der letzte Sensor ganz links. Die mux steuerleitungen könnten 
eventuell auch mit einem Schieberegister betrieben werden.

Grüsse

von Peter B. (Gast)


Lesenswert?

Hier wurde ja schon mehrfach die Funktionsweise von qtouch erklärt, doch
ist mir noch nicht ganz klar wie Cx in einer batteriebetriebenen 
Schaltung (also wo GND nicht Erde ist) aufgeladen werden kann. Wenn Cx 
aufgeladen wird müsste doch ein geschlossener Stromkreis existieren, was 
nach meinem Verständnis hier nicht der Fall ist. Bin dankbar, wenn mir 
jemand erklären könnte wie bzw. wodurch Cx aufgeladen wird.

Gruß

von Bernhard B. (schluchti)


Lesenswert?

Hat schon jemand versucht das Prinzip auf einen STM32 zu portieren?

von Stefan R. (droelf)


Lesenswert?

Übrigens, das Schöne an der Methode ist, die Umladungsschleife kann 
jederzeit für (relativ kurze Zeit) unterbrochen werden (durch 
Interrupts), ohne dass sich etwas ändert (da die Ladung ja erhalten 
bleibt, abgesehen von Leckströmen - deshalb ist die Zeit trotzdem kurz 
zu halten).
Ich habe mit dem usb-Stack von obdev auf einem attiny2313 eine simple 
usb-"Tastatur" (mit nur einer Taste) mit dem qtouch-Prinzip gebaut, es 
funktioniert einwandfrei, obwohl die Messroutine jederzeit vom 
einkommenden usb-Poll unterbrochen werden kann.

Gruß,
droelf

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

beschreibst du deinen aufbau ncoh etwas genauer mit bilder, zeichungen 
software .... ?

von Maxx (Gast)


Lesenswert?

Peter B. schrieb:
> Hier wurde ja schon mehrfach die Funktionsweise von qtouch erklärt, doch
> ist mir noch nicht ganz klar wie Cx in einer batteriebetriebenen
> Schaltung (also wo GND nicht Erde ist) aufgeladen werden kann. Wenn Cx
> aufgeladen wird müsste doch ein geschlossener Stromkreis existieren, was
> nach meinem Verständnis hier nicht der Fall ist.

Das ist auch nicht nötig.
Ein Kondensator speichert Elektrische Energie in einem el. Feld indem er 
Elektronen auf seinen Elektroden verteilt. Bis auf Nebeneffekte wandert 
kein Elektron durch einen Kondensator hindurch. Ein Kondensator ist also 
immer eine Unterbrechung des Stromkreises und es dürfte mit diesem 
klassischen Leitsatz zu keinem Strom kommen.

Durch den Potentialdruck werden aber auch den Elektroden die Elektronen 
näher zusammengeschoben, abhängig davon, wie sich die elektrischen 
Feldlinien ausbilden können. Das liegt an Form, Größe und Material und 
Ladung(~Potentialdruck) der Umgebung. Diese Veränderung wird über die 
Anzahl der Ladezyklen registriert. Der Strom fließt also "nur" weil sich 
Elektronen anders verteilen nicht, weil sie einem Kreislauf im 
herkömmlichen Sinne folgen. Ihre Menge bleibt innerhalb des Teilsystems 
gleich. Ein Ladungstransfer also Strom von System-qTouch und System-Erde 
findet nicht statt.

von Stefan R. (droelf)


Angehängte Dateien:

Lesenswert?

Martin J. schrieb:
> beschreibst du deinen aufbau ncoh etwas genauer mit bilder, zeichungen
> software .... ?

Anbei die Software sowie ein Bild des Aufbaus. Die Software besteht 
hauptsächlich aus dem 1-Key-Keyboard mit dem VUSB-Stack von hier:
http://blog.flipwork.nl/?x=entry:entry081009-142605
Informationen zur Beschaltung finden sich in der main.c im zip.
Ich verwende einen ATTiny2313 mit 16MHz, mit 3,3V, die ich aus USB und 
einem Festspannungsregler (ist auf der Rückseite der Platine, deshalb 
nicht sichtbar) gewinne.
Ebenso auf dem Bild ist die serielle Debugschnittstelle zu sehen. Erste 
Versuche den AVR direkt mit 5V zu betreiben (und Z-Dioden an den 
USB-Pins) lieferten recht verrauschte Messwerte, mit dem Spannungsregler 
geht das wesentlich besser.
Die Sensorplatte ist einfach ein ca. 1,5cmx3cm großes Metallplättchen, 
welches auf einem Stück Plastik in ca. 1,5cm Höhe über der Platine 
angebracht ist.
Die Firmware ist sehr schnell zusammengehackt und nicht sonderlich 
schön, zumal ist der Tiny mit dem USB-Stack schon ziemlich voll, aktuell 
haben nur noch 2 Bytes Platz im Flash.
Im Unterschied zu anderen Beispielen verwende ich den eingebauten 
Komparator, um die Aufladeschwelle zu erkennen (habe aber keine Versuche 
gemacht, ob das was bringt ggü. normalem Portpin). Die 
Signalverarbeitung der Rohdaten sieht folgendermaßen aus:
- Vergleich, ob der gemessene Rohwert unter Vergleichswert minus 
Threshold liegt (der Threshold ist über das "#define th 5" einstellbar).
- die Ausgabe dieses Vergleichs geht in ein 8-Bit Schieberegister, d.h. 
es werden immer die letzten 8 Messungen berücksichtigt.
- Nur wenn dieses SR mehr als "#define filtth 6" Nullen bzw. Einsen 
enthält wird abhängig vom aktuellen Zustand in einer fsm in den anderen 
übergegangen.
Damit erreiche ich eine sehr stabile Auswertung ohne Fehlauslösungen, 
schon bei knapp unter 1cm Entfernung eines Fingers zur Sensorplatte.
Solange die Taste "gedrückt" wird, wird einfach eine gedrückte 
Space-Taste ausgegeben.
Was noch fehlt, ist u.A. eine ständige Nachkalibrierung, bisland wird 
nur einmal beim Start der Schnitt von 8 Messungen genommen als 
Vergleichswert. Leider ist jedoch wiegesagt der Platz sehr beschränkt, 
ich habe bereits die Vendor- und Device-Strings auf nur je 2 Zeichen 
gekürzt, um mehr Platz zu haben ;-).

Gruß,
droelf


Nachtrag: Es werden alle nicht benötigten Pins auf Ausgang und 0 
geschaltet, ich hatte mit dem seriellen Kabel angesteckt, aber uart-tx 
nicht an (das tx-Pin also auf Eingang) eine Verschlechterung der 
Empfindlichkeit festgestellt.
Außerdem habe ich noch auf der Lochrasterplatte die Lötinseln rund um 
die beiden benötigten Pins, den Kondensator und den Widerstand zur 
Sensorfläche weggekratzt, um eben möglichst wenige zusätzliche 
Kapazitäten an der Sensorplatte zu haben.

von Johannes H. (icbruzzler)


Angehängte Dateien:

Lesenswert?

Hallo,
ich hab mir hier aus dem Thread mal die sense_key Funktion von Andreas 
Auer (Beitrag "Re: qtouch - sekt oder selters") geholt und 
zwischen Port C0 und C1 10nF und daran über 1kohm eine Touchfläche mit 
20x20mm.

Das Ergebnis der sense_key Funktion soll nun auf dem LCD ausgegeben 
werden. Dies funktioniert auch soweit aber leider wird immer nur eine 
Null angezeigt.
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <inttypes.h>
5
#include <util/atomic.h>
6
#include <oldmacros.h>
7
#include "lcd-routines.h"
8
#include <util/delay.h>
9
#define TAKT 16000000UL;
10
11
static int sense(void)
12
{
13
    unsigned char i=0; 
14
    DDRC  = 0x00;
15
    PORTC = 0x00;
16
    
17
    DDRC |= _BV(PC1);
18
    DDRC |= _BV(PC0);
19
    _delay_us(5);
20
    DDRC &= ~_BV(PC1);
21
    DDRC &= ~_BV(PC0);
22
23
    PORTC |= _BV(PC0);
24
    for(i=0; i<255 && !(PINC & _BV(PC0)); i++)
25
    {
26
        DDRC |=  _BV(PC0);
27
        _delay_us(5);
28
        DDRC &= ~_BV(PC0);
29
        DDRC |=  _BV(PC1);
30
        _delay_us(20);
31
        DDRC &= ~_BV(PC1);
32
    } 
33
    DDRC |= _BV(PC1);
34
    DDRC |= _BV(PC0);
35
    PORTC = 0x00;
36
    
37
    return i;
38
}
39
40
41
int main(void)
42
{
43
  
44
  while(1)
45
  {
46
  lcd_init();
47
  lcd_string("Sensekey:");
48
  lcd_data(sense());
49
  lcd_setcursor(0,2);
50
  
51
    {
52
    char Buffer[20];
53
    itoa(sense(), Buffer, 10);
54
    lcd_string(Buffer);
55
    }
56
  }
57
}



Was mache ich falsch?

Meine Sensorfläche ist einfach ein Stück Leiterplatte mit Tesa darauf 
als Berührungsschutz, also nur eine Kupferfläche. Ich hab mir auch schon 
mal den Designguide von Atmel angesehen, aber wurde auch nicht schlau 
daraus.

Vielen Dank schon mal im Vorraus

von Johannes H. (icbruzzler)


Lesenswert?

Update:

Ich hab jetzt ne Sensorfläche dran wo aussen rum ein streifen geerdet 
ist und die Fläche hängt am Capture bin.

Der Wert am Display ändert sich allerdings nur wenn ich mit dem Finger 
direkt auf die Platine zwischen GND und der Sensorfläche drücke von 0 
auf so an die 30 mein Kondensator zwischen den beiden Ports hat 100nF.

Hat jemand ne Idee für diesen Fehler? Warum ist das so?

von Peter D. (peda)


Lesenswert?

Johannes Huber schrieb:
> Was mache ich falsch?

Vielleicht solltest Du mal Deinen Code kommentieren. Das macht es 
anderen und vor allem Dir einfacher zu sehen, was er macht und ob das 
richtig ist.

Kombibedingungen im for()-Ausdruck halte ich für besonders 
unübersichtlich.
Gibt es weitere Abbruchmöglichkeiten, nehme ich dafür ein break.

Und Du mußt schon sagen, was Du wo angeschlossen hast, ein Schaltplan 
wäre natürlich noch besser.

Und statt nichtssagenden PC0, PC1 usw. nenne ich die Portpins nach ihrer 
Funktion.
Dann ist es auch einfacher, die Pins zu wechseln.


Mindestens ein Fehler ist, daß Du den einen Pin ständig auf high läßt, 
dadurch lädt Dir der interne Pullup den Kondensator sofort auf, so kanns 
nicht gehen.


Peter

von Johannes H. (icbruzzler)


Lesenswert?

Sorry,
ich hab gestern nur in aller schnelle vl ein bisschen unüberlegt 
gepostet also nochmal:

Ich benutzte nen Mega8 am Capture PIN PB0 hängt über 1kohm die 
Touchfläche und zwischen PB1 und PB0 hängt  bei mir ein 100nf Elko.
1
#include <avr/io.h>
2
#include <stdio.h>
3
#include <stdlib.h>
4
#include <inttypes.h>
5
#include <util/atomic.h>
6
#include <oldmacros.h>
7
#include "lcd-routines.h"
8
#include <util/delay.h>
9
10
static int sense(void) //Funktion aus Andreas Auers Beitrag auf nen Mega8 angepasst
11
{
12
    unsigned char i=0; 
13
    DDRB  = 0x00;
14
    PORTB = 0x00;
15
    
16
    DDRB |= _BV(PB1);
17
    DDRB |= _BV(PB0);
18
    _delay_us(5);
19
    DDRB &= ~_BV(PB1);
20
    DDRB &= ~_BV(PB0);
21
22
    PORTB |= _BV(PB0);
23
    for(i=0; i<255 && !(PINB & _BV(PB0)); i++)
24
    {
25
        DDRB |=  _BV(PB0);
26
        _delay_us(5);
27
        DDRB &= ~_BV(PB0);
28
        DDRB |=  _BV(PB1);
29
        _delay_us(20);
30
        DDRB &= ~_BV(PB1);
31
    } 
32
    DDRB |= _BV(PB1);
33
    DDRB |= _BV(PB0);
34
    PORTB = 0x00;
35
    
36
    return i;
37
}
38
39
40
@Peter Dannegger
41
Ich hab es auch schon mal mit deinem Code herum experimentiert welchen du auf Andreas Auers Beitrag hin gepostet hast aber mit der mydefs.h komme ich nicht so recht klar =)
42
43
Danke für deine Hilfe
44
45
Johannes
46
47
48
int main(void)
49
{
50
  
51
  while(1)
52
  {
53
  sense();
54
  lcd_init();
55
  lcd_string("Sensekey:");
56
  lcd_setcursor(0,2);
57
  
58
    {
59
    char Buffer[20];
60
    itoa(sense(), Buffer, 10);
61
    lcd_string(Buffer);
62
    }
63
  }
64
}

von NickJag (Gast)


Lesenswert?

Hi @All
Ich habe mal versucht den code auf einen Atmega8 zu übertragen, aber 
iergendwie klappt das alles nicht, habe leider auch Kein LCD was ich zum 
laufen bekomme, könnte mal jemand nen kompletten C code für nen atmega8 
posten, an einem Port einfach LED's geschaltet werden?

Währe nett wenn ihr mir helfen könntet

MfG
NickJag

von geht schon (Gast)


Lesenswert?

hier hast du nochmal alles schön zusammengefasst...
damit sollte man das schon hinbekommen

nen beispiel gibt es glaub ich auch noch weiter unten auf der Seite

von geht schon (Gast)


Lesenswert?


von NickJag (Gast)


Lesenswert?

Und wie würde dann eine einfache auswertung für einen Ausgang aussehen? 
verstehe das iergendwie nicht ganz....

Danke Für die hilfe...

NickJag

von Artur H. (hohoho)


Lesenswert?

Ich habe heute auch angefangen, mit QTouch rumzuexperimentieren.
Habe auf Lochraster einen ATmega8 und ein 4x4-Rasterfeld für einen 
Touch-Key neben minimalst-Beschaltung des mega ( ja, nicht einmal die 
Abblock-Kondensatoren habe ich drin ).
Eine LED signalisiert, wenn man am Key rumdrückt/sich in der Nähe 
aufhält.

Der Code von Andreas Auer hat mir leider immer nur 0 zurückgeliefert, 
aber mit dem Code von Peter Dannegger läuft es nun ( musste MAX_CYCLE 
nur anpassen, vielen Dank nochmal ).

Mein Aufbau ist alles andere als Ideal ( 100nF Kondensator, hatte gerade 
keinen besser passenden da ), trotzdem ist es für einen ersten Test 
wunderbar.

Werde das ganze demnächst auf einer geätzten Platine ( mit richtigen 
Werten und "guter" Beschaltung ) aufbauen, und habe prompt eine Frage 
...
Hat einer von euch schon einen Slider ( 3 Channels ) zum laufen bekommen 
( am liebsten ohne die Lib von Atmel ) ? Wie müsste man die 3 Werte 
miteinander verrechnen, um einen schönen linearen Weg zu haben ?

von Martin J. (bluematrix) Benutzerseite


Lesenswert?

nein ich bin noch nciht wieder dazu gekommen, aber würde mich über deine 
erfahrungen freuen.

mit der atmel lib hab ich mich noch nicht groß beschäftigt

von Andi (Gast)


Lesenswert?

Kann evtl. einer von euch nen Quellcode posten mit dem man mit einem 
Sensorfeld ne LED zum leuchten bringen kann?

Muss die elektrode noch zusätzlich an GND oder so angeschlossen werden?

von AVerr (Gast)


Lesenswert?

Quellcodes wurden ja schon mehrere gepostet.
Musst ggf. noch den LED-Teil dazucoden, aber das kriegt ja wohl jeder 
Anfänger hin ;)

Die Elektrode sollte bloß nicht an GND, sonst kriegst du gar nix mehr 
mit.
http://www.atmel.com/dyn/resources/prod_documents/doc10620.pdf
Dort ist alles über Elektroden erklärt, was man für den Anfang wissen 
muss.

von icbruzzler (Gast)


Lesenswert?

Hallo,
nimm den Code von Peter Dannegger
Beitrag "Re: qtouch - sekt oder selters"
der reicht für deine Zwecke völlig aus, kann sogar 3 Tasten auswerten.

Rufe die Funktion Sense_key in deiner main datei auf und lege den 
Schwellwert fest welchen die Sensorfläche liefern muss.
Zum testen des Schwellwerts ist die Ausgabe der kapazitiven Tasten auf 
ein LCD Display super, da man einfach die Werte ablesen kann.

Nein, die Sensorfläche muss nicht zusätzlich auf GND gelegt werden. 
allerdings erhöht ein Kondensator gegen Erde die Empfindlichkeit der 
Platte habe ich festgestellt.

von Andi (Gast)


Lesenswert?

Vielen Dank für die schnelle Antwort, kannst du vielleicht kurz meinen 
Code ansehen?

Der Kondensator kommt an PA0 und PB0 oder?

#include <avr\io.h>
#include <util\atomic.h>


#define SK_A0   (1<<5)
#define SK_B0   (1<<4)
#define SK_A1   (1<<2)
#define SK_B1   (1<<3)
#define SK_A2   (1<<0)
#define SK_B2   (1<<1)

#define SK_A012 (SK_A0 | SK_A1 | SK_A2)
#define SK_B012 (SK_B0 | SK_B1 | SK_B2)


#define MAX_CYCLE       2000


uint16_t keys[3];


void read_senskey( void )
{
  uint16_t i = MAX_CYCLE;
  uint8_t a, b, x, y;

  ATOMIC_BLOCK(ATOMIC_FORCEON){
    a = DDRA  & ~(SK_A012 | SK_B012);
    b = PORTA & ~(SK_A012 | SK_B012);
    y = SK_B012;                        // input mask
    do{
      DDRA = a;                         // tristate
      PORTA = b | SK_B012;
      DDRA = a | SK_B012;               // Bx = strong high
      DDRA = a;                         // tristate
      PORTA = b;
      DDRA = a | SK_A012;               // Ax = strong low
      if( --i == 0 )                    // timeout
        break;
      x = y & PINA;                     // not immediately after set 
DDRA !!!
      if( x ){
        if( x & SK_B0 )
          keys[0] = i;
        if( x & SK_B1 )
          keys[1] = i;
        if( x & SK_B2 )
          keys[2] = i;
      }
      y ^= x;                           // clear processed input
    }while( y );                        // all inputs done
    DDRA = a | SK_A012 | SK_B012;       // discharge
  }
}
int main (void)
{
 while(1)
 {
  read_senskey(); //obere Funktion wird aufgerufen, diese fragt ja die 
Touchfelder ab

  //jetzt die Ergebnisse der Touchabfrage (welche im Array keys[] 
gespeichert wurden) verwerten
  if( keys[0]>1 )
  {
   //LED an

   PORTA|=0x01;
  }
  else
  {
   //LED aus

   PORTA&=0xFE;
  }
 }

}

von icbruzzler (Gast)


Lesenswert?

Hallo,
meiner Meinung passt dein Code für einen ersten Test mit einer LED 
allerdings den Wert keys[0]>1 finde ich etwas unrealistisch =)) bei 
einer sensorplatte von 20x20mm und einem 100nf Kondensator habe ich 
werte um die 1500 wenn sich keine Hand in der Nähe befindet oder 
sonstige Störfaktoren.
Am besten du holst dir deinen Wert mit nem LCD display und trägst diesen 
dann entsprechend ein, oder schreibst dir ein unterprogramm welches 
einige male den wert von keys[0] misst und diesen dann in einer varible 
speichert zu beginn deines Programms und dann bei einer Abweichung nach 
oben von so ca. 20 von dem gespeicherten Wert in der Variable auslöst 
oder du machst es echt mit nem LCD.
Das ist im Moment die einfachste Lösung meiner Meinung nach.

von icbruzzler (Gast)


Lesenswert?

Ich würde auch noch ne kleine Warte Funktion direkt nach dem Einschalten 
der LED einfügen da Sie sonst so schnell wieder ausgeht dass du gar 
nicht mitkriegst dass se ein war ;)

von Andi (Gast)


Lesenswert?

OK das hört sich gut an, an welche pins muss ich nach dem Programm von 
Peter an das Touchpad anschließen? Seh da noch nicht wirklich durch:

#define SK_A0   (1<<5)
#define SK_B0   (1<<4)
#define SK_A1   (1<<2)
#define SK_B1   (1<<3)
#define SK_A2   (1<<0)
#define SK_B2   (1<<1)

Sind das auch die Ports A0 A1 A2 B0 B1 und B2???

von icbruzzler (Gast)


Lesenswert?

Zwischen Port A0 und Port B0 den Kondensator, da laut Datenblatt des 
Mega8 B0 dein Capture PIN ist schließt du da deine Sensorfläche an

A0 B0 ist ein Paar
A1 B1 und A2 B2 bilden ein Paar wo jeweils eine Taste angeschlossen 
werden kann.

von Andi (Gast)


Lesenswert?

Es funktioniert! Das merkwürdige daran ist das ich das Touchpad an Pin 
A4 und Pin A5 vom Mikrocontroller angeschlossen habe. Den Keys Wert habe 
ich wie folgt eingestellt durch testen:

if( keys[0]>1887 )

Kann es sein das die Belegung wie folgt ist?

#define SK_A0   (1<<5)  //Pin A5
#define SK_B0   (1<<4)  //Pin A4
#define SK_A1   (1<<2)  //Pin A3
#define SK_B1   (1<<3)  //Pin A2
#define SK_A2   (1<<0)  //Pin A1
#define SK_B2   (1<<1)  //Pin A0

von icbruzzler (Gast)


Lesenswert?

Sorry mein Fehler,
sieht man ja in dem Unterprogramm dass die Ports A0-A5 gebraucht werden 
und A0 und B0, A1 B1 und A2 B2 jeweils ein paar bilden.

von Manuel (Gast)


Lesenswert?

Mhm wo muss denn die LED in Andis Beispiel angeschlossen werden? Wollte 
das ganze jetzt auch mal auspobieren.

von Andi (Gast)


Lesenswert?

Servus,

wollte das q-touch Programm jetzt mal in ein anderes Programm einbinden, 
ging auch so weit ganz gut, mein neues Problem: Ich benötige den Port A 
für meinen ADC, also habe ich das Touch-Pad einfach an Port C 
angeschlossen und folgendes geändert:



/*Definition für Touch Pad*/
#define TP1_A   (1<<0) //
#define TP1_B   (1<<1) //
#define TP2_A   (1<<2) //
#define TP2_B   (1<<3) //
#define TP3_A   (1<<4) //
#define TP3_B   (1<<5) //
#define TP4_A   (1<<6) //
#define TP4_B   (1<<7) //

#define TP1234_A (TP1_A | TP2_A | TP3_A | TP4_A)
#define TP1234_B (TP1_B | TP2_B | TP3_B | TP4_B)


#define MAX_CYCLE       2000


uint16_t keys[4];


void read_senskey( void )
{
  uint16_t i = MAX_CYCLE;
  uint8_t a, b, x, y;

  ATOMIC_BLOCK(ATOMIC_FORCEON){
    a = DDRC  & ~(TP1234_A | TP1234_B);
    b = PORTC & ~(TP1234_A | TP1234_B);
    y = TP1234_B;                        // input mask
    do{
      DDRC = a;                         // tristate
      PORTC = b | TP1234_B;
      DDRC = a | TP1234_B;               // Bx = strong high
      DDRC = a;                         // tristate
      PORTC = b;
      DDRC = a | TP1234_A;               // Ax = strong low
      if( --i == 0 )                    // timeout
        break;
      x = y & PINC;                     // not immediately after set 
DDRA !!!
      if( x ){
        if( x & TP1_B )
          keys[0] = i;
        if( x & TP2_B )
          keys[1] = i;
        if( x & TP3_B )
          keys[2] = i;
    if( x & TP4_B )
          keys[3] = i;

      }
      y ^= x;                           // clear processed input
    }while( y );                        // all inputs done
    DDRC = a | TP1234_A | TP1234_B;       // discharge
  }
}

Das erste der 7 Touchfelder funktioniert auch weiter einwandfrei, das 
zweite und dritte reagiert nicht mehr auf die Berührung und das vierte 
geht gar nicht.
Woran könnte das liegen? Kann man das Touchfeld evtl. nur an Port A 
betreiben? Habe das Pollin-Board falls das irgendwie hilft.

Gruß Andi

von Sepp (Gast)


Lesenswert?

Hallo Andi,
ändere mal DDRC und PORTC überall auf DDRA und PORT A dann sollte es 
funktionieren.
Und warum hast du 7 Touchfelder? Mit deinem geposteten Code kannst du 
maximal 4 haben oder?

Ich hofffe ich konnte dir helfen.

Gruß Sepp

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Entschuldigt bitte, wenn ich diesen Thread noch einmal raus krame, aber 
ich komme nur zu sehr unbefriedigenden Ergebnissen. Ich bin in C nicht 
so fit, wie ich es gern wäre, aber ich glaube eigentlich alles korrekt 
umgesetzt zu haben:
1
void GetCap(void) {
2
  
3
  wdt_reset();
4
5
  sens = MAX_CYCLE;
6
  uint8_t a, b;
7
8
9
  ATOMIC_BLOCK(ATOMIC_FORCEON)
10
  {
11
    a = DDRB  & ~(_BV(B_SENS) | _BV(B_VGND));  // contains DDRB with all unused bits
12
    b = PORTB & ~(_BV(B_SENS) | _BV(B_VGND));  // contains PORTB with all unused bits
13
14
    do
15
    {
16
      DDRB  = a;                // both inputs floating
17
      PORTB = b | _BV(B_SENS);        // prepare charging
18
      DDRB  = a | _BV(B_SENS);        // charge sens
19
      DDRB  = a;                // weak high
20
      PORTB = b;                // floating
21
      DDRB  = a | _BV(B_VGND);        // transfer load
22
      if( --sens == 0 )            // failed
23
        break;
24
    }
25
    while( bit_is_clear(PINB, B_SENS) );    // complete
26
    DDRB = a | _BV(B_SENS);            // discharge
27
  }
28
}

Ich bekomme auch eine Reaktion, aber die Ergebnisse schwanken mehr, als 
ich erwarten würde. Ich habe einmal eine Grafik angehängt, die die 
Messwerte darstellt. Sowohl die Idle, als auf die Touch-Phase sind sehr 
unruhig; kann man auswerten, aber das soll doch so nicht aussehen, oder 
?

Ich bin für jeden Gedanken und jede Anregung dankbar :)
Vielen Dank, Stefan

von Stefan (Gast)


Lesenswert?

wirklich keine, der mal qualifiziert drüber schauen kann ?

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Also ich weiß nicht genau wie das bei mir aussieht. Ich kann mal 
schauen, dass ich mir auch diese Werte ausgeben lasse und dann kann ich 
mehr dazu sagen, ob das bei dir normal ist oder nicht!

Vom Programm her könnte ich jetzt nichts besonderes feststellen!

mfg
Andreas

von Peter D. (peda)


Lesenswert?

Es könnte helfen, wenn Du das Programm compilierbar postest.
Also mit allen nötigen Variablen, Defines und Includes und als Anhang.
Und der Schaltplan wäre auch nicht zu verachten.



Peter

von Bernhard B. (schluchti)


Lesenswert?

Hat von euch schon jemand nen Vergleichstest verschiedener Sensorflächen 
gemacht? Bis jetzt hab ich nur Kupfermünzen als Sensorfläche 
verwendet...funktioniert zwar ganz gut, aber gibts da vielleicht etwas 
besseres? Das ganze soll hinter eine 4mm Plexiglasscheibe

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Hi,

also ich hab vor kurzem einen Prototypen mit 3 Sensortasten gebaut. Die 
Sensorflächen sind quadratische Kupferflächen direkt auf der Platine mit 
ca. 1,2cm x 1,2cm und mit Lötstopplack bedeckt.
Die Tasten sind hinter 2mm Plexiglas und 2mm Luftspalt ist zwischen 
Sensorfläche und Plexiglas auch noch. Funktioniert einwandfrei.

Ich mach die Messung aber nicht in Software sondern mit den fertigen 
Chips von Atmel AT42QT1010.

Ach ja... hab ich noch vergessen. Ich hab auch noch eine Bohrung mitten 
in der Sensorfläche wo ich eine LED durchscheinen lasse.

mfg
Andreas

von Hans (Gast)


Lesenswert?

Kann man diese Charge-Transfer Methode uneingeschränkt verwenden, oder 
hält jemand (Atmel) Patente? Oder gelten etwaige Einschränkungen nur für 
deren Bibliothek?

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Hans schrieb:
> Kann man diese Charge-Transfer Methode uneingeschränkt verwenden, oder
> hält jemand (Atmel) Patente? Oder gelten etwaige Einschränkungen nur für
> deren Bibliothek?

Atmel verfolgt die Philosophie, die Anwender der verschiedensten 
Bausteine mit Applikationen zu unterstützen. Daher kann man das 
qTouch-Prinzip überall und uneingeschränkt anwenden. Bei den Lehrgängen 
zu dem Thema wurde dies auch ausdrücklich betont ;-)

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Bernhard B. schrieb:
> Das ganze soll hinter eine 4mm Plexiglasscheibe

Gar kein Problem. Die Flächen müssen nur groß genug sein. In deinem Fall 
etwa 2cm Kantenlänge bei quadratischen oder 3cm Durchmesser bei runden 
Flächen. Die Kapazität des Ladekondensators sollte in dem Fall etwas 
höher gewählt werden.

von Hans (Gast)


Lesenswert?

Knut Ballhause schrieb:
> Daher kann man das
> qTouch-Prinzip überall und uneingeschränkt anwenden.
Danke für die Info.

von Bernhard B. (schluchti)


Lesenswert?

Andreas Auer schrieb:
> Die
> Sensorflächen sind quadratische Kupferflächen direkt auf der Platine mit
> ca. 1,2cm x 1,2cm und mit Lötstopplack bedeckt.
> Die Tasten sind hinter 2mm Plexiglas und 2mm Luftspalt ist zwischen
> Sensorfläche und Plexiglas auch noch. Funktioniert einwandfrei.

Das klingt echt gut, ich denke ich werde das ebenfalls mit den 
Kupferflächen probieren. Ist einfach & billig. Danke!

Andreas Auer schrieb:
> Ach ja... hab ich noch vergessen. Ich hab auch noch eine Bohrung mitten
> in der Sensorfläche wo ich eine LED durchscheinen lasse.
Rein aus Interesse: Wie groß hast du das Loch gemacht?

Knut Ballhause schrieb:
> Gar kein Problem. Die Flächen müssen nur groß genug sein. In deinem Fall
> etwa 2cm Kantenlänge bei quadratischen oder 3cm Durchmesser bei runden
> Flächen. Die Kapazität des Ladekondensators sollte in dem Fall etwas
> höher gewählt werden.

Ok, dann werde ich die Fläche quadratisch machen, das ist mechanisch 
einfacher herzustellen. Bezüglich der Kapazität: Ich hätte da an 
irgendetwas zwischen 33nF und 50nF gedacht. Passt das?

Danke!

von Hans (Gast)


Lesenswert?

Bernhard B. schrieb:
> Bezüglich der Kapazität: Ich hätte da an
> irgendetwas zwischen 33nF und 50nF gedacht. Passt das?

Je größer im Verhältnis zur Kapazität der Sensorfläche, desto länger 
braucht die Messung.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Bernhard B. schrieb:
> Rein aus Interesse: Wie groß hast du das Loch gemacht?

Ich hab jetzt meine Eagle Files nochmal angesehen... und zwar war meine 
Sensorfläche 14mm x 10mm groß. Und die Kreisfläche ohne Kupfer (ist ja 
etwas größer als die Bohrung selbst) hatte einen Durchmesser von ca. 
3mm.

Als Kondensator hab ich 33nF verwendet. War ohne Plexiglas und Luftspalt 
sehr sehr empfindlich. Mit Plexiglas und Luftspalt hats dann gepasst.
Bessere wäre bei mir auch gewesen, wenn die Platine direkt am Plexiglas 
aufgelegen wäre (war nicht möglich, da noch ein OLED Display dazwischen 
war). Der Luftspalt ist sehr ungünstig. Sollte also in deinem Fall ganz 
leicht funktionieren.

mfg
Andreas

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Hans schrieb:
> Je größer im Verhältnis zur Kapazität der Sensorfläche, desto länger
> braucht die Messung.

Stimmt, aber nur so kann man große Flächen überhaupt messen und eine 
gescheite Reichweite erzielen. Ist die Fläche zu groß und der 
Kondensator zu klein, gibt es zu wenig Hub, den man auswerten könnte. 
Ist also alles ein wenig experimentell, aber wenn man die richtigen 
Werte hat, sehr zuverlässig.

von Bernhard B. (schluchti)


Lesenswert?

Andreas Auer schrieb:
> Ich hab jetzt meine Eagle Files nochmal angesehen... und zwar war meine
> Sensorfläche 14mm x 10mm groß. Und die Kreisfläche ohne Kupfer (ist ja
> etwas größer als die Bohrung selbst) hatte einen Durchmesser von ca.
> 3mm.
>
> Als Kondensator hab ich 33nF verwendet. War ohne Plexiglas und Luftspalt
> sehr sehr empfindlich. Mit Plexiglas und Luftspalt hats dann gepasst.
> Bessere wäre bei mir auch gewesen, wenn die Platine direkt am Plexiglas
> aufgelegen wäre (war nicht möglich, da noch ein OLED Display dazwischen
> war). Der Luftspalt ist sehr ungünstig. Sollte also in deinem Fall ganz
> leicht funktionieren.

Danke für die ausführliche Beschreibung!

von Libspendierer (Gast)


Lesenswert?

Nachdem ich mich durch diesen Registrationsprozess durchschlagen musste 
um den Link zu bekommen, hier für die Nachwelt:

http://www.atmel.com/dyn/resources/prod_documents/Atmel_QTouch_Libraries_4.3.1.exe

Ist ganz interessant zu sehen wie deren Filterroutinen aussehen ;)

von Bernhard B. (schluchti)


Lesenswert?

Nachdem ich mich jetzt mehrere Tage lang an der (zuverlässigen) 
Auswertung von Tastendrücken beschäftigt habe, haben sich noch ein paar 
Fragen aufgetan.
Wie schirmt man die Verbindung vom Touchpad zum Mikrocontroller am 
besten ab? Im Moment verwende ich dafür ein geschirmtes, ca. 20cm langes 
Kabel (da fällt mir ein: den Schirm des Kabels hab ich im Moment nicht 
angeschlossen - den ich sollte den vielleicht mal einseitig auf Masse 
legen) Ich weiß, man sollte die Verbindung möglichst kurz halten, doch 
kürzer kann ichs für den Testaufbau nicht machen. Die Auswertung des 
Tastendrucks klappt eigentlich ganz zufriedenstellend, aber nur solange 
ich das Kabel nicht bewege. Wenn ich das Kabel wenige cm nach rechts 
oder links bewege, kann ich nur noch mit Mühe einen Tastendruck 
erkennen, da sich die Schwellwerte ändern. Mit dieser Einschränkung kann 
ich jedoch leben, da ich das Verbindungskabel einfach mit Heisskleber an 
einer Stelle montiere wo man nicht so leicht hinlangen kann.

Was mich wesentlich mehr stört, ist folgendes: Auf der Platine wo der uC 
sitzt, der die Auswertung des Tastendrucks vornimmt befindet sich noch 
ein Anschluss für den USART. Jedes Mal wenn ich da ein Kabel anschließe, 
dann funktioniert die Auswertung nicht mehr. Meine Vermutung ist, dass 
das USART Kabel wie ne Antenne wirkt und die Schwellwerte dadurch 
verschoben werden. Kann man da schaltungstechnisch vielleicht etwas 
machen?

von Mobase (Gast)


Lesenswert?

Bernhard B. schrieb:
> da fällt mir ein: den Schirm des Kabels hab ich im Moment nicht
> angeschlossen - den ich sollte den vielleicht mal einseitig auf Masse
> legen)

keine schlechte Idee.

von Bernhard B. (schluchti)


Lesenswert?

Der Vollständigkeit halber: Mit angeschlossenem Kabelschirm 
funktioniert's ausgezeichnet!

von 21:21:21 (Gast)


Lesenswert?


von Jan (Gast)


Lesenswert?

Interessantes Prinzip! Ist die Anzahl der Transferzyklen linear zur 
gemessenen Kapazität?

von Christian O. (derbrain)


Lesenswert?

Hallo,
in der Application Note von Atmel und auch hier wurde erwähnt, dass 
Wasser auf der Sensorfläche die Messung beeinflussen kann. Nun möchte 
ich aber genau das: ein Regensensor mittels qtouch. Im Atmel-Forum hat 
ein Mitarbeiter bestätigt, dass das geht, aber "it needs some 
experiments".  Hat das schon mal jemand ausprobiert?
Wie sollte das Ganze dimensioniert werden, und welche Sensorgeometrie 
eignet sich dafür? Bei einer einfachen Kapazitätsmessung wäre ja eher 
eine mit einer GND-Fläche kammarting verzahnte Sensorfläche geeignet. 
Wie schaut das hier aus? Einmal GND außenrum oder GND ganz weglassen?
Die Messung kann/soll sehr langsam erfolgen - es macht nichts, wenn der 
Regen erst nach 10 oder 30 Sekunden oder noch später registriert wird, 
aber es soll ignoriert werden wenn mal jemand kurz mit dem Finger 
hinfasst. Zur Not kann das aber auch per Software rausgerechnet werden.
Gruß, Christian

von Markus (Gast)


Lesenswert?

Im Prinzip funktioniert das mit Wasser genauso wie mit einem Finger. Die 
Zeit die man braucht um den Speicherkondensator aufzuladen sinkt. Um wie 
viel ist dann die Frage.
Das langsame Auslösen kann man durch 1-2 Mittelwertfilter realisieren 
und eine durch Timer geregelte Abfrage. Der positive Nebeneffekt ist 
dabei, dass kurze Berührungen, wie eben mit dem Finger, nicht mehr 
erfasst werden.

Ich könnte mir gut vorstellen, dass du zu einem akzeptablen Ergebnis 
kommst wenn du alle 300-500ms eine Messung vornimmst und die Werte dann 
in unterschiedlich gewichtende Mittelwertfilter übernimmst. Entweder 
wartest du dann in einer Statusmaschine bis sich dein Filter dem 
aktuellen Wert wieder angenähert hat oder arbeitest mit einem Threshold. 
Dabei würdest du deinen Sensor einmal Kalibrieren und deinen 
Mittelwertfilter als Auslöser nutzen. Die Kalibrierung kann durch einen 
zweiten Filter geschehen der Werte noch langsamer aufnimmt als dein 
Messfilter.

Zur Dimensionierung des Sensors kann ich nur sagen, dass es theoretisch 
ohne Massefläche funktionieren sollte. Das ist quasi nur ein Schirm 
gegen Störeffekte da bei X/Y-Elektroden von Y nach GND eine Kapazität 
aufgebaut wird. Viel wichtiger ist die Dimensionierung des 
Speicherkondensators und des Entladewiderstandes, sowie die Auslegung 
der Filter und des Timings.
Alles wichtige dazu steht in der Atmel Design Guide: 
http://www.atmel.com/dyn/resources/prod_documents/doc10620.pdf

Ich persönlich habe die Erfahrung gemacht, dass Form und Größe zwar 
wichtige Faktoren, nicht aber entscheidend sind. Störeinflüsse von 
anliegenden Schaltungen oder der Umgebung, Integration der Strompfade 
und die Beschaltung sind wesentlich kritischer. Das steht aber auch 
alles in der Design Guide. Nebenbei kannst du deinen Sensor mit Masse 
auch "Totschirmen", also lieber weniger als mehr ;-).

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Regensensor mit qTouch ist nicht ratsam. Gerade bei diesem Prinzip hat 
Wasser ohne Bezugspotenzial zur Erde einen verschwindend geringen 
Einfluss. Ich kann mit meiner Dusche voll auf die Fliese draufhalten, 
hinter der die Elektrode liegt, ohne den Schaltvorgang auszulösen. Kommt 
hingegen die Hand auf die nasse oder trockene Fliese, wird sicher 
geschaltet. Besorge Dir besser eine Sensorfläche mit vergoldeter 
Kammstruktur (einfach) oder nutze einen Reflexkoppler unter einer zu 
beregnenden Scheibe (schwieriger).

von Markus (Gast)


Lesenswert?

Das stimmt wohl aber für den Bezug kann man sorgen. Die Idee an sich ist 
nicht schlecht und wie schon der Atmel-Mitarbeiter meinte: Es muss wohl 
etwas experimentiert werden. Unter Umständen wird dann doch ein Sensor 
mit Masse nötig. Wer nichts wagt der nichts gewinnt.

von gaast (Gast)


Lesenswert?

Für einen Regensensor wäre es wohl sinnvoller, statt einer einfach 
angeschlossenen Kondensatorplatte dessen andere Seite durch den Finger 
gebildet wird, beide Platten auf die Platine aufzubringen (evtl. in 
einer kammartigen Struktur). Eine Seite kommt dabei auf Masse, die 
andere ganz normal an den AVR. Zwischen den beiden wird nun ein kleiner 
Kondensator gebildet, dessen relative Kapazität durch das ganz normale 
QTouch-Programm ausgewertet wird. Befindet sich im Feldweg zwischen den 
beiden Leiterbahnen genug Wasser, wird die Kapazität ausreichend erhöht, 
um sicher erkannt zu werden.

von Stefan (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

hab mich nun auch mal an deisem Thema versucht.
Leider bis jetzt mit mäsigen Erfolg.

Ich verwernde einen ATmega32 den PinD6 und PinD7, sowie einen 1k 
Widerstand, und einen 33nF Kondensator.
Das Programm habe ich mit Hilfe von Codevision geschrieben.
Den Zähler "i" gebe ich über RS232 aus.
Die Schaltung wird über den ISP-USP-Programmer mit 5V versorgt.

Anbei findet ihr einige Bilder vom Aufbau, Schaltplan und den gesamten 
Code.

Leider bekomme ich immer "0" als Rückmeldung.
Woran könnte denn der Fehler liegen?

Danke für die Infos.
mfg Stefan

.
1
      do
2
      {
3
            //  PD6-----1k----PAD
4
            //       |
5
            //      33nF
6
            //       |
7
            //  PD7--         
8
            
9
            //  1. definierten Zustand für die Kondensatoren herstellen. D.h. PB1 und
10
            //  PC1 als Ausgänge schalten und auf low ziehen um alles Cs zu entladen
11
            //  (genügend lange warten).
12
            
13
            
14
            DDRD |= (1<<PD6);       // PD6 als Ausgang schalten
15
            DDRD |= (1<<PD7);       // PD7 als Ausgang schalten  
16
            PORTD &= ~(1<<PD6);     // Ausgang PD6 auf LOW
17
            PORTD &= ~(1<<PD7);     // Ausgang PD7 auf LOW
18
            delay_us (5); 
19
            
20
            //  2. PB1 auf high und PC1 auf low schalten (aber immernoch als Eingänge)   
21
            
22
            DDRD &= ~(1<<PD6);      // PD6 als Eingang schalten   
23
            DDRD &= ~(1<<PD7);      // PD7 als Eingang schalten     
24
            
25
            PORTD |= (1<<PD6);      // Eingang PD6 mit Pull-UP, bzw. später Ausgang auf HIGH
26
            
27
            //  3. PB1 als Ausgang schalten und kurze Zeit (z.B. 5us) warten bis der
28
            //  unbekannte Touchkondensator geladen ist.   
29
            
30
            for(i=0; i<65535 && !(PORTD & (1<<PD6)); i++)
31
            {
32
                DDRD |= (1<<PD6);       // PD6 als Ausgang schalten, da "PORTD |= (1<<PD6)" Ausgang auf HIGH       
33
                delay_us (5);
34
            
35
                //  4. PB1 wieder als Eingang schalten und PC1 als Ausgang schalten. Damit
36
                //  liegt jetzt der "Sampling Kondensator Cs" quasi parallel zum
37
                //  Touchkondensator und es müssen sich die Ladungen so umverteilen, dass
38
                //  beide die gleiche Spannung haben (Parallelschaltung). D.h. es wird Cs
39
                //  leicht geladen, da dieser ja viel größer ist.
40
41
                DDRD &= ~(1<<PD6);      // PD6 als Eingang schalten, da "PORTD |= (1<<PD6)" Eingang mit Pull-UP
42
                DDRD |= (1<<PD7);       // PD7 als Ausgang schalten, da "PORTD &= ~(1<<PD7)" Ausgangn auf LOW
43
                delay_us (20);          // Warten weil das Umladen Zeit braucht ???
44
            
45
                DDRD &= ~(1<<PD7);      // PD7 als eingang schalten, da "PORTD &= ~(1<<PD7)" Eingang ohne Pull-UP   
46
            
47
                //  5. Überprüfe ob PB1 schon als high eingelesen wird. Wenn nicht, dann
48
                //  beginne wieder bei Punkt 3 und erhöhe einen Zähler. Wenn PB1 bereits
49
                //  high ist, dann ist der Zählerstand ein Maß für die Anzahl der
50
                //  Ladezyklen        
51
            
52
            }                                                               
53
            DDRD |= (1<<PD6);       // PD6 als Ausgang schalten
54
            DDRD |= (1<<PD7);       // PD7 als Ausgang schalten  
55
            PORTD = 0x00;      
56
            
57
            printf("\n\ri:0x%X",i); 
58
            delay_ms(1000);      
59
              
60
      }
61
      while(1);

von Moby (Gast)


Lesenswert?

Eine schöne Idee das QTouch, einfach und billig. Auch die Funkschalter 
von EnOcean sind was Innovatives. ABER: Handbetätigte Schalter egal 
welcher Art sind doch öfter als man glaubt entbehrlich. Viel sinnvoller 
ist dann gleich die Investition in automatisiertes Erkennen menschlicher 
Absichten. Die Anwesenheitserkennung (z.B. via Radarmelder) zum Ersatz 
von Lichtschaltern ist hier nur das einfachste Beispiel...

von Christian O. (derbrain)


Lesenswert?

Nochmal eine kurze Verständnisfrage: Was meint Atmel mit 
QTouch-Channels? Kann ich nicht x-beliebige Pins hernehmen? Beim 
ATmega16M1 werden z.B. 12 Channels angegeben. Das Ding hat 32 Pins, 
davon 27 I/O Pins. Bei allen sind die PullUps abschaltbar. Da ich für 
einen Channel immer 2 Pins brauche, wären das also 13 Channels. Schaut 
12 einfach nur schöner aus oder darf ich 3 bestimmte Pins nicht 
verwenden?

von Christian O. (derbrain)


Lesenswert?

Ok, da hätt ich auch gleich draufkommen können: die fehlenden Pins sind 
XTAL1 und XTAL2 :-)

von Hanstuff (Gast)


Lesenswert?

Hallo zusammen,

Hat auch schon mal jemand die QTouch Library verwendet ?

mfg

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Hallo,

ja ich mal ganz kurz. Nachdem die Lib aber nicht wirklich gut 
funktioniert hat - vielleicht war ich auch nur zu doof - und ich sowieso 
wissen wollte wie es funktioniert, hab ich es auch selbst implementiert.

mfg
Andreas

von Hanstuff (Gast)


Lesenswert?

Hallo,
Ja ich habe auch schon einen selbst Programiert.
Die Lib. habe ich instaliert und auch schon passende gefunden für den 
ATmega32. Wen ich mein Sensor im QTouch Studio zeichne, dann spuckt der 
mir irgendwelche Parameter aus. Und mit einem kleinen Wizard kann man 
die MCU wählen und welche Pin und Ports man verwendet und dan kommen 
noch mehr Parameter raus.

Ich habe aber nicht begriffen, wie ich das ganze nun zu einem 
brauchbaren Programm zusammen schachtle? Vieleicht kann mir jemand 
weiterhelfen ?

danke mfg hans

von sepp (Gast)


Lesenswert?

Ja bei dem Punkt bin ich dann mittels Zeitmangel auch gescheitert und 
habs dann ach selbst implementiert.

von Peter D. (peda)


Lesenswert?

Stefan schrieb:
> Leider bekomme ich immer "0" als Rückmeldung.
> Woran könnte denn der Fehler liegen?

Du läßt immer den Pullup eingeschaltet, da kann das nichts werden.

Schau Dir mal meinen Code an:

Beitrag "Re: qtouch - sekt oder selters"


Peter

von Hanstuff (Gast)


Lesenswert?

Stefan schrieb:
> Leider bekomme ich immer "0" als Rückmeldung.
> Woran könnte denn der Fehler liegen?

Bei der Abfrage:
for(i=0; i<65535 && !(PORTD & (1<<PD6)); i++)

Probier mal PIND anstelle von PORTD.
Das Register PIN dient der Abfrage, wenn du PORT  [&] verknüpfst, 
schreibst du den Wert raus und deine Ladung wird Möglicher weise wieder 
entladen.

mfg

von Hanstuff (Gast)


Lesenswert?

Hallo Nochmal

Ich schlage mich grade mit der Touch library rum.
Die librarys sind ja solche .a Files, welche man laut Atmel in das 
Projekt hinein linken muss. Ich habe das jedoch nochnicht hinbekommen.
Kann mir bitte jemand erklären wie mann ein file.a in ein Projekt linkt 
?

mfg Hans

Danke =)

von Gerhard (Gast)


Lesenswert?

Hallo,

ich habe den Bascom-Code von Andreas aus diesem Beitrag
Beitrag "Re: qtouch - sekt oder selters"

dahingehend geändert, daß es jetzt möglich ist, mehrere Sensoren 
gleichzeitig zu verwenden. Dazu schalte ich jeweils die kompletten Ports 
B und C um. Somit sind, wie in dem Beispiel dem Atmega8, 6 Sensoren 
gleichzeitig bei voller Auflösung möglich. Bei Controllern mit vollen 
Ports mit jeweils 8 Pins sind dann 8 Sensoren möglich.

Anschlußbild, als Beispiel die Pins5 der Ports B und C:
PC.5-----------+
               |
              ---
              --- 10n
               |
PB.5-----------+---- 1K ---- Touchpad

die restlichen Pins sind entsprechend zu beschalten. Nichtbenutzte 
müssen mit GND verbunden werden, am Besten mit Pull-Down.

Die Schaltschwelle in der Zeile
   "Loop Until Cycles >= 100"
muß so gewählt werden, daß die Kondensatoren gerade noch nicht soweit 
geladen sind, daß ein High-Zustand erkannt wird.
Bei mir sind bei Berührung der Pads noch ca. 60 Zyklen nötig, die 
Kondensatoren zu laden. Der Unterschied ist schon deutlich. Als Pads 
verwende ich metallene Reißnägel.
Das Ergebnis ist dann im Register PinC zu finden, z.B. bei Betätigung 
des Pads der Pins im Anschlußbild-Beispiel &B00100000.

1
$regfile = "m8def.dat"                                      ' specify the used micro
2
$crystal = 8000000                                          ' used crystal frequency
3
$baud = 19200                                               ' use baud rate
4
$hwstack = 32                                               ' default use 32 for the hardware stack
5
$swstack = 10                                               ' default use 10 for the SW stack
6
$framesize = 40                                             ' default use 40 for the frame space
7
8
'$sim
9
10
'PC.x-----------+
11
'               |
12
'              ---
13
'              --- 10n
14
'               |
15
'PB.x------- ---+---- 1K ---- Touchpad
16
17
'LCD-Definition
18
Config Lcdpin = Pin , Db4 = Portd.4 , Db5 = Portd.5 , Db6 = Portd.6 , Db7 = Portd.7 , E = Portd.3 , Rs = Portd.2
19
Config Lcd = 16 * 2
20
Cls
21
22
Dim Cycles As Byte , Text As String * 8
23
24
Do
25
   Cycles = 0
26
27
   'Alles Entladen
28
   'beide out - beide low
29
   Ddrc = &B11111111 : Portc = 0
30
   Ddrb = &B11111111 : Portb = 0
31
32
   'auf vollstaendige Entladung warten
33
   Waitms 10
34
35
      Do
36
37
      'beide als tristate inp schalten, damit keine Ladung abfliessen kann
38
      Ddrb = 0
39
40
      'PC4 Out und high schalten, um C aufzuladen
41
      Portc = &B11111111 : Ddrc = &B11111111
42
43
      'und wieder aus
44
      Ddrc = 0
45
46
      'Die Ladung aus C jetzt nach PD5 auf GND abfuehren
47
      Portc = 0 : Ddrb = &B11111111
48
49
      'kurze Pause nötig
50
      Waitms 1
51
52
      'messen, ob Ladung schon fuer eine 1 an PinC reicht, sonst von vorn
53
      If Pinc > 0 Then Goto Printout
54
55
      Incr Cycles
56
      Loop Until Cycles >= 100                              'wiederholen und im Zweifel beenden
57
58
   Printout:
59
60
   Locate 1 , 1
61
   Lcd Bin(pinc)                                            'Eingänge PinC anzeigen
62
63
   Text = Str(cycles)
64
   Text = Format(text , "000")
65
   Locate 2 , 1
66
   Lcd Text                                                 'Zyklen-Zahl anzeigen
67
68
Loop
69
70
End                                                         'end program


Gruß
Gerhard

von Domsk (Gast)


Lesenswert?

Hab ich nun auch an den Aufbau der Schaltung gewagt.
hatte aber leider nicht den passenden Kondensator da.
Hab also den nächst größeren genommen. Einen 4,7uF + 4,8 Ohm Widerstand.
Da dieser ja theoretisch mehr Zyklen zum Aufladen braucht, hab ich die 
Begrenzung im Code rausgenommen. Beim ersten versuch hat mir der Code 
nur Nullen geliefert und beim zweiten Versuch nichts (berührt und 
unberührt).
Hab den Elko so gelötet, dass Minus zum Pin geht und Plus zur 
Touchelektrode. Ist doch richtig oder?
Läd sich der Kondensator eventuell garnicht auf oder dauert es einfach 
nur extrem lange?

Dann hab ich es noch mit einem 104pF Kondensator probiert. Unberührt hat 
der mir auch keine Werte geliefert. Bei direkter Berührung gabs dann 
irgendwelche Werte (von 0-300 alles dabei). Durch ein Blatt papier wurde 
dann wieder garnichts angezeigt.

Ich hab hier im Thread irgendwas von einem Capture Pin gelesen. Wofür 
ist der gut bzw. ist der relevant für den Aufbau? Ich hab meinen Aufbau 
an PortA.4 und PortA.7 angeschlossen.

von Bernhard M. (boregard)


Lesenswert?

Domsk schrieb:
> Hab also den nächst größeren genommen. Einen 4,7uF + 4,8 Ohm Widerstand.

Das ist ein verspäteter Aprilscherz, oder?
Im QTouch Bild oben im thread stehen als Beispielswerte 22nF und 1KOhm. 
Jetzt rechne mal aus, wieviele Dekaden Du da weg von bist....

von Domsk (Gast)


Lesenswert?

Leider nein.
Hups, da hab ich das wohl falsch verstanden. Dachte damit sind 
Widerstände von 1Ohm bis 10kOhm gemeint. Aber den werd ich hier zuhause 
wohl noch auftreiben können.

Das erklärt auch, warum kein Wert ausgegeben wurde.

von Bernhard M. (boregard)


Lesenswert?

Wenn Du den ganzen thread mal durchliest, wirst Du sehen, daß es eher am 
Kondensator liegt, der so zwischen 10nF und 33nF sein sollte.

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


Lesenswert?

Domsk schrieb:
> Dann hab ich es noch mit einem 104pF Kondensator probiert.
Soso, ein 104pF Kondensator also...

Sieh dir mal an, wie Kondensatoren gekennzeichnet werden. Könnte es 
sein, dass auch dein 104 pF Kondensator (wie so viele andere auch) in 
Wirklichkeit 10_0000 pF hat (also eine 10 und 4 Nullen), und mithin ein 
100nF Kondensator ist?

von Domsk (Gast)


Lesenswert?

Ja, Ich weiß, dass der Kondensator so am besten ist, aber es müsste mit 
größeren ja auch nach längerer Zeit eine Ausgabe erfolgen. Ich hatte 
einfach keine da.

Habs jetzt noch einige gefunden. Einen 22nF und einen 10nF Kondensator.
Beidesmal keine Ausgabe.

Entweder es steckt ein blöder Fehler drin, oder meine Kondensatoren sind 
kaputt, da sie schon etwas älter sind.
Einmal diesen hier: http://www.wima.de/DE/products_rfi.htm
Oben drauf steht "0u(Mikro-Zeichen)022" (heißt doch 22nF, wenn ich mich 
nicht irre)

Der zweite ist etwas länglich, platt und silbern und es steht "103J" 
drauf, also 10000pF und J als Toleranz oder? Vielleicht ist es auch kein 
Kondensator, man weiß es nicht :D

Oh ja, da hab ich mich wohl versehen. Hab das Codierungssystem von 
Kondensatoren auch erst heute entdeckt.

Folgender Code:

[c] $regfile = "m32def.dat"
$crystal = 16000000
$baud = 9600

$hwstack = 100                     ' default use 32 for the hardware 
stack
$swstack = 100                     ' default use 10 for the SW stack
$framesize = 100                   ' default use 40 for the frame space

Dim Cycles As Word

'PA7-----------+---- 10K ---- Touchpad
'              |
'             ---
'             --- 22n
'              |
'PA4-----------+

Do
Cycles = 0

'Alles Entladen
'beide out - beide low
Ddra.7 = 1 : Porta.7 = 0
Ddra.4 = 1 : Porta.4 = 0

'auf vollstaendige Entladung warten
Waitus 5

   Do
   'beide als tristate inp schalten, damit keine Ladung abfliessen kann
   Ddra.7 = 0 : Porta.7 = 0
   Ddra.4 = 0 : Porta.4 = 0
   Waitus 5

   'PC4 Out und high schalten, um C aufzuladen
   Ddra.4 = 1 : Porta.4 = 1
   Waitus 2

   'und wieder aus
   Ddra.4 = 0 : Porta.4 = 0

   'Die Ladung aus C jetzt nach PD5 auf GND abfuehren
   Ddra.7 = 1 : Porta.7 = 0

   'messen, ob Ladung schon fuer eine 1 an PD4 reicht, sonst von vorn
   If Pina.4 = 1 Then Print Cycles
   Incr Cycles

   Loop                    'wiederholen und im Zweifel beenden


Loop[c]

von Steffen B. (worstmann)


Lesenswert?

Ich hab mich jetzt auch mal mit dem Thema beschäftigt und dabei ist mir 
aufgefallen, dass es ja auch die Variante QTouch per ADC gibt. Kann mir 
jemand erläutern worin der essentielle Unterschied liegt? Schließlich 
ist das ja von der Beschaltung einfacher. Nur 1 Rs am ADC Pin und hinten 
raus ein Tiefpass.

von Joe (Gast)


Lesenswert?

Hallo,

funktioniert Q Touch auch hinter einem wasserdichten Plexiglas Gehäuse 
unter Wasser?

von blubberdrück (Gast)


Lesenswert?

Wenn du im Gehäuse drin sitzt, wahrscheinlich schon!

von Sascha W. (sascha-w)


Lesenswert?

@Joe

also eben mal getestet, es löst wunderbar aus, wenn man das Wasser 
berührt - wenn der Finger aber schon im Wasser ist führt eine 
Abstandsänderung des Fingers zum Sensor innerhalb des Wassers zu keiner 
Auslösung (bis ca. 10cm getestet).

Also für eine sinnvolle Anwendung - NEIN.

Sascha

von TouchFreund (Gast)


Angehängte Dateien:

Lesenswert?

Liebes Forum,

Eigentlich scheint diese Touch-Geschichte ja nicht sonderlich 
anspruchsvoll zu sein, dennoch habe ich meine liebe Mühe, das ganze ans 
laufen zu bekommen.

Aufbau:
RN-Control 1.4 mit Atmga1284P, 20MHz Quarz, ohne L293

An Porta.4 und Porta.5 ein WIMA 33nF sowie 1ct über 1kOhm als Sensor.

Folgender Code liefert leider kein vernünftiges Ergebnis:

Habe schon mit verschiedenen Kapazitäten, Sensoren und Zeiten probiert, 
es scheint jedoch irgendwo ein "Bock" drin zu sitzen, den ich einfach 
nicht sehe.

Ich tippe mal auf einen dummen Fehler... sieht ihn jemand!?

Danke!

Verwendeter Bascom-Code:
1
$regfile = "m1284Pdef.dat"
2
$crystal = 20e6
3
$hwstack = 64
4
$swstack = 48
5
$framesize = 64                                           'default use 40 for the frame space
6
7
'################################################################################
8
'LCD Initialisierung
9
Config Pinb.4 = Output                                      'Spannung an LCD aktivieren
10
Lcdpower Alias PortB.4
11
Config PinB.6 = Output
12
Lcd_rw Alias PortB.6
13
Lcd_rw = 0
14
Lcdpower = 1
15
Wait 1
16
Config Lcd = 20 * 4 , Chipset = Ks077
17
Config Lcdpin = Pin , Db4 = PortB.3 , Db5 = PortB.2 , Db6 = PortB.1 , Db7 = PortB.0 , E = PortB.5 , Rs = PortB.7
18
Config Lcdbus = 4
19
Initlcd
20
Cls
21
Cursor Off Noblink
22
Locate 1 , 1
23
Lcd "Touchdingens 1.0"
24
Waitms 100
25
'#################################################################################
26
27
Dim Cycles As Word
28
Dim Text As String * 8
29
30
Do
31
Cycles = 0
32
33
'Alles Entladen
34
'beide out - beide low
35
Ddra.5 = 1 : Porta.5 = 0
36
Ddra.4 = 1 : Porta.4 = 0
37
38
'auf vollstaendige Entladung warten
39
Waitus 5
40
41
   Do
42
43
   'beide als tristate inp schalten, damit keine Ladung abfliessen kann
44
   Ddra.5 = 0 : Porta.5 = 0
45
   Ddra.4 = 0 : Porta.4 = 0
46
   Waitus 5
47
48
   'Pa4 Out und high schalten, um C aufzuladen
49
   Ddra.4 = 1 : Porta.4 = 1
50
   Waitms 1
51
52
   'und wieder aus
53
   Ddra.4 = 0 : Porta.4 = 0
54
55
   'Die Ladung aus C jetzt nach Pa5 auf GND abfuehren
56
   Ddra.5 = 1 : Porta.5 = 0
57
58
   'messen, ob Ladung schon fuer eine 1 an PD4 reicht, sonst von vorn
59
   If Pina.4 = 1 Then Goto Printout
60
   Incr Cycles
61
62
   Loop Until Cycles >= 600                                 'wiederholen und im Zweifel beenden
63
64
65
66
67
Printout:
68
   Locate 2 , 1
69
   Lcd Cycles , Spc(5)
70
   Waitms 500
71
Loop
72
End

von TouchFreund (Gast)


Lesenswert?

Genau genommen wird immer der Maximalwert für "Cycles" ausgegeben, wird 
der Kondensator entfernt jedoch "0", was ja auch nachvollziehbar ist.

Hat niemand einen Tip?

von Hans (Gast)


Lesenswert?

Hätte das ja lieber über
1
Config PORTX.Y = Input / Output
gelöst. Finde ich irgendwie übersichtlicher.

Kannst du checken, was die Ports machen, d.h. ob sie die erwarteten 
Zustände einnehmen?

Wait xxx dazwischen packen und ausmessen!
Oszi zur Hand??

Gruß,

Hans

von LuckyIno (Gast)


Lesenswert?

Wie wärs mir GetRC()??

von Mw E. (Firma: fritzler-avr.de) (fritzler)


Lesenswert?

Das Qtouch für die AVRs benötigt ja 2 Pins pro "Taste".
Die Qtouch ICs besitzen ne Matrixschaltung (zB QT60240) wobei dort nur 
die Spalten den Ladekondi haben.
Hat also schonmal jemand versucht die Matrixschaltung mit nem AVR zu 
realisieren?

von Rey N. (finwe09)


Lesenswert?

Hallo zusammen,

ich habe auch versucht den oben aufgeführten Code zu 
implementieren...mit Erfolg.
Soweit so gut, leider stoße ich jetzt mit meinen C Programmier und 
Verständnis "Künsten" an meine Grenzen. Ich habe eine Anwendung bei der 
ich mehr als 10 Taster einlesen muss und möchte diese Taster gerne gegen 
die Touch Sensoren (Flächen) ersetzen. D.h. ich muss die Prozedur für 2 
Ports durchführen was mir einiges an Schwierigkeiten bereitet. Ich habe 
den Code schon so umgebaut, dass er mit 2 unterschiedlichen Ports 
funktioniert aber der Code ist sehr unschön bzw. in 2 Funktionen 
getrennt da ich es nicht hinbekomme eine Funktion zu programmieren die X 
Ports mit den von mir gewünschten PINs einliest.

Nachfolgend der Code mir den 2 Funktionen zur Abfrage...
1
#define SK_PortB_A0   (1<<0)
2
#define SK_PortB_B0   (1<<1)
3
#define SK_PortB_A1   (1<<2)
4
#define SK_PortB_B1   (1<<3)
5
#define SK_PortB_A2   (1<<4)
6
#define SK_PortB_B2   (1<<5)
7
8
#define SK_PortD_A0   (1<<0)
9
#define SK_PortD_B0   (1<<1)
10
11
#define SK_PortB_A012 (SK_PortB_A0 | SK_PortB_A1 | SK_PortB_A2)
12
#define SK_PortB_B012 (SK_PortB_B0 | SK_PortB_B1 | SK_PortB_B2)
13
14
//#define SK_PortD_A0 (SK_PortD_A0)
15
//#define SK_PortD_B0 (SK_PortD_B0)
16
17
18
#define MAX_CYCLE_PortB       4000
19
#define MAX_CYCLE_PortD       4000
20
21
uint16_t keys_PortB[3];
22
uint16_t keys_PortD[1];
23
24
void read_senskey_PortB( void )
25
{
26
  uint16_t i = MAX_CYCLE_PortB;
27
  uint8_t a, b, x, y;
28
29
  ATOMIC_BLOCK(ATOMIC_FORCEON){
30
    a = DDRB  & ~(SK_PortB_A012 | SK_PortB_B012);
31
    b = PORTB & ~(SK_PortB_A012 | SK_PortB_B012);
32
    y = SK_PortB_B012;                        // input mask
33
    do{
34
      DDRB = a;                         // tristate
35
      PORTB = b | SK_PortB_B012;
36
      DDRB = a | SK_PortB_B012;               // Bx = strong high
37
      DDRB = a;                         // tristate
38
      PORTB = b;
39
      DDRB = a | SK_PortB_A012;               // Ax = strong low
40
      if( --i == 0 )                    // timeout
41
        break;
42
      x = y & PINB;                     // not immediately after set DDRA !!!
43
      if( x ){
44
        if( x & SK_PortB_B0 )
45
          keys_PortB[0] = i;
46
        if( x & SK_PortB_B1 )
47
          keys_PortB[1] = i;
48
        if( x & SK_PortB_B2 )
49
          keys_PortB[2] = i;
50
      }
51
      y ^= x;                           // clear processed input
52
    }while( y );                        // all inputs done
53
    DDRB = a | SK_PortB_A012 | SK_PortB_B012;       // discharge
54
  }
55
}
56
57
void read_senskey_PortD( void )
58
{
59
  uint16_t i = MAX_CYCLE_PortD;
60
  uint8_t a, b, x, y;
61
62
  ATOMIC_BLOCK(ATOMIC_FORCEON){
63
    a = DDRD  & ~(SK_PortD_A0 | SK_PortD_B0);
64
    b = PORTD & ~(SK_PortD_A0 | SK_PortD_B0);
65
    y = SK_PortD_B0;                        // input mask
66
    do{
67
      DDRD = a;                         // tristate
68
      PORTD = b | SK_PortD_B0;
69
      DDRD = a | SK_PortD_B0;               // Bx = strong high
70
      DDRD = a;                         // tristate
71
      PORTD = b;
72
      DDRD = a | SK_PortD_A0;               // Ax = strong low
73
      if( --i == 0 )                    // timeout
74
        break;
75
      x = y & PIND;                     // not immediately after set DDRA !!!
76
      if( x ){
77
        if( x & SK_PortD_B0 )
78
          keys_PortD[0] = i;
79
      }
80
      y ^= x;                           // clear processed input
81
    }while( y );                        // all inputs done
82
    DDRD = a | SK_PortD_A0 | SK_PortD_B0;       // discharge
83
  }
84
}
85
86
int main(void)
87
{
88
  DDRC   |=  (1<<PC0)|(1<<PC1)|(1<<PC2);                  // set PC0, PC1, PC2 as output    
89
  
90
    LED2_OFF;
91
    LED3_OFF;
92
    LED4_OFF;
93
                        
94
  LED2_ON;                          
95
  _delay_ms(500);
96
  LED3_ON;                          
97
  _delay_ms(500);                        
98
  LED4_ON;
99
  _delay_ms(500);
100
101
    LED2_OFF;
102
    LED3_OFF;
103
    LED4_OFF;
104
105
    while(1)
106
    {
107
    
108
    read_senskey_PortB();      
109
110
      if(keys_PortB[0]>2000)        
111
      {
112
       LED2_ON;        //LED an
113
      }
114
      else
115
      {
116
         LED2_OFF;        //LED aus
117
      }
118
119
    read_senskey_PortD(); 
120
121
      if(keys_PortD[0]>2000)        
122
      {
123
       LED4_ON;        //LED an
124
      }
125
      else
126
      {
127
         LED4_OFF;        //LED aus
128
      }
129
    }
130
}

Also wie gesagt der Code funktioniert aber sehr unschön...könnte jemand 
mir helfen und nen Code posten wie ich die Funktion umschreibe und 
mehrere Ports übergreifend in Abhängigkeit von den einzelnen PINs 
abfragen kann... und das in einer Funktion und nicht in 2 getrennt wie 
aktuell bei mir

Wäre euch echt sehr dankbar!

Viele Grüße
Rey

von TouchFreund (Gast)


Lesenswert?

Tut jetzt auch bei mir, 20MHz sind einfach etwas flott gewesen. 1x 
"waitus 1" und schon gehts :)

was spricht dagegen, einfach 2+2 ports komplett umzuschalten und die 
portzustände einzulesen??

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Hi,

ich hab das ganze vor einiger Zeit mal in ein kleines "Framework" 
(Framework ist etwas hochgegriffen... habs halt bisschen universeller 
gestaltet und in ein eigenes File) verpackt.
Muss aber erst heute Abend schauen, wo ich es auf meinem Rechner hab.

Das ganze sieht so aus, dass du über eine Struktur angeben kannst 
welcher Port und welcher Pin als Touchsensor verwendet wird und einen 
Schwellwert. Ich glaub ich hab sogar einen Filter eingebaut, der das 
ganze Tiefpass filtert bzw. könnte man wenn ich mich recht erinnere auch 
eine eigene Funktion übergeben, in der man einen Filter implementiert.

Falls ihr interesse habt, kann ich es ja mal hier hochladen. Ist aber 
rein für C (also avrgcc) geschrieben.

mfg
Andreas

von Rey N. (finwe09)


Lesenswert?

TouchFreund schrieb:
> Tut jetzt auch bei mir, 20MHz sind einfach etwas flott gewesen. 1x
> "waitus 1" und schon gehts :)
>
> was spricht dagegen, einfach 2+2 ports komplett umzuschalten und die
> portzustände einzulesen??

Hallo nochmal,

folgendes macht mich an meiner Programmierung stutzig...nach folgender 
Vorgabe:

...
1
#define MAX_CYCLE_PortB       4000
2
#define MAX_CYCLE_PortD       4000

wenn ich nun den Wert an Port B und C abfrage:
1
read_senskey_PortB();
2
read_senskey_PortD();

funktioniert alles blendend...

allerdings ist mir aufgefallen, wenn ich nun eine Abfrage auskommentiere 
z.B.
1
read_senskey_PortB();
2
// read_senskey_PortD();    AUSKOMMENTIERT

funktioniert der Tousch-Schalter nicht mehr bzw. der Wert in der 
Abfrage:
1
      if(keys_PortB[0]>1600)        
2
      {
3
       LED2_ON;        //LED an
4
      }
5
      else
6
      {
7
         LED2_OFF;        //LED aus
8
      }

es muss > 1600 abgeändert werden z.B. in den Wert 2300 dass alles 
funktioniert.!?

Kann mir einer erklären wie der Zählwert der Auslesfunktion von Port B 
mit dem Aktivieren bzw. deaktivieren der Auslefunktion von Port C 
zusammenhängt???

Wäre euch super dankbar, es ärgert mich das es funktioniert, ich aber 
nicht weiss ob es ein Zufall ist oder nicht bzw. ich nicht verstehe wie 
das zusammenhängt ;-)

Danke und VG Rey

von Rey N. (finwe09)


Lesenswert?

Andreas Auer schrieb:
> Hi,
>
> ich hab das ganze vor einiger Zeit mal in ein kleines "Framework"
> (Framework ist etwas hochgegriffen... habs halt bisschen universeller
> gestaltet und in ein eigenes File) verpackt.
> Muss aber erst heute Abend schauen, wo ich es auf meinem Rechner hab.
>
> Das ganze sieht so aus, dass du über eine Struktur angeben kannst
> welcher Port und welcher Pin als Touchsensor verwendet wird und einen
> Schwellwert. Ich glaub ich hab sogar einen Filter eingebaut, der das
> ganze Tiefpass filtert bzw. könnte man wenn ich mich recht erinnere auch
> eine eigene Funktion übergeben, in der man einen Filter implementiert.
>
> Falls ihr interesse habt, kann ich es ja mal hier hochladen. Ist aber
> rein für C (also avrgcc) geschrieben.
>
> mfg
> Andreas

;-) wäre echt nett, bin für alles dankbar dass mich (oder vlt. auch noch 
andere) weiterbringt!

VG Rey

von TouchFreund (Gast)


Lesenswert?

Es ändert sich ja die Gesamtkapazität der Kondensatoren, die aufgeladen 
werden wollen. So dauert es eben ein paar Zyklen Länger, bis der C Voll 
ist.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Lesenswert?

Abgesehen davon würde ich nicht den absoluten Zählerstand nach der 
read_senskey_XXX() Funktion auswerten, sondern eher die Änderung des 
Wertes zu einem initialen Referenzwert. Also das Ganze beim Einschalten 
mal machen lassen und der Wert der rauskommt ist dann der Referenzwert. 
Und die Differenz zu diesem Referenzwert wenn du den Finger draufhälst 
kannst du auswerten. Damit ist dir am Anfang ziemlich egal, ob das jetzt 
bei 1600 schaltet oder bei 2000.

Optional ist auch noch möglich, dass du die Drift für den Referenzwert 
berücksichtigst... damit der Touchsensor nicht auf einmal von alleine 
einschaltet oder gar nicht mehr einschaltet.

mfg
Andreas

von Rey N. (finwe09)


Lesenswert?

TouchFreund schrieb:
> Es ändert sich ja die Gesamtkapazität der Kondensatoren, die aufgeladen
> werden wollen. So dauert es eben ein paar Zyklen Länger, bis der C Voll
> ist.

obwohl es jetzt eigentlich ein "Kondensator" bzw. eine Abfrage weniger 
gibt?

hmm ich stehe irgendwie auf dem Schlauch...

Ich überleg mal weiter Danke
Rey <-- Grübel Grübel

von Rey N. (finwe09)


Lesenswert?

Hallo Andreas,

auch dir danke für deine Antwort...habe das nun seit 2 Stunden versucht 
zu verstehen und in C umzusetzen, leider ohne Erfolg ;-( ich muss jetzt 
wohl erst mal aufs Fahrrad und an die frische Luft...

Du schreibst

> Abgesehen davon würde ich nicht den absoluten Zählerstand nach der
> read_senskey_XXX() Funktion auswerten, sondern eher die Änderung des
> Wertes zu einem initialen Referenzwert. Also das Ganze beim Einschalten
> mal machen lassen und der Wert der rauskommt ist dann der Referenzwert.

Das heisst vor der Hauptschleife einmal die keys Variable mit einem Wert 
von z.B. 1600 in meinem Fall vergleichen und die Differenz speichern? 
Ist das der Referenzwert den du gemeint hast?

Danke
Rey

von Malte P. (Gast)


Lesenswert?

Wenn D die Zyklenzeit ist, gilt:

If D > Dmax Then Dmax = D
   D_on = Dmax - 20
   D_off = Dmax - 10

Vorher nen gleitenden Mittelwert bilden, dann läuft das sehr stabil und 
ohne "prellen".

So sollte die Kapazität wurscht sein.

von Mike J. (emjey)


Lesenswert?

Rey N. schrieb:
> Das heisst vor der Hauptschleife einmal die keys Variable mit einem Wert
> von z.B. 1600 in meinem Fall vergleichen und die Differenz speichern?
> Ist das der Referenzwert den du gemeint hast?

Bevor du in die Hauptschleife kommst kannst du doch 8 mal jede einzelne 
Taste auslesen, dann jedes mal durch 8 teilen und diesen Wert als 
Referenzwert für die entsprechende Taste benutzen.

Du kannst auch gleich das Maximum der ermittelten Werte bestimmen und du 
setzt die Differenz für jeden "Touche-Taster" auf die ermittelte 
Differenz plus ein bisschen (mindestens +1).
Wenn der Wert darüber liegt wird der Taster als gedrückt gewertet.

Ich mache das so bei meinem einfacheren Verfahren (wie bei Elm-Chan) 
dazu brauche ich nur einen 1MOhm Widerstand nach +3.3V und einen Pin pro 
Taster.

von Rey N. (finwe09)


Lesenswert?

Mike J. schrieb:
> Rey N. schrieb:
>> Das heisst vor der Hauptschleife einmal die keys Variable mit einem Wert
>> von z.B. 1600 in meinem Fall vergleichen und die Differenz speichern?
>> Ist das der Referenzwert den du gemeint hast?
>
> Bevor du in die Hauptschleife kommst kannst du doch 8 mal jede einzelne
> Taste auslesen, dann jedes mal durch 8 teilen und diesen Wert als
> Referenzwert für die entsprechende Taste benutzen.

Hab ich vertsanden und umgesetzt, nicht schön aber sollte passen:
1
void eval_val_keys_ref_max_PortB_AB0( void )
2
{
3
  int i = 0;
4
  int j = 0;
5
  int num_keys_mesh = 8;
6
    
7
  read_senskey_PortB();     
8
  val_keys_PortB_AB0_[0]=keys_PortB[0];    
9
  read_senskey_PortB();     
10
  val_keys_PortB_AB0_[1]=keys_PortB[0];  
11
  read_senskey_PortB();     
12
  val_keys_PortB_AB0_[2]=keys_PortB[0];  
13
  read_senskey_PortB();     
14
  val_keys_PortB_AB0_[3]=keys_PortB[0];  
15
  read_senskey_PortB();     
16
  val_keys_PortB_AB0_[4]=keys_PortB[0];  
17
  read_senskey_PortB();     
18
  val_keys_PortB_AB0_[5]=keys_PortB[0];  
19
  read_senskey_PortB();     
20
  val_keys_PortB_AB0_[6]=keys_PortB[0];  
21
  read_senskey_PortB();     
22
  val_keys_PortB_AB0_[7]=keys_PortB[0];  
23
  
24
/***************** found ref value *****************/  
25
  for (j = 0; j < num_keys_mesh; j++)          
26
  {
27
    ref_val_PortB_AB0 += val_keys_PortB_AB0_[j];
28
  
29
  }
30
31
  ref_val_PortB_AB0 = ref_val_PortB_AB0 / 8; 
32
33
/***************** found max value ******************/
34
  max_val_PortB_AB0 = val_keys_PortB_AB0_[0];          
35
    
36
    for (i = 0; i <= num_keys_mesh; i++)
37
    {
38
      if(val_keys_PortB_AB0_[i] > max_val_PortB_AB0)
39
        {
40
          max_val_PortB_AB0 = val_keys_PortB_AB0_[i];
41
        }   
42
    }
43
44
  dif_ref_max_val_PortB_AB0 = max_val_PortB_AB0 - ref_val_PortB_AB0;


> Du kannst auch gleich das Maximum der ermittelten Werte bestimmen und du
> setzt die Differenz für jeden "Touche-Taster" auf die ermittelte
> Differenz plus ein bisschen (mindestens +1).
> Wenn der Wert darüber liegt wird der Taster als gedrückt gewertet.

Das Maximum sowie die Differenz von Max zu Ref-Wert hab ich auch 
gebildet, also vor der Hauptschleife...

aber den Rest hab ich nicht so ganz verstanden... auch nach 2 Sunden 
frischer Luft nicht ... versuche es morgen früh mal so, hab die Hardware 
in der Firma...
1
while(1)
2
    {
3
  
4
    read_senskey_PortB();       
5
  
6
      if(keys_PortB[0] > max_val_PortB_AB0 )        
7
      {
8
       LED2_ON;        //LED an
9
      }
10
      else
11
      {
12
         LED2_OFF;        //LED aus
13
      }

hat dann allerdings glaube ich nichts mit der von euch erwähnten 
Differenz zu tun...
weiss aber im Moment nicht wie ich das umsetzen soll.

> Ich mache das so bei meinem einfacheren Verfahren (wie bei Elm-Chan)
> dazu brauche ich nur einen 1MOhm Widerstand nach +3.3V und einen Pin pro
> Taster.

DANKE für eure Hilfe auch wenn ich immer noch auf dem Schlauch stehe...
VG Rey

von Rey N. (finwe09)


Lesenswert?

Guten Abend,

hab das heute mal getestet mit folgendem Ergebnis:

wenn ich folgendes Abfrage:
1
read_senskey_PortB();       
2
  
3
      if(keys_PortB[0] > max_val_PortB_AB0)        
4
      {
5
       LED2_ON;        //LED an
6
      }
7
      else
8
      {
9
         LED2_OFF;        //LED aus
10
      }

ist das Ergebnis sehr ernüchternd, die LED brennt nicht.

wenn ich abfrage:
1
read_senskey_PortB();       
2
  
3
      if(keys_PortB[0] > ref_val_PortB_AB0)        
4
      {
5
       LED2_ON;        //LED an
6
      }
7
      else
8
      {
9
         LED2_OFF;        //LED aus
10
      }

funktioniert es nur, wenn ich den Sensor "extrem fest" drücke bzw das 
Kabel berühre welches mit der Fläche verlötet ist.

wenn ich abfrage:
1
read_senskey_PortB();       
2
  
3
      if(keys_PortB[0] > ref_val_PortB_AB0 - 700)        
4
      {
5
       LED2_ON;        //LED an
6
      }
7
      else
8
      {
9
         LED2_OFF;        //LED aus
10
      }

funktioniert es gut.

Was meint Ihr dazu?

von Mike J. (emjey)


Lesenswert?

Rey N. schrieb:
> Was meint Ihr dazu?

Lass dir mal deinen aktuellen Wert des Tasters ausgeben, es kann sein 
dass der niedriger ist als der beim starten ermittelte Wert.

von Andreas A. (Firma: Embedded Microtec) (andi) Flattr this


Angehängte Dateien:

Lesenswert?

Hi,

hat leider etwas gedauert, aber anbei sind die Sourcen für die 
kapazitive Touch Sensor Geschichte. Es ist auch eine Demoapplikation 
dabei, die das Softwaregerüst verwendet (leider undokumentiert). Aber 
durch die Applikation erklärt sich das eine oder andere sicher von 
selbst.

lg.
Andreas

von Rey N. (finwe09)


Lesenswert?

Mike J. schrieb:
> Rey N. schrieb:
>> Was meint Ihr dazu?
>
> Lass dir mal deinen aktuellen Wert des Tasters ausgeben, es kann sein
> dass der niedriger ist als der beim starten ermittelte Wert.

Hy,

sobald das Display bei mir eintrifft (das alte hatte einen Kurzschluss 
nicht überlebt...) werde ich mal die Werte auslesen...

Danke

von Rey N. (finwe09)


Lesenswert?

Andreas Auer schrieb:
> Hi,
>
> hat leider etwas gedauert, aber anbei sind die Sourcen für die
> kapazitive Touch Sensor Geschichte. Es ist auch eine Demoapplikation
> dabei, die das Softwaregerüst verwendet (leider undokumentiert). Aber
> durch die Applikation erklärt sich das eine oder andere sicher von
> selbst.
>
> lg.
> Andreas

Hy Andreas,

danke für die Files... versuche das mal nachzuvollziehen und melde mich 
ggfls. hab da mit Sicherheit noch die ein oder andere Frage

Vg Rey

von Alex (Gast)


Lesenswert?

Hallo,

Mal eine frage:
Ergeben sich Unterschiede bei "Reichweite" und Empfindlichkeit bzw. 
Auslesesicherheit des Touchpads bei unterschiedlichen 
AtmelversorgungsSpannungen?
also:
Misst man mit Vcc = 5V besser und sicherer als mit VCC = 3,3V?

Vielen Dank,
Alex

von Tim  . (cpldcpu)


Lesenswert?

Hallo zusammen,

ich habe mich, mit Hilfe dieses exzellenten Threads, auch an die 
Implementation der Ladungspumpentechnik mit einem externen Kondensator 
gemacht. Der Ansatz funktioniert eigentlich recht gut, unpraktisch ist 
nur die starke Prozessorbelastung.

Auf halben Wege bin ich über diese App-Note von Atmel zu einem noch 
interessanteren Ansatz gestoßen (QtouchADC): 
http://www.atmel.com/Images/doc8497.pdf
Im Gegensatz zum Ansatz aus dem Thread, wird die Ladung aus dem Touchpad 
nicht in einen externen Kondensator sondern in den internen Sample&Hold 
Kondensator des AD-Wandlers umgeladen. Die Spannung am S&H Kondensator 
kann dann über den ADC direkt ausgewertet werden. Danach wird der S&H 
Kondensator aufgeladen und über das Touchpad entladen. Die Ergebnisse 
beider Messungen werden kombiniert.

Die Vorteile sind offensichtlich: Nur ein externes Bauteil, schneller, 
Interruptfähig.

Da ich die Library nicht nutzen kann/will, habe ich auch diese Methode 
nachgekocht. Soweit funktioniert es recht gut. Der Code unten setzt 
folgende Schritte um:

1)  Pad über Pin1 auf 0V Entladen
    S&H Kondensator über Pin0 auf 5V Laden (AREF)

2)  S&H Kondesator mit Pin1 ADC Verbinden
    ADC Auslesen

3)  Pad über Pin1 auf 5V Laden
    S&H Kondensator über Pin0 auf 0V Entladen.

4)  S&H Kondesator mit Pin1 ADC Verbinden
    ADC Auslesen

5)  Ergebnisse aus 2) und 4) subtrahieren.

Und hier auch die Frage: Um den S&H Kondensator gezielt zu be- und 
entladen, schalte ich den ADC über den Multiplexer an einen freien Pin 
(Pin0), an den ich über den Ausgangstreiber das gewünschte Potential 
anlage. Erstaunlicherweise funktioniert dieese auch ohne einen 
ADC-Vorgang auszulösen. Ist dieses irgendwie erklärbar? Außerdem gibt es 
eine starke Beeinflussung durch externe Streukapazitäten an Pin0. Gibt 
es eine bessere Möglichkeit zur Umsetzung?


1
  // Init ADC
2
  
3
  ADMUX  =_BV(REFS0)|0x0f;
4
  ADCSRA  =_BV(ADEN)|_BV(ADPS2)|_BV(ADPS1)|_BV(ADPS0); // Enable ADC, Set prescaler to 128
5
6
7
int  senseadctwice(void) {
8
  /*
9
      Capacitive sensing using charge sharing between 
10
      the S/H capacitor and an external sensing pad
11
      
12
      ATMega 328P
13
      Float/ref  Analog0  = PC0
14
      Sense an  Analog1 = PC1
15
  */  
16
17
  int dat1,dat2;
18
  
19
  // Precharge Low
20
  ADMUX  =_BV(REFS0)|0x00;  // Charge S/H cap from Analog0
21
  
22
  PORTC = _BV(PC0);    // S/H Charge Vdd (Analog0), Cext (Analog1) gnd
23
  DDRC = _BV(PC1)|_BV(PC0);
24
  _delay_us(8);
25
  DDRC  &=~(_BV(PC1));  // float input
26
              // additional delay due to ADC logic
27
28
  ADMUX  =_BV(REFS0)|0x01; // Read Cext from Analog1
29
  ADCSRA  |=_BV(ADSC); // Start conversion
30
  
31
  while (!(ADCSRA&_BV(ADIF)));    
32
  ADCSRA  |=_BV(ADIF); // Clear ADIF
33
34
  dat1=ADC;
35
36
  // Precharge High
37
  ADMUX  =_BV(REFS0)|0x00;  // Charge S/H cap from Analog0
38
  
39
  PORTC = _BV(PC1);    // S/H Charge gnd (Analog0), Cext (Analog1) Vdd
40
  DDRC = _BV(PC1)|_BV(PC0);
41
  _delay_us(8);
42
43
  DDRC  &=~(_BV(PC1));
44
  PORTC =0;      // pull up off
45
            // additional delay due to ADC logic
46
47
  ADMUX  =_BV(REFS0)|0x01; // Read Cext from Analog1
48
  ADCSRA  |=_BV(ADSC); // Start conversion
49
  
50
  while (!(ADCSRA&_BV(ADIF)));
51
  ADCSRA  |=_BV(ADIF); // Clear ADIF
52
53
  dat2=ADC;
54
55
  return dat2-dat1;
56
}

von srubs (Gast)


Angehängte Dateien:

Lesenswert?

hallo zusammen.
den code, den Autor: Martin J. (bluematrix)veröffentlicht hat. kann es 
sein, das da noch viele sachen zum funktionieren fehlen.? allein die 
LEDs müssen ja irgentwo mal deklariert werden.
außerdem verstehe ich dieses stück noch nicht:

void read_senskey( void )
{
  uint16_t i = MAX_CYCLE;
  uint8_t a, b, x, y;

  ATOMIC_BLOCK(ATOMIC_FORCEON)
    {
    a = DDRE  & ~(SK_A012 | SK_B012);
    b = PORTE & ~(SK_A012 | SK_B012);
    y = SK_B012;                          // input mask
    do
      {
      DDRF   = a;                           // tristate
      PORTF   = b | SK_B012;
      DDRF   = a | SK_B012;                 // Bx = strong high
      DDRF   = a;                           // tristate
      PORTF   = b;
      DDRF   = a | SK_A012;                 // Ax = strong low

kann mir jemand helfen.? ich finde das projekt auch voll genial.

danke

von Niels K. (niesl)


Lesenswert?

Der Vollständigkeit halt halber wollte ich hier noch den Code für den 
XMega posten. Erklärt wurde er ja in diversen Beiträgen.
1
static uint16_t sense(void)
2
{  
3
  uint16_t i=0;          
4
  // discharge
5
    SNSPort.DIR |= (1<<SNSPIN);
6
    SNSPort.OUT &= ~(1<<SNSPIN);
7
    SNSKPort.DIR |= (1<<SNSKPIN);
8
    SNSKPort.OUT &= ~(1<<SNSKPIN);  
9
    delay_us(5);    
10
  for(i=0; i<2000 && !(SNSPort.IN & (1<<SNSPIN)); i++)
11
  {
12
       SNSKPort.DIR &= ~(1<<SNSKPIN);
13
    SNSPort.OUT |= (1<<SNSPIN);
14
    SNSPort.DIR |= (1<<SNSPIN);
15
    SNSPort.DIR &= ~(1<<SNSPIN);
16
    SNSPort.OUT &= ~(1<<SNSPIN);
17
    SNSKPort.DIR |= (1<<SNSKPIN);
18
  }
19
  SNSPort.DIR |= (1<<SNSPIN);
20
  return i;
21
}

von Dieter M. (Gast)


Lesenswert?

Hallo,

ich würde das qtouch modul vom 32-Bit Atmel µC AT32UC3L032 gerne 
verwenden, um kleine Kapazitätsänderungen zu detektieren (pF-Bereich). 
Nachdem ich mir dieses Thema durchgelesen habe, hätte ich noch ein paar 
Fragen dazu:

Ist es prinzipiell möglich, so kleine Kapazitätsänderungen zu 
detektieren?

Gehe ich richtig in der Annahme, dass ich die oben angeführten 
Codebeispiele nicht auszuprogrammieren brauche, weil im verwendeten µC 
das Modul integriert ist?

Die Sens-Kapazität Cs und die sich ändernde Kapazität werden extern an 
die beiden entsprechenden Pins des µC gelegt?

Wie genau funktioniert der Counter? Werden hier einfach die Takte 
gezählt, die benötigt werden, bis die Spannung am Cs als High erkannt 
wird oder wird dazu ein eigener Counter verwendet?

Vielen Dank für die Hilfe!

von Dieter M. (Gast)


Lesenswert?

Zusätzlich müsste ich die Kapazitätsänderung innerhalb von 1 ms 
erkennen. Ist das prinzipiell überhaupt möglich? Dafür müsste ich Cs 
vermutlich kleiner machen, was sich wieder negativ auf die Auflösung der 
Count-Werte auswirkt. Könnte mir jemand einen Tip geben?

von Dieter M. (Gast)


Lesenswert?

Eine Frage hätte ich dabei noch: was ist der Unterschied zwischen 
"Sensitivity" und "out-of-touch-Sensitivity" ??

von H.Joachim S. (crazyhorse)


Lesenswert?

Ok, was älter - macht aber nichts :-)
Toucherkennung selbst läuft super, aber die Platine muss über I2C 
angebunden werden (I2C-slave, ATMega328P, Master ist ein STM32). 
Ausserdem noch ein paar andere Sachen die am ATMega hängen.
Und jetzt beisst sich die Sache, read_senskey() dauert etwa 8ms, 
natürlich tödlich für die eigentlich asynchrone I2C-Kommunikation. Mit 
freigegebenem Interrupt läuft die touch-Sache mehr schlecht als recht, 
mit gesperrtem Interrupt ist die Kommunikation Glückssache.
Mir fällt da keine ordentliche Lösung ein. Im Moment habe ich eine zus. 
Leitung gefädelt, die dem master sagt, wann er mit dem slave babbeln 
darf. Funktioniert auch, aber ich habe nur eine 4polige Verbindung 
zwischen den Platinen (die Gegenseite ist fertig, nicht auf meinem Mist 
gewachsen). Irgendwelche Ideen, wie man das Problem lösen könnte?
Ich denke mal, ich werde einen AT42QT2120 o.ä. zus. verwenden.

von Peter D. (peda)


Lesenswert?

H.Joachim S. schrieb:
> tödlich für die eigentlich asynchrone I2C-Kommunikation.

Warum, I2C ist doch nicht zeitkritisch. Der Slave kann einfach über 
Clock-Stretching den Master warten lassen.

Hier mal ein Beispiel für ADC-Touch:
Beitrag "Re: Touch-Controller für Lampe"

von c-hater (Gast)


Lesenswert?

H.Joachim S. schrieb:

> Und jetzt beisst sich die Sache, read_senskey() dauert etwa 8ms,
> natürlich tödlich für die eigentlich asynchrone I2C-Kommunikation.

I2C ist nicht asynchron, sondern im Gegenteil voll synchronisiert. Es 
gibt also nicht nur einen Takt (die ABWESENHEIT eines solchen macht 
eine asynchrone Kommunikation aus), sondern der Slave kann ihn obendrein 
nach seinen Bedürfnissen verlangsamen, theoretisch bis zum völligen 
Stillstand.

Aus praktischen Gründen wird man aber einen Timeout sinnvoller Größe 
setzen. In deinem Fall muss der halt dann einfach nur größer als 8ms 
sein, das ist alles.

Funktioniert die Kommunikation trotzdem nicht, hast du irgendwas falsch 
gemacht. Suche den Bug.

von Peter D. (peda)


Lesenswert?

H.Joachim S. schrieb:
> Im Moment habe ich eine zus.
> Leitung gefädelt, die dem master sagt, wann er mit dem slave babbeln
> darf.

Die Leitung existiert schon, nennt sich SCL. Natürlich darf der Master 
nicht blockierend in der Mainloop warten, sondern per I2C-Interrupt im 
Hintergrund. Der Interrupt setzt dann ein Flag "habe fertig" zum Main.

von H.Joachim S. (crazyhorse)


Lesenswert?

Mit asynchron meinte ich nicht die Übertragung selbst, sondern dass die 
Kommunikation zu einem unbestimmten (und unpassenden) Moment losgehen 
kann und wird.

clock-stretching klingt interessant. Habe ich ehrlich gesagt noch nie 
benutzt. Das könnte die Lösung sein, muss ich mich mal schlau machen.
Schön ist es dennoch nicht, dass die Interrupts so lange blockiert sind.

Danke erstmal.

von Peter D. (peda)


Lesenswert?

H.Joachim S. schrieb:
> Schön ist es dennoch nicht, dass die Interrupts so lange blockiert sind.

Interrupts können nur durch andere Interrupts blockiert werden.
Interrupts sollte man daher immer kurz halten. Ich versuche möglichst 
unter 200 Zyklen zu bleiben (25µs @8MHz).
8ms in einem Interrupt zu warten, ist definitiv zuviel.

ADC-Touch läßt sich gut im ADC-Interrupt ausführen, d.h. das Main läuft 
dabei weiter.

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.