Mostrando entradas con la etiqueta Python. Mostrar todas las entradas
Mostrando entradas con la etiqueta Python. Mostrar todas las entradas

viernes, 13 de junio de 2025

Raspberry Pi sensor DHT11 y DHT22

DHT11
Uno de los sensores más populares utilizados en conjunto con la Raspberry Pi es el DHT11, un sensor de humedad y temperatura de bajo costo y fácil de usar.

¿Qué son los sensores DHT11 y DHT22?

Los sensores DHT11 y DHT22 son dispositivos electrónicos que mide la temperatura y la humedad relativa del aire. Es un sensor digital, lo que significa que los datos que proporciona son en formato digital y pueden ser fácilmente leídos por un microcontrolador como la Raspberry Pi.

DHT22


A pesar de su bajo costo, el DHT11 más que el DHT22, son bastante precisos y fiables, lo que los convierte en una excelente opción para una amplia gama de aplicaciones.

El DHT11 esta más indicado para Proyectos educativos o prototipos simples y ambientes interiores controlados como pueden ser habitaciones, oficinas.

Sin embargo el DHT22 será más útil en proyectos de tipo invernadero, neveras y exteriores.

Funciones del Sensor

  • Medición de temperatura
  • Medición de humedad
  • Salida digital
  • Bajo consumo
  • Fácil de usar

Comparativa: DHT11 vs DHT22

Característica DHT11 DHT22
Precisión (Temp) ±2°C ±0.5°C
Rango (Temp) 0°C a 50°C -40°C a 80°C
Precisión (Hum) ±5% RH ±2% RH
Rango (Hum) 20% a 80% RH 0% a 100% RH
Frecuencia de Muestreo 1 Hz 0.5 Hz
Resolución 1°C / 1% RH 0.1°C / 0.1% RH
Consumo Eléctrico 0.5 - 2.5 mA

Instalación y Configuración en Python:

Para utilizar los sensores DHT11 y DHT22 con una Raspberry Pi, necesitaremos un entorno de programación adecuado y una biblioteca para interactuar con el sensor. Python es uno de los lenguajes de programación más populares para la Raspberry Pi, y existen varias bibliotecas que facilitan la lectura de datos del DHT11.

Necesitamos instalar la biblioteca Adafruit. Ahora en un terminal de tu Raspberry Pi y ejecuta el siguiente comando para instalar la biblioteca adafruit-circuitpython-dht:


pip3 install adafruit-circuitpython-dht


Esta biblioteca proporciona una manera sencilla para leer datos de los sensores DHT11 y DHT22.

Ahora tenemos que conectar el sensor DHT a a la Raspberry Pi. Para esto identificaremos los pines de cada sensor y los conectamos siguiendo las serigrafias que vienen en el sensor:

  • Data: al GPIO21 (pin40)
  • VCC: al cualquier pin 5V
  • GND: al cualquier pin GND

Ahora en la terminal creamos un nuevo archivo Python llamado "dht11_test.py y escribimos el siguiente código que nos mostrará en pantalla los datos de temperatura y humedad del DHT11:



# Código para lectura del sensor DHT11
import time

import board

import adafruit_dht

#Inicia el dispositivo DHT con el pin de datos conectado a:
dhtDevice = adafruit_dht.DHT11(board.D21)

# Si no deseas usar pulseio puedes usar DHT11 use_pulseio=False
# Esto puede ser necesario en ordenadores de tipo Raspberry Pi con Linux
# Pero no funcionará en CircuitPython
# dhtDevice = adafruit_dht.DHT11(board.D18, use_pulseio=False)

while True:
    try:
        # Imprime los valores en el puerto serie
        temperature_c = dhtDevice.temperature
        temperature_f = temperature_c * (9 / 5) + 32
        humidity = dhtDevice.humidity
        print(f"Temp: {temperature_f:.1f} F / {temperature_c:.1f} C    Humidity: {humidity}% ")

    except RuntimeError as error:
	# Los errores ocurren con bastante frecuencia, los DHT son difíciles de leer, 
    simplemente sigue adelante.

        print(error.args[0])
        time.sleep(2.0)
        continue
    except Exception as error:
        dhtDevice.exit()
        raise error

    time.sleep(2.0)

Guarda el archivo como dht11_test.py y ejecútalo desde la terminal:


python3 dht11_test.py
o
python3 -m dht11_test


Para el caso del DHT22 es exactamente igual menos la linea "sensor = adafruit_dht.DHT11" que tenemos que cambiar por "sensor = adafruit_dht.DHT22" y se ve así:


# Código para lectura del sensor DHT22
import time

import board

import adafruit_dht

#Inicia el dispositivo DHT con el pin de datos conectado a:
dhtDevice = adafruit_dht.DHT22(board.D21)

# Si no deseas usar pulseio puedes usar DHT22 use_pulseio=False
# Esto puede ser necesario en ordenadores de tipo Raspberry Pi con Linux
# Pero no funcionará en CircuitPython
# dhtDevice = adafruit_dht.DHT22(board.D21, use_pulseio=False)

