Así es como finalmente puse en práctica el fabuloso enfoque esbozado por VillageTech .
Hardware
Cableado
El pin por defecto para los dispositivos Onewire en el Pi es GPIO 4
. Así que conecté GND
al manguito de la clavija y conectó la punta al mencionado pin GPIO.
Una ficha
Todo lo que necesito para una ficha es el chip DS18B20 y un jack de 3,5mm. Entonces suelda el pin GND y VCC del chip juntos y conéctalo a la funda. Añade un poco de tubo retráctil al pin del medio para evitar cortocircuitos y conéctalo a la punta del jack.
Ambas tomas funcionan las que tienen dos anillos y la que sólo tiene la punta.
Resistencia pull up
Decidí no usar una resistencia pull up externa, ya que la Pi tiene resistencias pull up internas.
No friamos los auriculares
Como flawr Se ha señalado correctamente el hecho de que si parece una toma de audio de 3,5 mm, la gente podría verse tentada a introducir los auriculares.
Siempre que utilicemos energía parásita, en la que sólo un cable de tierra y una salida GPIO de alta impedancia estén expuestos al enchufe, deberíamos estar seguros, ya que no tenemos un V DD línea que podría crear un cortocircuito a través de la baja resistencia de los auriculares.
Configuración
Añade la siguiente línea a /boot/config.txt
:
dtoverlay=w1-gpio
Hay más opciones. Puede encontrar más en el /boot/overlays/README
de su Pi.
Algunas fuentes sugieren añadir los dos módulos w1-gpio
y w1_therm
à /etc/modules
Sin embargo, descubrí que la entrada de la superposición del árbol de dispositivos en el boot/config.txt
era suficiente para mis propósitos.
Ahora reinicie el dispositivo.
Añadir un pullup por software en python:
import RPi.GPIO as GPIO
GPIO_PIN_NUMBER=14
GPIO.setmode(GPIO.BCM)
GPIO.setup(GPIO_PIN_NUMBER, GPIO.IN, pull_up_down=GPIO.PUD_UP)
En cuanto creé este pull up pude detectar los tokens en /sys/bus/w1/devices/
con el 28
en otra ventana de terminal:
$ ls /sys/bus/w1/devices/
28-00000aabbccd w1_bus_master1
Después de unos 10 segundos, las entradas en devices
desaparecería. Tuve que crear la siguiente configuración, para que los dispositivos desaparecieran después de un segundo más o menos:
sudo nano /etc/modprobe.d/w1.conf
Ahora añade el contenido al archivo y reinicia el dispositivo de nuevo:
options wire timeout=1 slave_ttl=1
En mi configuración este archivo no existía previamente.
Software
Creé una clase de python que buscara cambios en el sistema de archivos y me dijera si un nuevo token estaba conectado o si todos los tokens estaban desconectados.
import os
import thread
import time
from datetime import datetime, timedelta
class W1Service(object):
__instance = None
def __new__(cls):
# Singleton initializer
if W1Service.__instance is None:
W1Service.__instance = object.__new__(cls)
return W1Service.__instance
on_all_token_removed = None
on_token_added = None
is_scanning = False
def start_scan(self, delay=10):
return thread.start_new_thread(self.scan, (delay,))
def scan(self, delay=10):
W1Service.is_scanning = True
last_token = None
current_token = ''
current_token_timestamp = datetime.now() - timedelta(days=1)
while W1Service.is_scanning:
file = open('/sys/devices/w1_bus_master1/w1_master_slaves')
all_tokens = file.readlines()
file.close()
no_token_attached = len(all_tokens) == 0 or 'not found.\n' in all_tokens
if no_token_attached and self.on_all_token_removed and current_token != last_token:
self.on_all_token_removed()
current_token = None
last_token = None
for line in all_tokens:
current_token = line.split("\n")[0]
time_diff = datetime.now() - current_token_timestamp
if self.on_token_added and last_token != current_token and time_diff.seconds >= 3:
# Test if the token is still attached
if os.path.exists('/sys/bus/w1/devices/' + current_token + '/w1_slave'):
self.on_token_added(current_token)
last_token = current_token
else:
current_token = None
else:
current_token = None
time.sleep(delay)
def stop_scan(self):
W1Service.is_scanning = False
Ahora utilizar el servicio creado es bastante sencillo:
import time
import w1_service
def token_added(token):
print("Connected %s" % token)
def all_token_removed():
print('All tokens were removed')
service = w1_service.W1Service()
service.on_token_added = token_added
service.on_all_token_removed = all_token_removed
service.start_scan(0)
while True:
# The scan runs in a seperate thread
time.sleep(1)
Esto producirá la siguiente salida al insertar diferentes fichas
All tokens were removed
Connected 28-00000aabbccd
All tokens were removed
Connected 28-00000ffddeea
All tokens were removed
Connected 28-00000bbddaa1
Connected 28-00000ffddeea
All tokens were removed
Connected 28-00000bbddaa1
All tokens were removed
Tenga en cuenta que mi código tiene en cuenta el hecho de que en mi configuración sólo se puede añadir un token a la vez. Así que sólo el token más nuevo es interesante para mí. Si se añaden múltiples tokens, que el protocolo onewire soporta muy bien, el código tendría que ser actualizado.
Aplicación
Ahora, cada vez que se inserta un token, éste se relaciona con una persona a la que mi nice puede enviar y recibir mensajes
Notas y otras consideraciones
En teoría, los tokens de Onewire podrían añadirse en paralelo, lo que ofrecería nuevas capacidades como el chat de grupo o similares. Así que podrías conectar diez tokens en un solo GPIO.
También me gusta el planteamiento con el enfoque R/C pasivo, que es muy pragmático y sencillo de montar también. Puede que lo pruebe en otro proyecto. Sin embargo, un amigo tenía algunos
Consideré añadir iBeacons como tokens, pero entonces tendría que tener en cuenta los diferentes RSSI de los tokens y no estaría 100% claro qué token estaba activo en cada momento.
Un amigo me sugirió que añadiera un lector de tarjetas y que utilizara tarjetas SD antiguas de 1 GB para fotos que pudieran tener la imagen pegada en la parte delantera. La tarjeta podría contener toda la información sobre la persona más un saludo personalizado o algo parecido. Lo mismo se podría hacer con viejas memorias USB como fichas.
Fue muy divertido ponerlo en práctica y ver el interés que despertó mi pregunta en la gente. Os doy las gracias a todos y os deseo un bonito 0x1414
(=2020) :-)