Ich versuche, meine eigene Wecklampe zu machen. Ich habe eine Lampe mit einem großen Metallsockel, um alle Komponenten darin zu verstecken. Ich habe auch ein Velleman K8064 DC Controlled Dimmer Kit , das ich zusammengestellt habe und funktioniert. Ich habe einen Raspberry Pi, um alles zu steuern (ich plane auch, den Pi als Android Dock zu verwenden)
Ich möchte, dass der Sockel der Lampe als Berührungsschalter funktioniert, um die Lampe ein- und auszuschalten. Ich habe versucht, einen Berührungsschalter, den ich auf www.talkingelectronics.com gefunden habe, mit einem Steckbrett zu versehen , aber beim Testen ist die Lampe immer an.
Kann mir jemand einen Schaltplan eines einfacheren Berührungsschalters zeigen, der mit einem Himbeer-Pi funktioniert?
Wenn Sie Low-Level-Zugriff auf die kratzigen GPIOs haben, gibt es eine einfache Möglichkeit, dies zu tun. Sie benötigen lediglich einen Widerstand. Ja, du hast richtig gelesen.
Schließen Sie einfach einen Stift an den Lampensockel an und binden Sie den Widerstand zwischen Sockel und , das ist die 3,3-V-Schiene, denken Sie daran, dass die Pins nicht 5-Volt-tolerant sind.
Hier ist in Pseudocode, was Sie softwareseitig tun müssen:
while(1) {
timer.reset()
gpiox.direction = GPIO.OUT
gpiox.write(GPIO.LOW)
while(gpiox.read != GPIO.LOW)
gpiox.direction = GPIO.IN
timer.start()
while(gpiox.read == GPIO.LOW)
timer.stop()
out = timer.read()
if (out > THRESHOLD)
pressed = true
else
pressed = false
}
Was ist los? Zuerst setzt du einen Timer zurück. Es muss schnell sein, so etwas wie ein CPU-Timer, der bei jedem Taktzyklus oder so inkrementiert wird.
Sie setzen Ihren Pin als Ausgang, schreiben eine Null darauf und warten dann, bis er wirklich auf Null geht. Dies kann je nach Treiber/HAL, den Sie verwenden, innerhalb des Schreibvorgangs erfolgen, aber damit dies funktioniert, müssen Sie keinen verwenden. Nachdem der Pin wirklich Null ist, setzen Sie ihn als Eingang und starten den Timer. Die parasitäre Kapazität des Lampensockels und des Stifteingangs und, falls vorhanden, Ihres Fingers beginnt sich über den Widerstand aufzuladen. Wenn die Spannung über der Kapazität als logisch hoch gelesen wird, stoppen Sie den Timer: Der Trick besteht darin, dass die Kapazität größer ist, wenn Ihr Finger vorhanden ist, sodass das Laden auf die logische Eins viel länger dauert, sodass Sie dies erkennen können Fingeranwesenheit durch Ablesen des Timers.
Auf welche Probleme könnten Sie stoßen?
Nun, vielleicht haben Sie einfach keinen so niedrigen Zugriff auf die kratzigen GPIO-Pins ... Aber das müssen Sie herausfinden. Vielleicht haben Sie keinen solchen Low-Level-Timer. Das größte Problem ist, dass die Kapazität des Lampensockels möglicherweise sehr groß ist, sodass eine Berührung keinen großen Unterschied macht.
Diese Methode ist auf jeden Fall einen Versuch wert, da sie ein paar Cent kostet. Über den Widerstand möchten Sie etwas, das die Kapazität langsam genug auflädt, damit Ihr Timer tatsächlich die benötigte Zeit messen kann, aber schnell genug, um den "Knopf" möglicherweise 20 Mal pro Sekunde tatsächlich abzutasten. Lampe plus Körper plus Stift kann etwa 1 nF betragen, Sie möchten a von etwa 20ms so
Aber wie funktioniert es?
Alles um uns herum hat eine Kapazität in Bezug auf etwas anderes. Es ist üblich, Masse als "etwas anderes" zu bezeichnen, also hat alles eine Kapazität in Bezug auf Masse. Betrachten wir die folgende Schaltung:
Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan
ist die Eingangskapazität des digitalen Ports plus die Kapazität des Lampensockels gegen Masse, normalerweise etwa 100 pF, während (wie in „Mensch“) ist die Fähigkeit, die wir gegenüber dem Boden haben. Wenn Sie den Lampensockel berühren, schließen Sie den Schalter mit der Aufschrift "Touch", während die Himbeere nur einwirken kann . Sie beginnen mit geschlossen, also . Wenn sich die Himbeere öffnet die Eingangskapazität beginnt sich aufzuladen durch mit Zeitaufwand . Das V(t)-Gesetz ist ziemlich bekannt:
An diesem Punkt würde es den Timer anhalten und prüfen, wie lange es gedauert hat: ob etwas in der Nähe ist
es findet keine Berührung statt. Die Himbeere würde schließen
und warten Sie, bis sich der Kondensator entladen hat, dh warten Sie, bis der Stift Null anzeigt, um schließlich den Schalter zu öffnen und von vorne zu beginnen.
Aber was ist, wenn wir schließen?
? Also,
Änderungen:
jetzt und ggf
klein genug ist, und hoffentlich ist es das auch,
vielleicht sogar zehnmal größer als
. Die Himbeere startet ihren Timer, aber jetzt dauert es erheblich länger, eine hohe Eingabe zu lesen:
Die vorletzte Beziehung ist eine Art "Wir hoffen, das stimmt"-Beziehung. Wenn die Himbeere schließlich eine hohe Eingabe liest, stoppt sie den Timer und sagt: Nun, das dauert ziemlich lange, lasst uns das Licht für meinen Programmierer umschalten! Und das ist so ziemlich alles.
Und warum funktioniert deine Lösung?
Das liegt daran, dass Ihr Körper als Antenne fungiert. Sie speisen im Grunde die Netzfrequenz in den Himbeer-Eingangsstift ein, und das kann dazu führen, dass der Eingang als einer gelesen wird, aber das wäre eine unzuverlässige Möglichkeit, Ihre Lampe umzuschalten. Soweit ich gelesen habe, arbeitet Ihr System ziemlich zufällig ... Versuchen Sie es mit dem richtigen Weg.
Ich habe eine C-Implementierung (siehe unten) basierend auf dem Pseudocode in Vladimirs Antwort geschrieben .
Funktioniert wie ein Zauber auf meinem Pi Zero W, ich benutze es, um die Hintergrundbeleuchtung eines LCD-Displays umzuschalten, indem ich seine Lünette berühre. Ich habe einen 1-MΩ-Widerstand verwendet, der im Leerlauf ~ 20 μs zum Aufladen und beim Berühren 45-110 μs benötigt. Es kann sogar Berührungen durch die nichtleitende Beschichtung auf der Lünette erkennen, daher sollte der Pi vor statischer Entladung geschützt werden.
Bisher hatte ich keine Probleme mit wiederholten Berührungen, die nicht erkannt wurden.
// Filename: touch_toggle.c
/* Compile with gcc -lwiringPi touch_toggle.c -o touch_toggle
* Run with sudo ./touch_toggle
* Do not touch while starting the program so it can initialize properly
*/
/* SCHEMATIC
*
* ,----------------------,
* | Raspberry Pi |
* | |
* | TOUCH_PIN VCC |
* `-----+-------------+--'
* | |
* +---[1MΩ]-----+
* |
* Touch surface
*
*/
#include <wiringPi.h>
#include <stdio.h>
// Note: Pin numbers are in BCM notation (pin number format is set by wiringPiSetupGpio)
// See pinout.xyz
#define TOUCH_PIN 20
#define OUTPUT_PIN 21
// How long to pull the touch pin low
// Controls loop speed and affects CPU usage
#define DELAY 15
int main(void) {
wiringPiSetupGpio();
unsigned int timer;
unsigned int threshold = 0;
unsigned char state = 0; // Currently being touched?
unsigned char out_state = 0; // State of output pin
signed char hysteresis = 0; // Counter for consecutive readings
pullUpDnControl(TOUCH_PIN, PUD_OFF); // Not sure if this would ever be set, just to be safe
pinMode(OUTPUT_PIN, OUTPUT);
digitalWrite(OUTPUT_PIN, out_state);
// Measure capacitance to calibrate touch sensitivity
for (char i=0; i < 10; i++) {
// Pull touch pin low to discharge
pinMode(TOUCH_PIN, OUTPUT);
digitalWrite(TOUCH_PIN, LOW);
// Wait a bit
delay(DELAY);
// Start timer
timer = micros();
pinMode(TOUCH_PIN, INPUT);
// Wait for pin to become high
while (!digitalRead(TOUCH_PIN));
// Get time elapsed
threshold += micros() - timer;
}
// Set threshold to twice the average capacitance
threshold /= 5; // This number might need to be increased if the touch is not sensitive enough
printf("threshold=%d\n",threshold);
while (1) {
pinMode(TOUCH_PIN, OUTPUT);
digitalWrite(TOUCH_PIN, LOW);
delay(DELAY);
timer = micros();
pinMode(TOUCH_PIN, INPUT);
while (!digitalRead(TOUCH_PIN));
timer = micros() - timer;
if (timer > threshold) {
if (hysteresis < 0) hysteresis = 0;
hysteresis++;
} else {
if (hysteresis > 0) hysteresis = 0;
hysteresis--;
}
// 3 consecutive readings are required to toggle touch state
if (hysteresis > 2) {
if (state == 0) {
out_state = !out_state;
digitalWrite(OUTPUT_PIN, out_state);
state = 1;
// Print when touch starts and the measured value
// Can be commented out
printf("START %d", timer);
fflush(stdout); // Display instantly (by default only flushed on newline)
}
hysteresis = 0;
} else if (hysteresis < -2) {
if (state == 1) {
state = 0;
printf(" END\n");
}
hysteresis = 0;
}
}
return 0;
}
Code auch unter: https://pastebin.com/FrsYCtXu
Vielen Dank an Vladimir für seine Antwort, die es mir ermöglicht hat, auf diese Lösung zu kommen.
Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan
Der Python-Code lautet wie folgt
import time
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
touchSwitch = 23
outputPin = 24
GPIO.setup(touchSwitch, GPIO.IN)
GPIO.setup(outputPin, GPIO.OUT)
GPIO.output(outputPin, False)
while True:
switchTouched = GPIO.input(touchSwitch)
if switchTouched:
print "touch detected"
time.sleep(0.3) # sleep again here so not to toggle the lamp to quickly
else:
print "not touched"
time.sleep(0.15) # 0.10 seems to give the best results but 0.15 uses less CPU
Das Problem bei dieser Lösung besteht darin, dass beim Halten der Berührungsplatte nach etwa 5 bis 12 Erkennungen einer Berührung die Berührung eine Zeit lang nicht erkannt wird und dann erneut erkannt wird. Da ich es nur für eine Touch-Lampe verwende, ist die Lösung gut genug für meine Bedürfnisse.
Dies scheint ohne Verzögerung zu funktionieren (unter Verwendung der Schaltung von TheLukeMcCarthy, aber mit GPIO 18 als Eingang und GPIO 17 als Ausgangspin)
#include <wiringPi.h>
int main (void)
{
register unsigned char on = 0 ;
wiringPiSetup () ;
pinMode ( 1, INPUT) ;
pinMode ( 0, OUTPUT) ;
pinMode ( 4, OUTPUT) ;
digitalWrite ( 4, LOW) ;
digitalWrite ( 0, LOW) ;
while ( 1 )
{
if ( digitalRead (1) )
{
if ( on )
{
on=0;
digitalWrite ( 4, LOW) ;
}
else
{
on=1;
digitalWrite ( 4, HIGH) ;
}
delay ( 300 ) ;
}
delay ( 50 ) ;
}
return 0 ;
}
Der Luke McCarthy
Wladimir Cravero
Der Luke McCarthy
Der Luke McCarthy
Wladimir Cravero
Der Luke McCarthy
Wladimir Cravero
Wladimir Cravero