while True:
    try:
        # Imprime los valores en el puerto serie
        temperature_c = dhtDevice.temperature
        temperature_f = temperature_c * (9 / 5) + 32
        humidity = dhtDevice.humidity
        print(f"Temp: {temperature_f:.1f} F / {temperature_c:.1f} C    Humidity: {humidity}% ")

    except RuntimeError as error:
	# Los errores ocurren con bastante frecuencia, los DHT son difíciles de leer,
    simplemente sigue adelante.

        print(error.args[0])
        time.sleep(2.0)
        continue
    except Exception as error:
        dhtDevice.exit()
        raise error

    time.sleep(2.0)

Guardamos el archivo como dht22_test.py y ejecutamos desde la terminal:


python3 dht22_test.py
o
python3 -m dht22_test

El código de este ejemplo llamado dht_simpletest.py lo podemos encontrar en el repositorios de Adafruit_CircuitPython_DHT


Solución de errores:

uno de los errores que más comunes es el uso de la librería "board". Muchas veces podemos recibir el siguiente mensaje:


    import board
ModuleNotFoundError: No module named 'board'

O también este:


    dhtDevice = adafruit_dht.DHT11(board.D21)
                                   ^^^^^^^^^
AttributeError: module 'board' has no attribute 'D21'

Nos hace referencia a la librería board que se instala normalmente con "pip install board". Pero al estar haciendo uso de Adafruit CircuitPython necesitamos la librería que esta asociadad a Adafruit llamada "Adafruit-Blinka"

Esta librería instalara "board" y otras librerías como "pyserial" o "pyusb".

En el caso de que haya un error nos puede aparecer este mensaje:


Unable to set line 18 to input


Si aparece este error, nos hace referencia al pin, que o bien no esta activo o no es el puerto correcto donde esta conectado el sensor DHT 11.

Aplicaciones del DHT11 y Raspberry Pi

La combinación de Raspberry Pi y DHT11 o DHT22 ofrece un sinfín de posibilidades para proyectos de IoT. Algunas de las aplicaciones más comunes incluyen:

  • Estaciones meteorológicas caseras: Crea una estación meteorológica personalizada para monitorear la temperatura y humedad en tu hogar o jardín.
  • Sistemas de control de invernaderos: Automatiza el riego y la ventilación de tu invernadero en función de las condiciones ambientales.
  • Monitoreo de condiciones ambientales: Utiliza el sensor para monitorear la temperatura y humedad en espacios cerrados, como oficinas o almacenes.
  • Proyectos de domótica: Puedes integrar el sensor en sistemas de domótica para crear ambientes más cómodos y eficientes.
  • Prototipos de IoT: Utilizalos como punto de partida para desarrollar prototipos de dispositivos IoT más complejos.

Conclusión:

El sensor DHT11 es una herramienta invaluable para cualquier persona interesada en proyectos de electrónica y programación. En combinación con la Raspberry Pi, ofrece una plataforma potente y flexible para crear una amplia variedad de aplicaciones.

Con este artículo, has adquirido los conocimientos básicos para comenzar a trabajar con el DHT11 y la Raspberry Pi. ¡Anímate a experimentar y crear tus propios proyectos!

Instalación librería Adafruit-Blinka

Librería adafruit-circuitpython-dht

Aquí tienes otros enlaces de este blog relacionados con Raspberry Pi:

Programa de ejemplo de este articulo en GitHub

Raspberry Pi 3 Oled i2C

Raspberry Pi PWM

Poner Ip fija en Raspberry Pi


Un saludo a todos!!

viernes, 27 de septiembre de 2024

ESP8266 Servidor socket ADXL 345

Si ya leíste la entrada anterior sobre el sensor ADXL345, hemos mostrado los datos que genera un sensor de 3 ejes en el monitor serial. A mucha gente, una serie de números en una pantalla no le dicen mucho, algo más "humano" puede ser representarlo en un gráfico.

¿Como dibujar con Python?

Aunque más que a Python nos referimos a una de las librerías más famosas para crear interfaces, Tkinter. Junto con esta librería viene uno de los widgets más versátil para el dibujo, Canvas.

Canvas te proporciona un espacio donde puedes dibujar y mostrar elementos gráficos de forma personalizada. Es como una hoja de papel en la que puedes dibujar líneas, formas, texto, imágenes e incluso vídeo si utilizas una librería externa como OpenCV (Open Source Computer Vision Library).

Dentro de Canvas encontraremos la función create_line, con la que representaremos las coordenadas X Y Z de forma visual de tal manera que van a tener sentido.


id = cv.create_line(obj, init_ancho, init_alto, ancho, alto, trazo)



El programa va estructurado en dos partes, por un lado tenemos el ESP8266 con el sensor ADXL345 en modo servidor y por otro lado tenemos un ordenador con Python y el programa ADXL345 Interface Axis. 

NodeMCU -> Python Tkinter

ESP8266 ModeMCU con ADXL345

Este sensor tiene su propia entrada en el blog "ESP8266 y ADXL345 acelerómetro de 3 ejes. Lectura Serial" y es recomendable leerlo para entender mejor el funcionamiento del sensor ADXL345.

Primero iniciamos el microcontrolador ESP8266 con el sketch "esp8266_adxl_socket_server.ino". La principal diferencia con el programa básico es la implementación de un servidor socket en modo servidor con la librería "ESP8266WiFi.h". Solo hay que cambiar los datos para el ssid y password.

 
#include "ESP8266WiFi.h"

