Überall im Alltag begegnen uns Sensoren jeglicher Art. So auch Touch-Sensoren. Wir finden sie in Handys (Touchscreen), im Trackpad am Laptop oder auch in Ampeln verbaut. Alle sehen sie etwas unterschiedlich aus und dienen teils verschiedenen Anwendungen, dennoch funktionieren die kapazitiven Touchsensoren, alle nach dem gleichen Prinzip. Es gibt zwei Pins, zwischen denen ein hochohmiger Wiederstand geschaltet ist. (etwa 1 Megaohm). Auf dem einen Pin wird dann eine Spannung angelegt und die Zeit gemessen, bis diese Spannung auch beim anderen Pin anliegt. Weil das viel zu schnell geht und wir das sonst nicht messen können fügen wir mit einem kleinen Kondensator etwas Kapazität zur Schaltung hinzu (jedes Kabel hat von sich schon ein ganz kleinen anteil Kapazität und Induktiviät abhängig von seiner Länge). Wie lange das Signal vom einen Pin bis zum anderen bnötigt hängt also von der Kapazität am Empfänger-Pin ab. Je größer diese ist, desto mehr Elektronen müssen fließen um auf dem Empfänger-Pin die gleiche Spannung aufzubauen. Das ist ja alles schön und gut, aber wie hilft uns das bei dem Touch-Sensor weiter? Naja, es ist so, dass auch der eigene Körper eine gewisse Kapazität aufweist, wie ein ganz kleiner Kondensator. Wenn wir nun mit unserem Finger den Empfänger-Pin berühren, fügen wir der Schaltung die körpereigene Induktiviät zu, da wir selbst durch den Boden geerdet sind. Dadurch verändert sich die Latenz von dem Sende- zum Empfänger-Pin ein wenig. Mehr Induktivität ==> mehr Latenz. Diese Latenz können wir messen.

Wenn wir diesen Konzept in einen Schaltplan übertragen müssten sähe das ungefähr so aus:

Wie du in dem Schaltplan erkennst haben wir den Kontakt mit dem menschlichem Körper als Kondensator und Wiederstand dargestellt, die mit der Erde verbunden sind.

Wenn wir dies nun in einen Bauplan für den Raspi übertragen, sieht das zum Beispiel so aus:

In dem Beispiel Nutzen wir Pin 24 zum senden und Pin 23 zum Empfangen.

Damit wir diesen Aufbau auch nutzen können brauchen wir noch das ensprechende Skript.

Erstelle eine neue Datei touch.py mit nano.

Zunächst importieren wir die GPIO und die time Bibliothek:

import time
import RPi.GPIO as GPIO

Dann definieren wir einige Variablen:

send = 27
receive = 17
limit = 0.0145

send ist der Pin von dem wir das Signal senden, recieve ist der Pin, mit dem wir das Signal empfangen und limit ist der Grenzwert, ab dem wir eine Berührung erkannt haben.

Als nächstes definieren wir eine Funktion, mit der wir die Latenz messen können.

def measure():
  # reset
  GPIO.output(send, False)
  while GPIO.input(receive) == True:
    time.sleep(0.00001)

  # measure
  time_started = time.time()
  GPIO.output(send, True)
  while GPIO.input(receive) == False:	
    continue
  return time.time() - time_started

Bevor wir mit dem Messen starten, müssen wir warten, dass beide Pins LOW sind, Damit unser Messergebniss nicht verfälscht wird. Wir seten also den sende-Pin auf LOW und warten bis bis der empfänger-Pin auch LOW ist.
Danach können wir die Messung starten. Wir schreiben also die Aktuelle Zeit als timestamp in die Variable time_started und setzen den Sende-Pin auf HIGH. Dann lassen wir solange eine while-Schleife, laufen, bis der Empfangs-Pin nicht mehr LOW ist und geben dann mit return time.time() - time_started die Differenz aus dem aktuellen Timestamp und dem Timestamp als wir die Messung gestarted haben zurück.

Kommen wir zum letzten Block. Damit wir genauere messwerte erzielen können, führen wir die Messung mehrmals durch und berechnen dann den Mittelwert.

try:
  while True:
    # measure delay
    sum = 0
    for i in range(8):
      sum += measure()
    diff = sum/8
    print(diff)
    if diff > limit:
      print('Berührung erkannt')
    time.sleep(0.05)

except KeyboardInterrupt:
  GPIO.cleanup()

Zunächst setzen wir die Variable sum und setzen diese erstmal auf 0. Dann starten wir eine for-Schleife. Dadurch führen wir den Eingerückten Teil 8x aus. Wir führen also acht Messungen durch und addieren diese zusammen.
Im nächsten Schritt teilen, wir die Summe aller Messungen wieder durch 8 um den Durchschnitt zu erhalten. Diesen schreiben wir in die Konsole. Dann überprüfen wir noch, ob der Wert überhalb unseres Grenzwertes liegt und wenn ja, schreiben wir das noch in die Konsole. Der gesamte Block befindet sich noch in einem try Block, damit beim Beenden des Programms die Pinbelegung durch GPIO.cleanup() wieder aufgehoben wird.

Wenn du alles zusammengefügt hast, kannst du dein Skript jetzt starten. Dir sollten auf der Konsole dann ganz viele Zahlen mit den aktellen Messwert angezeit werden und ob der Kontakt berührt wird oder nicht. Wenn dein Sensor noch nicht ganz richtig erkennt, ob er berührt wird oder nicht, kannst du den Grenzwert anhand der Werte in der Konsole anpassen.