The project involves developing an RS232 controller for the UHD-401MV 4x1 Multiviewer Video Switcher, enabling it to be operated via Home Assistant using MQTT communication.
Products
Pico-2CH-RS232 Setup
For hardware setup, please refer to the Pico-2CH-RS232 Wiki. Connect one of the RS232 output channels to the adapter designed for the UHD-401MV.
UART Code
The provided code enables the sending of ASCII commands from the PICO to the UHD-401MV, utilizing the command codes as specified in the manual.
import time import board import busio # Function to send RS232 commands def send_rs232_command(command): uart.write(bytes(command+'\r\n', 'ascii')) print(command) time.sleep(0.1) # Wait for a short moment for the command to be processed uart = busio.UART(tx=board.GP4, rx=board.GP5, baudrate=115200,)
Settings.toml
CircuitPython works with WiFi-capable boards to enable you to make projects that have network connectivity. This means working with various passwords and API keys. As of CircuitPython 8, there is support for a settings.toml file. This is a file that is stored on your CIRCUITPY drive, that contains all of your secret network information, such as your SSID, SSID password and any API keys for IoT services. It is designed to separate your sensitive information from your code.py file so you are able to share your code without sharing your credentials.
CircuitPython previously used a secrets.py file for this purpose. The settings.toml file is quite similar.
CIRCUITPY_WIFI_SSID = "your_wifi_ssid" CIRCUITPY_WIFI_PASSWORD = "your_wifi_password" MQTT_BROKER = "your_MQTT_broker_url" MQTT_USERNAME = "your_MQTT_username" MQTT_PASSSWORD = "your_MQTT_password"
MQTT & WiFi Code
The provided code enables monitoring of an MQTT topic for incoming messages. The final version of this code will specifically listen for messages published through Home Assistant.
import os import ipaddress import wifi import socketpool import adafruit_minimqtt.adafruit_minimqtt as MQTT print() print("Connecting to WiFi") # connect to your SSID wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) print("Connected to WiFi") pool = socketpool.SocketPool(wifi.radio) # prints MAC address to REPL print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address]) # prints IP address to REPL print("My IP address is", wifi.radio.ipv4_address) # pings Google ipv4 = ipaddress.ip_address("8.8.4.4") print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000)) # Define callback methods which are called when events occur def connect(mqtt_client, userdata, flags, rc): # This function will be called when the mqtt_client is connected # successfully to the broker. print("Connected to MQTT Broker!") print("Flags: {0}\n RC: {1}".format(flags, rc)) def disconnect(mqtt_client, userdata, rc): # This method is called when the mqtt_client disconnects # from the broker. print("Disconnected from MQTT Broker!") def subscribe(mqtt_client, userdata, topic, granted_qos): # This method is called when the mqtt_client subscribes to a new feed. print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos)) def unsubscribe(mqtt_client, userdata, topic, pid): # This method is called when the mqtt_client unsubscribes from a feed. print("Unsubscribed from {0} with PID {1}".format(topic, pid)) def publish(mqtt_client, userdata, topic, pid): # This method is called when the mqtt_client publishes data to a feed. print("Published to {0} with PID {1}".format(topic, pid)) def message(client, topic, message): print("New message on topic {0}: {1}".format(topic, message)) MQTT.set_socket(pool) # Set up a MiniMQTT Client (make sure your settings.toml file is correct) mqtt_client = MQTT.MQTT( broker=os.getenv('MQTT_BROKER'), username=os.getenv('MQTT_USERNAME'), password=os.getenv('MQTT_PASSWORD'), ) # Connect callback handlers to mqtt_client mqtt_client.on_connect = connect mqtt_client.on_disconnect = disconnect mqtt_client.on_subscribe = subscribe mqtt_client.on_unsubscribe = unsubscribe mqtt_client.on_publish = publish mqtt_client.on_message = message mqtt_topic = 'hdmimatrix' print("Attemping to connect to %s" % mqtt_client.broker) mqtt_client.connect() print("Subscribing to %s" % mqtt_topic) mqtt_client.subscribe(mqtt_topic) while True: mqtt_client.loop()
import microcontroller import time import board import busio import os import ipaddress import wifi import socketpool import adafruit_minimqtt.adafruit_minimqtt as MQTT sound = 2 pip_size = 1 quad_mode=1 screen_one = 2 screen_two = (screen_one % 4) + 1 screen_three = (screen_two % 4) + 1 screen_four = (screen_three % 4) + 1 video_mode = 1 pip_position = 1 print() print("Connecting to WiFi") # connect to your SSID wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD')) print("Connected to WiFi") pool = socketpool.SocketPool(wifi.radio) # prints MAC address to REPL print("My MAC addr:", [hex(i) for i in wifi.radio.mac_address]) # prints IP address to REPL print("My IP address is", wifi.radio.ipv4_address) # pings Google ipv4 = ipaddress.ip_address("8.8.4.4") print("Ping google.com: %f ms" % (wifi.radio.ping(ipv4)*1000)) # Functio n to send RS232 commands def send_rs232_command(command): uart.write(bytes(command+'\r\n', 'ascii')) print(command) time.sleep(0.1) # Wait for a short moment for the command to be processed uart = busio.UART(tx=board.GP4, rx=board.GP5, baudrate=115200,) send_rs232_command(f's PIP size {pip_size}!') send_rs232_command(f's PIP position {pip_position}!') send_rs232_command(f's quad mode {quad_mode}!') send_rs232_command(f's multiview {video_mode}!') send_rs232_command(f's in source {screen_one}!') send_rs232_command(f's output audio {sound}!') send_rs232_command(f's window 1 in {screen_one}!') send_rs232_command(f's window 2 in {screen_two}!') send_rs232_command(f's window 3 in {screen_three}!') send_rs232_command(f's window 4 in {screen_four}!') # Define callback methods which are called when events occur def connect(mqtt_client, userdata, flags, rc): # This function will be called when the mqtt_client is connected # successfully to the broker. print("Connected to MQTT Broker!") print("Flags: {0}\n RC: {1}".format(flags, rc)) def disconnect(mqtt_client, userdata, rc): # This method is called when the mqtt_client disconnects # from the broker. print("Disconnected from MQTT Broker!") microcontroller.reset() def subscribe(mqtt_client, userdata, topic, granted_qos): # This method is called when the mqtt_client subscribes to a new feed. print("Subscribed to {0} with QOS level {1}".format(topic, granted_qos)) def message(client, topic, message): global sound global screen_one global video_mode global pip_size global pip_position global quad_mode if message == 'ChangeSound': sound = (sound % 4) + 1 send_rs232_command(f's output audio {sound}!') if message == 'Single': if video_mode != 1: send_rs232_command('s multiview 1!') else: sound = (sound % 4) + 1 video_mode = 1 screen_one = sound screen_two = (screen_one % 4) + 1 screen_three = (screen_two % 4) + 1 screen_four = (screen_three % 4) + 1 send_rs232_command(f's in source {screen_one}!') send_rs232_command(f's output audio {sound}!') send_rs232_command(f's window 1 in {screen_one}!') send_rs232_command(f's window 2 in {screen_two}!') send_rs232_command(f's window 3 in {screen_three}!') send_rs232_command(f's window 4 in {screen_four}!') if message == 'PIP': if video_mode != 2: screen_one = sound screen_two = (screen_one % 4) + 1 screen_three = (screen_two % 4) + 1 screen_four = (screen_three % 4) + 1 send_rs232_command('s multiview 2!') send_rs232_command(f's window 1 in {screen_one}!') send_rs232_command(f's window 2 in {screen_two}!') send_rs232_command(f's window 3 in {screen_three}!') send_rs232_command(f's window 4 in {screen_four}!') video_mode = 2 pip_size = (pip_size % 3) + 1 send_rs232_command(f's PIP size {pip_size}!') if message == 'PIPPosition': send_rs232_command('s multiview 2!') pip_position = (pip_position % 4) + 1 send_rs232_command(f's PIP position {pip_position}!') if message == 'Quad': if video_mode != 5: send_rs232_command('s multiview 5!') screen_two = (screen_one % 4) + 1 screen_three = (screen_two % 4) + 1 screen_four = (screen_three % 4) + 1 send_rs232_command(f's window 1 in {screen_one}!') send_rs232_command(f's window 2 in {screen_two}!') send_rs232_command(f's window 3 in {screen_three}!') send_rs232_command(f's window 4 in {screen_four}!') video_mode = 5 quad_mode = (quad_mode % 2) + 1 send_rs232_command(f's quad mode {quad_mode}!') if message == 'RotateScreens': screen_one = (screen_one % 4) + 1 screen_two = (screen_one % 4) + 1 screen_three = (screen_two % 4) + 1 screen_four = (screen_three % 4) + 1 if video_mode == 1 or video_mode == 2: sound = screen_one send_rs232_command(f's output audio {sound}!') send_rs232_command(f's in source {screen_one}!') send_rs232_command(f's window 1 in {screen_one}!') send_rs232_command(f's window 2 in {screen_two}!') send_rs232_command(f's window 3 in {screen_three}!') send_rs232_command(f's window 4 in {screen_four}!') print("New message on topic {0}: {1}".format(topic, message)) MQTT.set_socket(pool) # Set up a MiniMQTT Client (make sure your settings.toml file is correct) mqtt_client = MQTT.MQTT( broker=os.getenv('MQTT_BROKER'), username=os.getenv('MQTT_USERNAME'), password=os.getenv('MQTT_PASSWORD'), ) # Connect callback handlers to mqtt_client mqtt_client.on_connect = connect mqtt_client.on_disconnect = disconnect mqtt_client.on_subscribe = subscribe mqtt_client.on_message = message mqtt_topic = 'hdmimatrix' print("Attemping to connect to %s" % mqtt_client.broker) mqtt_client.connect() print("Subscribing to %s" % mqtt_topic) mqtt_client.subscribe(mqtt_topic) while True: mqtt_client.loop()