const char* ssid = "YOUR_SSID";
const char* password =  "PASSWORD";

// Tipo de Socket y puerto
WiFiServer wifiServer(1314);

En la función setup() realizamos la conexión:

 
void setup() 
 
  Serial.begin(115200);
 
  delay(1000);
 
  WiFi.begin(ssid, password);
 
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Conectando..");
  }
 
  Serial.print("Connected to WiFi. IP:");
  Serial.println(WiFi.localIP());
 
  wifiServer.begin();
  

Por último se ejecuta todo en loop()


void loop() {
 
  WiFiClient client = wifiServer.available();
 
  if (client) {
    Serial.println("Client connected");
    while (client.connected()) {
 	  
      // Función donde se obtienen los datos del sensor.
      client.print(getADXL());
      delay(10);
    }
 
    client.stop();
    Serial.println("Client disconnected");
 
  }
}

Ahora que sabemos como se conecta a nuestra red wifi,tenemos que averiguar la IP del dispositivo. La opción más sencilla es abrir el monitor serial y esperar la confirmación de conexión con la red que hayamos definido en YOUR_SSID y PASSWORD. Otra opción es mirar que dirección IP nos asigno el router.

Si utilizas el IDE de Arduino tras la confirmación se mostrará la IP del dispositivo ESP8266.

Monitor serial

El resto de información confirma que el sensor ADXL345 esta funcionando correctamente. Ahora podemos desconectar el ESP8266 y conectarlo a una fuente externa como una powerbank. Una vez que lo conectes se volverá a cargar la IP que nos dio el monitor serial.

Cliente ADXL345 Interface Axis

Por la parte del cliente, este programa creado con Python y la librería gráfica Tkinter. Consta de dos archivos, main_adxl345.py y class_cliente_adxl345.py.

  • main_adxl345.py es el encargado de dibujar la interfaz y las funciones que manejan los datos del sensor.
  • class_cliente_adxl345.py se encarga de la conexión wi-fi con el microcontrolador con el servicio socket server.

La interfaz:

Esta es la ventana principal donde se mostraran los datos que recibimos desde el ESP8266. Lo ejecutamos usando el comando:


python3 -m main_adxl345

Es bastante sencilla, en la parte izquierda es donde esta el canvas para representar los ejes y la parte derecha están los apartados de conexión y el muestreo de los datos.


En el apartado "socket connection" es donde hay que introducir la IP que nos ha proporcionado Arudino IDE en el monitor serial y pulsar el botón "start conn".

Si todo esta correcto, la pantalla empezará a mostrar los datos y representar en la pantalla los ejes del sensor. Podemos hacer que se muestren o no las lineas de cada eje de una manera independiente con los check button situados bajo el frame de recepción de datos.

 

 

ADXL345 Interface Axis es un programa sencillo con el que podremos ver los ejes de un sensor ADXL 345 de una manera visual, un código sencillo y reutilizable. De hecho con unas pocas modificaciones lo he usado para mi próximo ejemplo con un sensor GPS 6MV2 y representar sus datos. 

Programa de ejemplo de este articulo en GitHub

 

Aquí tienes otros enlaces de este blog relacionados con Python:

Muestra el estado del sistema Raspberry Pi

Raspberry pi PWM

Espero que os guste el contenido, Saludos!!

martes, 17 de septiembre de 2024

Python Sockets, manipular datos recibidos por cliente

Ahora que ya tengo en marchar Terminal DCC, una de las cosas que más me ha llamado la atención es la plasticidad de la biblioteca "sockets".

¿Que son los sockets?

De una manera simple, son los puntos de conexión entre procesos de diferentes sistemas a través de una red.

Con sockets no solo podemos transmitir texto entre cliente y servidor, también números, tanto int como float, binarios como imágenes o vídeo en resumen podemos enviar cualquier información que pueda ser representada como una secuencia de bytes.

Los usos más comunes que se le da a los sockets son como:

  • Servidor web
  • Transferencia de archivos
  • Clientes de chat
  • Juegos en red

En este ejemplo recibiremos los datos desde un servidor en formato bytes y los pasaremos a una codificación "UTF-8" para poder manejarlo como un String desde la misma u otra clase diferente.


Conceptos básicos:

  • Socket: Es el punto de conexión entre dos procesos. Se caracteriza por una dirección (IP) y un puerto.
  • Dirección IP: Es una etiqueta numérica única que identifica un dispositivo en una red.
  • Puerto: Es un número que identifica un servicio específico en un dispositivo.
  • TCP/IP: Es el protocolo de comunicación más utilizado en Internet. TCP (Transmission Control Protocol) garantiza la entrega ordenada y fiable de datos, mientras que IP (Internet Protocol) se encarga del enrutamiento de paquetes de datos.

Consideraciones importantes:

  • Serialización: Para enviar objetos de Python, debes serializarlos en una secuencia de bytes. Pickle es un módulo estándar de Python que permite la serialización de objetos, pero ten en cuenta que los objetos serializados con pickle pueden no ser compatibles entre diferentes versiones de Python.
  • Protocolo: El protocolo de comunicación que utilices (TCP, UDP, etc.) influirá en la forma en que se envían y reciben los datos.
  • Codificación: Es crucial elegir la codificación correcta para los datos de texto. La codificación UTF-8 es muy común, pero existen otras opciones.

