Radiotransmisor: un programa para intercomunicar placas vía LoRa


Presentación

Ya escrita y probada la librería Transceptor1262 (https://carlosvaccaro.com.ar/lora/lora001.php) llego el momento de usarla y que mejor para ello que implementar un programa que permita la comunicacion entre diversos nodos (placas esp32 con LoRa).

El programa se instala en al menos dos placas que deben estar cada una conectada via usb a una computadora, al iniciarse el programa en la placa esta pedira a traves de la consola que se ingrese una identificacion de ususario, de modo similar a los sistemas de chat por IRC y luego quedara en escucha

Cuando cualquiera de las placas conectadas envie un mensaje, este será recibido por todas las demas, tambien estan agergados un par de mensajes automaticos que avisa a todas las placas conectadas cuando se conecta una nueva o uando alguna se desconecta

Instalación previa

Para el uso de este programa es necesario tener flasheada la placa con el firmware de Micropython (yo uso el genérico para ESP32-S3) luego deben subirse los archivos de la Librería Transceptor1262 y los archivos transceptor.json y transceptor.py que crean objeto transceptor y lo inicializan para su uso.

Link de descarga de los archivos mencionados

📥 Descargar transceptor1262.py
📥 Descargar transceptor1262_const.py
📥 Descargar transceptor.py
📥 Descargar transceptor.json

Finalmente se debe subir a la placa el archivo radiotrasnmisor.py que contiene el programa de comunicacion entre placas

El programa radiotransmisor.py

radiotransmisor.py es una aplicación de comunicación LoRa de dos vías que combina las funciones de transmisión y recepción en un solo programa. Está diseñado para operar en modo receptor por defecto, permitiendo al usuario enviar mensajes temporalmente al presionar Ctrl+C.

Inicialización:
– Al iniciar, el programa solicita al usuario que ingrese su identificación o nombre de usuario (mi_id).
– Luego, envía un mensaje de conexión a través del módulo LoRa con el formato “{mi_id}: Estoy conectado en escucha”, para notificar a otros nodos que está activo.
– Muestra instrucciones breves sobre cómo usar el programa, como presionar Ctrl+C para enviar un mensaje o hacerlo dos veces para salir.

Modo Receptor (modo_receptor):
– El programa entra en un bucle continuo (while True) donde intenta recibir mensajes del módulo LoRa con un tiempo de espera de 15 segundos.
– Si recibe un mensaje, lo decodifica y lo analiza para ver si sigue el formato “ID: mensaje”. Si es así, lo imprime como “{emisor_id}: {mensaje_real}”. Si no, imprime el mensaje completo con un prefijo [RX].
– Si el usuario presiona Ctrl+C, se interrumpe el bucle de recepción y se cambia al modo emisor (modo_emisor).

Modo Emisor (modo_emisor):
– Se solicita al usuario que escriba un mensaje en la consola.
– Si el usuario presiona Ctrl+C mientras está en este modo, se envía un mensaje de desconexión (“{mi_id}: Me desconecto, hasta luego.”) y el programa se cierra.
– Si se ingresa un mensaje y se presiona Enter, se formatea como “{mi_id}: {mensaje_usuario}” y se envía por el módulo LoRa.
– Si ocurre un error durante el envío, se imprime un mensaje con el estado del error.
– Tras enviar el mensaje (o si se presiona Enter sin escribir nada), el programa vuelve al modo receptor.

Características técnicas:
Uso del módulo transceptor: Se apoya en una clase o módulo externo (transceptor) para manejar las funciones de bajo nivel de envío y recepción LoRa.
Manejo de interrupciones: El programa está diseñado para responder a Ctrl+C para cambiar entre modos o salir, lo cual es útil para mantener el control sin interrupciones accidentales.
Formato de mensajes: Los mensajes enviados y recibidos siguen un formato estandarizado que incluye el ID del emisor, facilitando la identificación de quién envió cada mensaje.
Gestión de errores: Incluye manejo de excepciones para evitar interrupciones inesperadas y mostrar mensajes informativos en caso de errores.

Código

Archivo: radiotransmisor.py

# radiotransmisor.py
from transceptor import transceptor
import sys
from transceptor1262_const import ERROR

# ID del usuario
mi_id = ""

def modo_receptor():
    # Funcion de receptor.
    while True:
        try:
            # Escucha.
            msg, err = transceptor.recibir(timeout_ms=15000)
            if msg:
                # Decodificar el mensaje recibido
                mensaje_bruto = msg.decode('utf-8', 'ignore')
                
                # Parsea el mensaje para obtener el ID del emisor
                partes = mensaje_bruto.split(': ', 1)
                if len(partes) == 2:
                    emisor_id, mensaje_real = partes
                    print(f"{emisor_id}: {mensaje_real}")
                else:
                    # Si no tiene el formato 'ID: mensaje', lo muestra completo
                    print(f"[RX] ✅ Recibido: {msg}")
        except KeyboardInterrupt:
            # Interrumpir la recepción para cambiar al modo emisor
            break
        except Exception as e:
            print(f"[EXCEPCIÓN en modo_receptor] {e}")

    # Interrumpir el bucle si se presiona Ctrl+C y cambiar al modo emisor
    modo_emisor()

def modo_emisor():
    #Funcion de emisor.
    try:
        mensaje_usuario = input(f"{mi_id}: ")
    except KeyboardInterrupt:
        # Salir del programa si se presiona Ctrl+C en modo emisor
        # Enviar mensaje de desconexión antes de salir
        mensaje_desconexion = f"{mi_id}: Me desconecto, hasta luego.".encode('utf-8')
        try:
            transceptor.enviar(mensaje_desconexion)
        except Exception as e:
            print(f"[ERROR] No se pudo enviar mensaje de desconexión: {e}")
        
        print("\n[INTERRUPCIÓN] Saliendo del programa. ¡Hasta luego!")
        sys.exit(0)

    # Si se ingresó un mensaje, formatearlo e enviarlo
    if mensaje_usuario:
        mensaje_para_enviar = f"{mi_id}: {mensaje_usuario}".encode('utf-8')
        try:
            bytes_enviados, estado = transceptor.enviar(mensaje_para_enviar)
            if estado != 0:
                print(f"[TX] Error al enviar: {ERROR.get(estado, 'Desconocido')}")
        except Exception as e:
            print(f"[ERROR] Excepción al enviar: {e}")
    
    # Volver al modo recepción después de enviar o si no se escribió nada
    modo_receptor()

if __name__ == "__main__":
    print("Inicializando sistema LoRa...")
    print("Presiona Ctrl+C para enviar un mensaje.")
    print("Presiona dos veces Ctrl+C para cerrar el programa.")
    
    # Solicitar identificación del usuario
    mi_id = input("Ingresa tu identificación (nombre de usuario): ")
    
    # Enviar mensaje de conexión
    mensaje_conexion = f"{mi_id}: Estoy conectado en escucha".encode('utf-8')
    try:
        transceptor.enviar(mensaje_conexion)
    except Exception as e:
        print(f"[ERROR] No se pudo enviar mensaje de conexión: {e}")
    
    # Iniciar la aplicación en modo recepción
    print("[INFO] Modo Recepción Activado")
    modo_receptor()
    
    
📥 Descargar radiotransmisor.py

Cerrar