Si tienes acceso de bajo nivel a los GPIO's de Raspy, hay una manera fácil de hacerlo, todo lo que necesitas es un reisistor. Sí, has leído bien.
Sólo hay que conectar una clavija a la base de la lámpara y atar la resistencia entre la base y \$V_{cc}\$ , ese es el riel de 3.3V, recuerda que los pines no son tolerantes a 5 voltios.
Aquí está en pseudocódigo lo que necesitas hacer del lado del software:
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
}
¿Qué ocurre? En primer lugar, reinicias un temporizador. Tiene que ser rápido, algo así como un temporizador de la cpu que se incrementa en cada ciclo de reloj más o menos.
Estableces tu pin como ouput, escribes un cero en él y luego esperas a que realmente se ponga a cero. Eso puede hacerse dentro de la escritura dependiendo del driver/HAL que estés usando, pero para que esto funcione necesitarás no usar ninguno. Después de que el pin esté realmente a cero lo pones como entrada y arrancas el temporizador. La capacitancia parásita de la base de la lámpara y de la entrada del pin y, si está presente, tu dedo comienza a cargarse a través de la resistencia. Cuando el voltaje a través de la capacitancia se lee como un alto lógico paras el temporizador: el truco es que si tu dedo está presente la capacitancia es mayor por lo que tarda mucho más en cargarse hasta el uno lógico, por lo que puedes saber la presencia del dedo leyendo el temporizador.
¿Qué problemas puede encontrar?
Bueno, tal vez no tengas un acceso de tan bajo nivel a los pines GPIO de la raspa... Pero eso es algo que tienes que averiguar. Tal vez no tengas un temporizador de tan bajo nivel. El mayor problema es que tal vez la capacitancia de la base de la lámpara es muy grande para que al tocarla no haya una gran diferencia.
De todos modos, vale la pena probar este método porque cuesta unos pocos céntimos. Sobre la resistencia, quieres algo que cargue la capacitancia lo suficientemente lento para que tu temporizador pueda realmente medir el tiempo que tarda, pero lo suficientemente rápido para poder realmente muestrear el "botón" quizás 20 veces por segundo. La lámpara más el cuerpo más la clavija pueden ser alrededor de 1nF, usted quiere un \$\tau=RC\$ de unos 20ms por lo que $$R=\frac{\tau}{C}=\frac{20\cdot10^{-3}s}{1\cdot10^{-9}F}=20M\Omega$$ Bueno, eso es demasiado. Necesitarás un temporizador rápido e irás por algo alrededor de \$1M\Omega\$
¿Pero cómo funciona?
Todo lo que nos rodea tiene una capacidad con respecto a otra cosa. Es común referirse a la tierra como "algo más", por lo que todo tiene una capacitancia con respecto a la tierra. Dicho esto, consideremos el siguiente circuito:
simular este circuito - Esquema creado con CircuitLab
\$C_{in}\$ es la capacitancia de la entrada del puerto digital más la capacitancia de la base de la lámpara hacia tierra, normalmente unos 100pF, mientras que \$C_H\$ (como en "humano") es la capacidad que tenemos hacia la tierra. Cuando se toca la base de la lámpara se cierra el interruptor etiquetado como 'toque', mientras que la frambuesa sólo puede actuar sobre \$SW_{in}\$ . Se comienza con \$SW_{in}\$ cerrado, así que \$V_{C_{in}} = 0\$ . Cuando la frambuesa abre \$SW_{in}\$ la capacitancia de entrada comienza a cargarse hasta \$V_{cc}\$ a través de \$R_p\$ con un coste de tiempo \$\tau=R_p\cdot C_{in}\$ . La ley V(t) es bastante conocida: $$V_{C_{in}}(t) = V_{cc}(1-e^{-\frac{t}{\tau}})$$ La frambuesa detectará una entrada alta cuando el voltaje alcance algo alrededor de \$\frac{2}{3}V_{cc}\$ así que eso tomará:
$$t_{HIGH}=\tau\ln\Big(\frac{V_{cc}}{V_{cc}-\frac{2}{3}V_{cc}}\Big)=\tau\ln(3)$$
En este punto se detendría el temporizador y se comprobaría cuánto tiempo ha tardado: si es algo alrededor de \$1.1\tau\$ no se produce ningún toque. La frambuesa se cerraría \$SW_{in}\$ y esperar a que el condensador se descargue, es decir, esperar a que el pin lea cero, para finalmente abrir el interruptor y empezar de nuevo.
Pero, ¿y si cerramos \$SW_h\$ ? Bueno, \$\tau\$ cambios: \$\tau'=R_p\cdot (C_{in}+C_H)\$ ahora, y si \$C_{in}\$ es lo suficientemente pequeño, y espero que lo sea, \$tau'\$ puede ser incluso diez veces mayor que \$\tau\$ . La frambuesa iniciará su temporizador pero ahora tardará bastante más en leer una entrada alta:
$$t'_{HIGH}=...=\tau'\ln(3)\approx 10\cdot\tau\ln(3)=10\tau$$
La penúltima relación es una especie de relación "esperamos que sea verdad". Cuando la frambuesa finalmente leerá una entrada alta, detendrá el temporizador y dirá "bueno, eso tomó mucho tiempo, ¡vamos a encender la luz para mi programador! Y eso es todo.
¿Y por qué funciona su solución?
Esto se debe a que tu cuerpo está actuando como una antena. Básicamente estás alimentando la frecuencia de la red en el pin de entrada de la frambuesa, y eso puede hacer que la entrada se lea como una, pero eso sería una forma poco fiable de alternar tu lámpara. Por lo que puedo leer tu sistema está funcionando de forma bastante aleatoria... Intenta hacerlo de la forma adecuada.