Empecemos con el servidor:

Tanto el servidor como el cliente son clases. Para llamar a la clase "serverSocket" tenemos que pasarle los parámetros "IP" y "puerto"


## Inicia el programa principal
if __name__ == '__main__':
	# Inicia el socket con los parametros IP y puerto
	# Si no especificamos una dirección IP y usamos un 
	# String vacío, socket usará la IP de la maquina.
	server = serverSocket("", 1314)

	# Inicia el servidor
	server.iniciar()
    

Al iniciar el servidor con "python3 class_server_test.py", aparecerá el siguiente mensaje


[START] Server starting at 192.168.0.25
[LISTENING] Waiting for connections... 

Con esto ya tenemos el servidor a la escucha esperando conexiones desde los clientes

Cliente conectando con el servidor:

Del otro lado tenemos al cliente al que llamaremos "clienteSocket" desde el archivo "class_cliente_test.py" y al que tenemos que pasar los parámetros que usará para establecer la conexión con el servidor y son la IP del servidor, el puerto que esta a la escucha en el servidor y el número de cliente en caso de que conectemos mas de un cliente.


## Inicia el programa cliente
if __name__ == '__main__':
	# Establece conexión con el servidor
	cliente = clienteSocket("192.168.0.25", 1314, 1)

	# Inicia la conexión con el servidor
	estado = cliente.iniciar()
	
	# Imprime en pantalla el estado del servidor
	print(estado)

	# Si el estado contiene la palabra "CONNECTED"
	if "CONNECTED" in estado:

		# Envía un mensaje al servidor comunicando que estamos conectados
		cliente.clientSendData("Cliente conectado...")
		
		# Inicia un bucle con la respuesta del resta del servidor
		while True:

			# imprime los datos desde el cliente
			print(cliente.get_client_data())

			cliente.clientSendData(cliente.get_client_data())
			
			# Espera 2 segundos para volver a leer los datos
			time.sleep(2)

Si todo esta correcto en la pantalla del cliente se imprime el mensaje:


	[CONNECTED] 192.168.0.25:1314
    
	[OK] datos recibidos
    

Ahora ya tenemos el sistema conectado. Pero nosotros los datos que necesitamos no se van a quedar en el la clase cliente, queremos mostrarlos en otra pantalla como una interfaz con Tkinter o pyTermTk.

Los datos los obtenemos desde la función "cliente.get_client_data()" Es necesario tenerlo en bucle "while" o un "hilo" para que este constantemente a la escucha de los nuevos datos:


## Iniciar el cliente desde otra clase:
cliente = clienteSocket("192.168.0.25", 1314, 1)
cliente.iniciar()

# Obtener datos del cliente desde otra clase:
datas = cliente.get_client_data()

Y de está manera tenemos los datos de una conexión socket disponible para conectar cualquier dispositivo a nuestra red.

Conexión Cliente - Servidor


Con algunas modificaciones, estos ejemplos pueden servir para conectar dispositivos tan dispares como:

  • Ordenadores: Sobremesa, portátil, servidor...
  • Raspberry Pi: En todas sus versiones
  • Microcontroladores: Dispositivos como ESP8266 o ESP32

Programa de ejemplo de este articulo en GitHub

Espero que este ejemplo sea de ayuda y mejore las conexiones entre vuestros dispositivos, tanto tradicionales como IoT.

Saludos!!

miércoles, 11 de septiembre de 2024

Terminal DCC - Controla trenes DCC con la terminal

Muy Buenas a todos!!! Hoy traigo un programa creado con el ya comentado creador de interfaces de terminal pyTermTk. He vuelto a juntar las dos cosas que más me gustan, la informática y los trenes (si, muy a lo Sheldon).

Ya hacía tiempo que le iba dando vueltas a un controlador desde el terminal que no fuera estar metiendo instrucciones a mano desde una terminal. Entonces hace unos meses descubrí pyTermTk y empece a trabajar con el.

Tengo que decir que el diseñador de interfaces ttkDesigner ayudó mucho en el proceso, algunas veces me ha dado algún quebradero de cabeza, pero más por inexperiencia con la librería

También se han incluido los archivos json de las interfaces generados por ttkDesigner en la carpeta del repositorio

Terminal DCC esta diseñado para leer una base de datos generada con Rocrail y conectarnos a una central DCC de tipo hazlo tu mismo (DIY).

Para seleccionar el archivo desde un file picker que se abrirá al pulsar sobre el botón de menú "open". Desde aquí seleccionaremos el archivo .xml donde estén almacenados los datos del plan Rocrail.

 

Cuenta con dos pantallas principales llamadas Controller y List. En la primera de ellas, Controller, podemos manejar las locomotoras. Por otra parte List nos mostrará un resumen de los elementos almacenados en el archivo plan.xml


A la ventana configuración accedemos desde el menú superior "File", en "Config". Una vez que se abre la pantalla, encuentran los parámetros IP, que será la IP de la central DCC y el puerto que por defecto es el "2560" para realizar la conexión con wi-fi y sockets.

También se pueden configurar las pantallas Controller y List para que aparezcan al iniciar Terminal DCC.

Con estos datos ya podremos realizar la conexión pulsando sobre "Connection On/Off". Si todos los datos son correctos recibiremos un mensaje de confirmación:


