Veleta calcular dirección del viento
Teoria
La veleta es un sensor analógico que nos da la dirección del viento. Está montado con 8 resistencias que se van levantando conforme la veleta gira lo que termina dándonos 16 posiciones para la lectura del viento, en mi caso solo usaré 8 posiciones. Estas posiciones se pueden leer viendo el voltaje de salida de la veleta.
La PCB de la veleta se ve así:

Para leer el voltaje de salida de la veleta hay que tener varias cosas en cuenta.
Primero de todo, al ser mediciones de voltaje lo que queremos medir es una señar analógica y por lo tanto necesitaremos un ADC (conversor de analógico a digital) que nos traduzca el voltaje a valores que pueda leer la Raspberry Pi mediante el protocolo I2C. En mi caso usaré el ADC ADS1115 debido a que he tenido malar experiencias con el ADC MCP3008.
Segundo, hay que tener en cuenta el voltaje de entrada ya que dependiendo es esto el voltaje de salida será diferente. Está pensado para funcionar a 5V, pero en nuestro caso funcionará a 3.3V.
Tercero y último, hay que poner una resistencia, en el caso de estar conectado a 5V tocaría usar una de 10KOhms y en el caso de 3.3V se usa una de 4.7kOhms. Las resistencias se usan para reducir la intensidad del voltaje antes de que lo lea el ADC ya que si no se le pusiese leería en casi todas las posiciones el voltaje máximo de entrada
Ahora el RJ11 tiene 4 cables. Los dos del anemómetro que están en la misma posición y los dos de la veleta que van uno a cada lado. Por lo que en anemómetro hay que conectarlo a la veleta para ahorrarnos un conector RJ11 y cables extra para conectarlo a la Raspberry Pi.
Cableado
Ala hora de clablearlo primero tenemos que conectar el anemómetro directamente a la veleta y esta última será la que pase los datos a la Raspberry Pi. El esquema es el siguiente:

La veleta funciona con 4 cables, 2 del anemómetro que se conecta a la veleta y otros dos de la propia veleta. Como se puede observar en el esquema anterior. Siguiendo esa numeración de cables las conexiones son las siguientes:
- Cable 1: este se conecta a un pin 3.3V de la placa.
- Cable 2: este se conecta a un pin GND de la placa.
- Cable 3: este se conecta al pin GPIO5 de la placa.
- Cable 4: este se conecta al canal 0 del ADS1115. Por este cable pasará el voltaje de salida de la veleta el cual tenemos que leer mediante el ADC.
En el caso del conversor ADS1115 tenemos que hacer las siguientes conexiones para poder leer el voltaje de salida del cable 5 de la veleta:
- Pin VDD: se conectará a un pin 3.3V de la placa.
- Pin GND: se conectará a un pin GND de la placa.
- Pin SCL: se conectará a un pin SCL de la placa.
- Pin SDA: se conectará a un pin SDA de la placa.
- Pin A0: es el comentado en el punto anterior. Se conecta al cable 4 de la veleta.
- Resistencia 4.7k Ohms: se pone entre el cable 4 de la veleta y el ADC para reducir la intensidad de voltaje. Va conectado a una fase de tierra.
Su diseño queda de la siguiente forma:

