Loading...

Veleta calcular dirección del viento

Pablo Durán
Comparte el post:

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í:

PCB de la veleta

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:

Orden de los cables rj11

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:

Cableado de la veleta

Recomiendo mirar la numeración de los cables del puerto RJ11 para comprender mejor cómo está cableado el circuto:

Esquema de la veleta.

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.

diagrama de la veleta.

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