--> [CONNECTED] to DCC station 192.168.1.5:2560

Una vez conectados podemos interactuar con la central introduciendo comandos con el widget de texto en la parte inferior. 

Con el botón "DCC On/Off" encendemos o apagamos la central DCC. Con la cental encendida ya podemos  manejar locomotoras desde el Controller con sus funciones básicas de avance, retroceso, parada. Las funciones de las locomotoras aún no están implementadas.

 


Instalación: 

Para instalar Terminal DCC solo necesitamos tener acceso a un terminal linux.

Una vez estamos en el terminal creamos un entorno virtual donde instalaremos las librerías y accedemos a el:


python3 -m venv ~/venv/TerminalDCC

source ~/venv/TerminalDCC/bin/activate

Nos situamos en la carpeta donde vamos a descargar Terminal DCC y lo podemos descargar directamente desde GitHub con la "git":


git clone https://github.com/Peyutron/TerminalDCC

Instalamos las librerías del archivo "requirements.txt" con "pip":


pip install -r requirements.txt

Ya solo queda ejecutar el programa:


python3 -m TerminalDCC_main
o
python3 TerminalDCC_main.py

 Bien pues esto es todo, las funciones son básicas y seguramente haya otro programa que no sea Rocrail, pero por el momento me ha servido para practicar Python con sus librerías, listas, diccionarios y sockets entre otros. La intención es actualizar la entrada cuando vaya haciendo cambios en el programa.

 

Si te gusta la programación y el contenido que realizo puedes aportar comentando tanto aquí como en el canal de Youtube.

 



Terminal DCC en GitHub

Y aquí tienes algunos ejemplos sobre TermTk y ttkDesigner:

pyTermTk y ttkDesigner: Button y Lablel

pyTermTk y ttkDesigner: List, ListSelect y Lablel

pyTermTk y ttkDesigner: Slider y Label

Librería PyTermTk crea interfaces en terminal

Librería PyTermTk en GitHub

Sígueme para más artículos sobre TermTk y otros temas de programación, Saludos!!!

miércoles, 4 de septiembre de 2024

pyTermTk y ttkDesigner: Abrir y guardar archivo EditText con File Picker

Seguimos viendo ejemplos de como crear interfaces con ttkDesigner. Hemos visto botones y labels, listas o sliders. Los siguiente widgets que vamos a ver es el widget FilePicker y Text Edit.

¿Que es un File Picker?

Es una herramienta visual que nos permite seleccionar un archivo específico desde tu sistema de archivos. Es como una ventana emergente que te muestra la estructura de tus carpetas y archivos, y te permite navegar entre directorios hasta encontrar la carpeta o archivo que deseas. Con el se pueden abrir archivos, guardar los datos o la selección múltiple de archivo.

¿Que es un Text Edit?

El widwet Text Edit nos permite crear áreas de texto multilinea es una especie de caja donde el usuario puede escribir o pegar texto de varias líneas,

domingo, 1 de septiembre de 2024

Raspberry Pi 3 Oled 0.96 I2C Adafruit

 Hace un tiempo conecte la pantalla Oled I2C con la librería "lemur", tenéis toda la información en la entrada 'Raspberry Pi 2 con Oled 128x64 I2C'.

Ahora lo quiero aplicar a la Raspberry Pi 3 y añadirlo al ventilador pwm que ya instalamos anteriormente así que aprovecho para darle una actualización a la entrada anteriormente enlazada y añadir algunos pasos más.

La librería que usamos anteriormente está descontinuada ahora la información ahora la información esta en la propia web de Adafruit. Los cambios son mínimos ya que solo instalando la librería y cambiando las lineas de configuración todo vuelve a funcionar como antes. Veamos como instalar las librerías que relacionadas adafruit-circuitpython-ssd1306.


sudo apt-get install python3-pip	

pip3 install adafruit-circuitpython-ssd1306

sudo apt-get install python3-pil

sudo apt-get install python3-numpy

Para usar pantalla Oled 128x64 I2C hay que importar la librería de la siguiente manera:


import board
import adafruit_ssd1306
from PIL import Image, ImageDraw, ImageFont

# Use for I2C.
i2c = board.I2C()  # uses board.SCL and board.SDA

try:
	disp = adafruit_ssd1306.SSD1306_I2C(128, 64, i2c, addr=0x3C, reset=RST)
    print("\nAdafruit SSD1306 ok")
except Exception as errors:
	print("\nError Adafruit SSD1306:",str(errors), "\nPlease check Raspi-config\n")
	exit()

Una vez que tenemos la pantalla funcionando estos son los datos que vamos a mostrar:, 

  • IP de la red
  • Uso del CPU 
  • Temperatura del procesador
  • Uso de Ram
  • Velocidad del ventilador (PWM)
  • Tiempo que lleva encendido el sistema
  • Sistema operativo
Para conseguir todos estos datos que queremos mostrar en la pantalla usaremos las librerías externas:
  • psutil
  • subprocess
  • sys
Empecemos por la IP

La ip la podemos obtener con subprocess:



    ## Obtiene la ip del equipo
    # @ return String "0.0.0.0"
    def GetIP():
        return str(subprocess.check_output(['hostname', '-I'])).split(' ')[0].replace("b'", "")