Recomiendo mirar la numeración de los cables del puerto RJ11 para comprender mejor cómo está cableado el circuto:
Funcionamiento
A la hora de crear el código he hecho una tabla de direcciones y voltajes para saber dónde está apuntando la veleta.
Voltaje | Dirección |
---|---|
0.10V – 0.18V | Oeste |
0.18V – 0.35V | Noroeste |
0.35V – 0.55V | Norte |
0.55V – 0.90V | Suroeste |
0.90V – 1.30V | Norte |
1.30V – 1.95V | Sur |
1.95V – 2.40V | Sureste |
2.40V – 3.00V | Este |
Esta tabla se ha conseguido viendo el voltaje dado en por la veleta cada vez que la giraba 45º. Se puede observar que conforme se aumenta el voltaje el margen es cada vez más amplio.
Tenemos que importar tres librerías, de una de ellas tenemos que importar dos cosas como podemos ver a continuación:
import board
: la usaremos para acceder a los canales SCL y SDA de la placa.import busio
: este tiene la comunicación I2C al que le pasamos los canales SCL y SDA.import adafruit_ads1x15.ads1115 as ADS
: Con el accederemos al método de nuestro ADC el ADS1115.from adafruit_ads1x15.analog_in import AnalogIn
: lo usaremos para acceder a los canales del ADS1115 y leer los voltajes.
La clase se llama Veleta y nos devolverá a la clase principal la dirección del viento y si está en funcionamiento como booleano. Al estar conectado al ADC puede que este falle en la lectura si deja de funcionar por lo que en ese supuesto la veleta devolverá al programa principal que no está en funcionamiento y no preguntará por la dirección del viento.
Código
Test
En este apartado tienes el código básico para leer los pulsos de voltaje y pasarlos a direcciónes del viento. Es importante poner el puerto correcto que en este caso es el puerto 0.
import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
class Veleta:
def __init__(self):
self.direccion = "None"
def iniciarLectura(self):
'''Hace la lectura del voltaje de salida de la veleta'''
# Crear el bus I2C
i2c = busio.I2C(board.SCL, board.SDA)
# Creando el objeto ADC mediante el bus I2C
ads = ADS.ADS1115(i2c)
# Creando una entrada para el canal 0 del ADC
chan = AnalogIn(ads, ADS.P0)
# Creando una entrada para los canales 0 y 1
#chan = AnalogIn(ads, ADS.P0, ADS.P1)
# Lectura del dato
voltaje = chan.voltage
return voltaje
def getDireccion(self):
'''Mediante el voltaje de salida de la veleta determinará
la dirección del viento Devolviendo así un String con el
resultado'''
voltaje = self.iniciarLectura()
if (voltaje > 0.100 and voltaje < 0.180):
self.direccion = "O"
elif (voltaje >= 0.180 and voltaje < 0.350):
self.direccion = "NO"
elif (voltaje >= 0.350 and voltaje < 0.550):
self.direccion = "N"
elif (voltaje >= 0.550 and voltaje < 0.900):
self.direccion = "SO"
elif (voltaje >= 0.900 and voltaje < 1.300):
self.direccion = "NE"
elif (voltaje >= 1.300 and voltaje < 1.950):
self.direccion = "S"
elif (voltaje >= 1.300 and voltaje < 1.950):
self.direccion = "S"
elif (voltaje >= 1.950 and voltaje < 2.400):
self.direccion = "SE"
elif (voltaje >= 2.400 and voltaje < 3.000):
self.direccion = "E"
else:
self.direccion = "None"
return self.direccion
objeto_veleta = Veleta()
print(objeto_veleta.getDireccion())
Avanzado
En este caso la programación mas pesada estaba paradógicamente en la parte básica. Para derirlo al programa principal lo único que necesitamos es que recoja la excepción de voltaje no leído ya que el valor nos lo tiene que pasar el conversor ADC y puede que la comunicación falle.
import time
import board
import busio
import adafruit_ads1x15.ads1115 as ADS
from adafruit_ads1x15.analog_in import AnalogIn
class Veleta:
'''Le la dirección del viento mediante la veleta.'''
def __init__(self):
self.direccion = "None"
def iniciar_lectura(self):
'''Crea un objeto del chip ADS1115 para poder leer los datos
de la veleta.'''
# Crea un bus I2C
i2c = busio.I2C(board.SCL, board.SDA)
try:
# Crea un objeto ADC usando el bus I2C
ads = ADS.ADS1115(i2c)
# Entrada del canal 0 del chip
chan = AnalogIn(ads, ADS.P0)
voltaje = chan.voltage
# Recoge el error de lectura del canal SDA
except ValueError:
voltaje = 0
return voltaje
def get_direccion_viento(self):
'''Mediante el voltaje de salida de la veleta determinará
la dirección del viento Devolviendo así un String con el
resultado. Hay 8 direcciones posibles.'''
voltaje = self.iniciar_lectura()
if 100 < voltaje < 0.180:
self.direccion = "O"
elif 0.180 < voltaje < 0.350:
self.direccion = "NO"
elif 0.350 < voltaje < 0.550:
self.direccion = "N"
elif 0.550 < voltaje < 0.900:
self.direccion = "SO"
elif 0.900 < voltaje < 1.300:
self.direccion = "NE"
elif 1.300 < voltaje < 1.950:
self.direccion = "S"
elif 1.300 < voltaje < 1.950:
self.direccion = "S"
elif 1.950 < voltaje < 2.400:
self.direccion = "SE"
elif 2.400 < voltaje < 3.000:
self.direccion = "E"
else:
self.direccion = "None"
return self.direccion