Obtenemos la carga de CPU con psutil:


    ## Obtiene la carga de la CPU
    # @ return float
    def GetCPU():
        return psutil.cpu_percent(1)


La temperatura de la CPU con subprocess:


    ## Obtiene la temperatura de la CPU
    # @ return float
    def GetTemp():
        output = subprocess.run(['vcgencmd', 'measure_temp'], capture_output= True)
        temp_str = output.stdout.decode()
        try:
            return float(temp_str.split('=')[1].split('\'')[0])
        except (IndexError, ValueError):
            raise RuntimeError('no se puede obtener temperatura')


La RAM en uso mediante psutil:


    ## Obtiene la cantidad de RAM en uso
    # @ return float
    def GetRAM():
        return psutil.virtual_memory()[2]


El PWM que aplicamos al pin viene nos lo devuelve la clase healt_pwm_class.py:


    ## Obtiene la velocidad del ventilador
    # @ hpc: healt_pwm_class.System_PWM_Fan
    # @ type_ int: 0=Proporcional, 1=Por pasos de temperatura
    # @ return int: valor de pwm aplicado en el pin
    def GetFanPWM(sef, hpc, type_):
    	if type_ == 0:
        	return hpc.Proportional()
	else:
        	return hpc.Stepped()



El sistema operativo lo obtenemos gracias a sys:


    ## Función que devuelve el SO en uso
    # @ return String
    def getOS():
        platforms = {
        'linux1' : 'linux',
        'linux2' : 'linux',
        'darwin' : 'mac',
        'win32' : 'win32'
        }
        if sys.platform not in platforms:
            return sys.platform
        
        return platforms[sys.platform]    



Y por último el tiempo que lleva encendida la maquina con psutil:


    ## Obtiene el tiempo que lleva la maquina encendida
    # @ return String "0d 00h 00m 00s"
    def GetUpTime():
        boot_time_timestamp = psutil.boot_time()
        current_time_timestamp = time.time()
        uptime_seconds = current_time_timestamp - boot_time_timestamp
        uptime_minutes = uptime_seconds // 60
        uptime_hours = uptime_minutes // 60
        uptime_days = uptime_hours // 24
        uptime_str = f"{int(uptime_days)}d {int(uptime_hours % 24)}h {int(uptime_minutes % 60)}m {int(uptime_seconds % 60)}s"
        # print("Uptime: " + uptime_str)
        return uptime_str

Como todas las funciones están en una clase llamada "system_functions_class.py". También podemos llamar a estas funciones de manera individual directamente desde la clase de la siguiente manera:


    # Importamos la clase
    from system_functions_class import *
    
    sfc = System_Functions()
	# Retorna la IP del equipo
    ip = sfc.GetIP()
    
    # Retorna la temperatura de la CPU
    cpu_temp =.sfc.GetTemp()
    
    # Imprime los resultados de ip y cpu_temp
    print("IP: {}, CPU temp: {}".format(ip, cpu_temp))
    

 

¿Como usamos el programa?

Clonamos el repositorio rpi3_healt_system desde GitHub. Vamos a nuestra carpeta de proyectos y escribimos:


https://github.com/Peyutron/python-Warehouse/tree/main/Raspberry_Python/rpi3_healt_system

Con el programa en nuestro equipo, el ejecutable principal se llama "main_rpi_healt.py y lo ejecutamos con


python3 -m main_rpi_healt

Si todo ha ido bien con la instalación en el terminal recibiremos el siguiente mensaje:


Adafruit ssd1306 ok

y en la pantalla se dibujara lo siguiente:

Los datos que se muestran se guardan en un archivo JSON. Esto nos servirá en un futuro para enviar los datos a otros equipos o como consulta de la última vez que se ejecuto el programa. La información se guarda en un archivo llamado healt_datas.json y este es su contenido:


{
    "filename": "healt_datas.json",
    "ip": "192.168.1.39",
    "m0_cpuf": 39,
    "m0_cpul": 0.0,
    "m0_cput": 45.6,
    "m0_os": "linux",
    "m0_raml": 18.5,
    "m0_ut": "0d 4h 48m 55s"
}


Aquí tienes otros enlaces de este blog relacionados con Raspberry Pi:

Programa de ejemplo de este articulo en GitHub

Raspberry pi PWM

Poner Ip fija en Raspberry Pi

Información desde la web oficial de Adafruit


Un saludo a todos!!

lunes, 26 de agosto de 2024

pyTermTk y ttkDesigner: Slider y Label

Hemos visto algunos ejemplos con TermTk y TTkDesigner, hoy traemos otro más, el Slider o control deslizante. Como ya hemos visto antes con Button y Label o con el widged List, el widget Slider tiene una uso muy similar.

Antes de aplicar el código vamos a crear una pantalla donde pondremos los siguientes elementos:

  • Un widget tipo Slider al que llamaremos "sl1"
  • Un widget tipo Label al que llamaremos "lb1"
  • TermTk Slider
    ttkDesigner Slider

lunes, 5 de agosto de 2024

pyTermTk y ttkDesigner: Mostrar listas

Anteriormente ya hemos visto como crear boton y un label con pyTermTk y TTkDesigner. El siguiente widget que he probado es el widget list. Con las listas podemos mostrar la información de una manera estructurada, generalmente en vertical, y nos facilita su lectura. También nos permite seleccionar elementos de esta lista y de esta manera podemos interactuar con los datos que muestra.

Como ya hemos hablado anteriormente sobre como crear una interfaz, vamos crear una con los siguientes elementos:

  • Un widget tipo List al que llamaremos "ls1"
  • Un widget tipo Label al que llamaremos "lb1"
  • Listas con pyTermTk

jueves, 1 de agosto de 2024

pyTermTk y ttkDesigner: Button y Lablel

No lo vamos a negar, pyTermTk me ha encantado. Siempre hemos tenido ganas de poder hacer el terminal un poquito más amigable, pero no siempre es una tarea sencilla.

Ya hemos visto como instalar pyTermTk y ttkDesigner. Ahora veremos como funciona, accedemos al programa desde la terminal con el comando:


$ttkDesigner

A partir de aquí, tenemos la pantalla dividida en secciones:

  • Lista de elementos:

    Tenemos muchos de donde escoger, Layouts, Containers, Buttons, etc... Solo tenemos que mantener pulsado el elemento y arrastrar hacia el marco principal

  • Árbol de inspección:

    Todos los elementos que adjuntemos al proyectos ordenados por jerarquía

  • Propiedades del widget:

    Son las características de cada elemento, tales como alto, ancho, posición, etc...

  • Editor de Signal y slots:

    Se emite una señal cuando se produce un evento en particular.
    Un slot es una función que se llama en respuesta a una señal particular.
    TermTk TTkWidgets tiene muchas signals y slots predefinidos, pero es posible crear una subclase a cualquier TTkWidgets y añadir nuestras propias signals/slots. En este ejemplo solo usaremos los slots.



  • Logs:

    Registro de lo que pasa en el programa en tiempo de ejecución

miércoles, 10 de julio de 2024

Librería PyTermTk crea interfaces en terminal


Buenas a todos! Hoy he descubierto una librería para Python que me ha dejado una espinita. Se llama PyTermTK y es una biblioteca que ofrece una gran variedad de características para crear TUIs (Terminar User Interfaces).
Tiene un gran parecido a TKinter a la hora de diseñar una interfaz y vamos a ver como se instala y ver algunos de sus ejemplos.
PyTermTK también tiene la opción para un diseñador de interfaces llamado ttkDesigner y veremos también como instalarlo y como usarlo.

Instalación de la librería con pip3:


# Instalación

pip3 install pytermtk

Que nos ofrece PyTermTk:

lunes, 1 de julio de 2024

Raspberry Pi 3 ventilador PWM

Como estamos a Julio y se vienen 'las calores', es hora de refrigerar la Raspberry pi 3. Esta es una Raspberry que adquirí de segunda mano y viene sin ningún tipo de refrigeración y eso no es muy recomendable. Como le voy a dar varios usos (maquina arcade, probar SO etc) puede ser que tenerla sin un disipador no sea lo mejor. 

Ya he encargado unos cuantos disipadores en una web chinesca, pero espero que sea valida para estos pequeños accesorios.

También se me ocurrió ponerle un pequeño ventilador conectado a uno de los puertos GPIO de las Raspberry pi. Como los ventiladores son de 5V DC pero no tienen linea PWM, tenemos que crear un pequeño driver con un transistor que controle el PWM.

Primero tenemos que saber cuales son las temperaturas aproximadas que alcanza el procesador. Investigando un poco he encontrado esta tabla, más o menos representativa:


Temperaturas: Sin disipador Con disipador Disipador activo
Sin carga: ~40ºC ~30ºC 25ºC - 30ºC
Carga media: 50ºC - 60ºC 40ºC - 50ºC 30ºC - 40ºC
Carga intensiva: 60ºC - 80ºC 50ºC - 70ºC 40ºC - 60ºC

Tomando esta tabla como referencia crearemos unos perfiles y por último un perfil personalizado.

También se puede añadir un DHT11 para tener una referencia de la temperatura ambiente, pero eso para otro momento, Por el momento nos vamos a centrar en el PWM 

Programaremos en Python y usaremos las librerías RPi.GPIO para el control de los pines GPIO. La librería time para hacer una pausa antes de mostrar los datos y subprocess para capturar la salida de 'vcgencmd' donde nos mostrará el dato de measure_temp.  

Con estos datos y con el perfil que tengamos seleccionado aplicara una velocidad u otra al ventilador.

El programa completo se puede descargar desde Github

En este punto ya tenemos la parte de programación. Ahora le toca el turno a la electrónica.

Como queremos mover un ventilador, aunque pequeño, su carga es mucho más que los 15mA que puede entregar el pin de la Raspberry Pi. Para solucionar esto usaremos un transistor NPN como el BC548 una resistencia de 10Kohm y un diodo 1N4007

Usaremos el siguiente diagrama:


Una vez tenemos todo conectado tenemos que habilitar los pines de la Raspberry Pi. Tenemos un diagrama de los pines si en el terminal usamos el comando 'pinout'


Este comando también nos dará información como el modelo, SoC, RAM, puertos USB y algunos parámetros más. Si necesitas más información sobre la placa podemos usar el comando 'raspinfo'

Ahora solo falta que este programa se ejecute al iniciar la maquina. Esto es muy sencillo solo tenemos que añadir una linea en el 'crontab' ejecutando 'sudo crontab -e' que será la encargada de cargar el programa en el inicio del sistema. Añadiremos la siguiente linea:


  @reboot sleep 15; /usr/bin/python3 /home/ruta_del_archivo/pwm_fan_rpi3.py > /dev/null
  

Lo podemos desglosar de la siguiente manera:
  • @reboot sleep 15; -> Iniciara el script cuando se reinicie la maquina y hayan pasado 15 segundos
  • /usr/bin/python3 -> Ruta donde se encuentra Python3
  • home/.../pwm_fan_rpi3.py -> ruta donde se encuentra el script de Python
  • > /dev/null -> mandamos la salida del programa a null
Tengo que añadir que al intentar ejecutar el programa en el sistema RetroPie que tengo instalado este comando no me ha funcionado correctamente, he tenido que poner este:
  
@reboot sleep 15 && python3 /home/pi/Ruta_del_archivo/pwm_fan_rpi3.py > /home/Ruta_para_log/cron.log 2>&1

Por otro lado al cargar el programa me daba muchos errores de las librerías y la única solución que he encontrado es instalar las librerías con sudo. Haciendo esto todo ha funcionado perfectamente iniciando el ventilador al arrancar el sistema.

Y bueno hasta aquí la parte de programación y teoría. Montaremos los componentes y probaremos que tal va el programa.

Advertencia: 

A partir de 80°C, la Raspberry Pi 3 comenzará a reducir su velocidad de reloj (thermal throttling) para protegerse del sobrecalentamiento. Esto puede afectar el rendimiento de la placa.

Superar los 85°C durante un período prolongado puede dañar la Raspberry Pi 3.


Fuente:

viernes, 26 de enero de 2024

Actualizar Python en Ubuntu con apt

Revisando la versión de Python y aprovechando una reinstalación del sistema que he realizado hace poco, tenía que revisar unos programas y antes de empezar he revisado la versión que tengo actualmente instalada y era la 3.1 lo que me pareció un poco baja ya que la ultima vez, y la que tengo en el otro equipo, es la 3.8

Para actualizar Python primero vemos la versión que tenemos actualmente instalada con el comando:


python3 --version

Python 3.10.12


Una vez tenemos esta información actualizamos el sistema con el siguiente comando:

domingo, 5 de noviembre de 2023

Raspberry pi 2 con Oled 128x64 I2C

 Raspberry Pi ese pequeño ordenador de "bajo coste" que poca presentación necesita. Todos sabemos de su versatilidad y potencia. Raspberry Pi se usa en muchisimos proyectos de robotica, mini PCs, servidores y un largo etcétera. Por su puesto gracias a su puerto GPIO donde podremos conectar otra gran cantidad de sensores y accesorios.

En mi caso tengo un Raspberry Pi 2 Model B. A día de escribir esta entrada ya tiene unos añitos pero sigue dando guerra. La tengo para hacer mis cosillas de programación, también alguna vez como emulador de juegos retro o como es este caso, para cacharrear.

En este caso he añadido una pequeña pantalla Oled de 128x64 y comunicación I2C. Es la que uso generalmente con Arduino y en tiendas de internet lo podemos encontrar por unos 2 o 3 euros.
Si bien es una pantalla pequeña es lo suficiente para poder mostrar cierta información en ella así como imágenes o animaciones.

martes, 7 de febrero de 2023

Python Raspberry: contador de segundos

 Hace poco que estoy tocando algo de Python para y tenía la duda de cuanto tiempo estaba encendida conectada a una batería o powerbank. La Raspberry en cuestión es un modelo 2B con algunos añitos a sus espaldas pero que arranca como una campeona!

En cuanto a la batería, no se exactamente cual es su capacidad, debe rondar los 10.000mA con 5 baterías 18650 recicladas de portátil, (unos 2000mA por unidad) Así que me puesto a investigar y este sería el código para que cuente un segundo y lo guarde en un archivo de texto.

Para que no me sobreescibiera el archivo cada vez que arranque la Raspberry, el nombre del archivo empieza con la hora y luego el nombre del archivo.


from datetime import datetime
import time
d = datetime.now().strftime("%H%M%S")
namefile = d + "_readme.txt"
print(namefile)

try:

	with open(namefile, 'w') as f.write('Archivo nuevo creado!')
except FileNotFoundError:
	print("no se crea el archivo :(")

inicio = time.time()

time.time.process_time()

contador = 0

while True:
	contador = time.time() - inicio
    #print ("segundo: %02d" % ( contador) )
    time.sleep(1)
    with open(namefile, 'a) as f: 
    f.write("\nsegundo: %02d" % ( contador) )
    

Archivo nuevo creado!
segundo: 00
segundo: 01
segundo: 02

El resultado han sido 61445 segundos, unas 17 horas. Eso si con apenas carga de trabajo ya que ahora mismo no esta haciendo nada en particular, solo unas pruebas que estoy realizando.

Si bien no es la mejor forma, por el momento para mi propósito que es tener una estimación del tiempo que pueden alimentar las báterias una Raspberry pi está bien.

Evidentemente estos datos cambiaran dependiendo del modelo de Raspberry y el pack de báterias.

Saludos!!!