Send OSC from Arduino to Computer

  • en
  • de
  • Send OSC from Arduino to Computer

    written by David Huss


    OSC (Open Sound Control) is a protocol with which data can be sent between applications. For example sending data from a python script to VCV-Rack, audio DAWs, or even to certain hardware synthesizers. OSC acts as a glue, so to be speak.

    In this case we want to go this route [Arduino] -> [USB-Serial] -> [Laptop/Python Script] -> [OSC] -> [Laptop/VCV-Rack].

    This is the python part:

    #! /usr/bin/python
    # -*- coding: utf-8 -*-
    import serial
    import time
    import serial.tools.list_ports
    from pythonosc import udp_client
    Receives Serial messages in the format "address:value" from Arduino
    and forward the value to the given OSC-address
     - pyserial (install with `pip install pyserial`)
     - python-osc (install with `pip install python-osc`)
    # A list of strings which identify a valid "Arduino" for us.
    # Use something from the description of list_comport_devices()
    PORT_IDENTIFIERS = ["Arduino", "CH340", "USB2.0-Serial", "USB Serial", "Teensyduino"]
    # OSC IP to connect to ( is the IP address of this computer)
    OSC_IP = ""
    # OSC Port to connect to (7001 is default)
    OSC_PORT = 7001
    def list_comport_devices():
        Print a list of devices connected to this computers serial port
        # Get a full list of devices connected
        ports = [p for p in serial.tools.list_ports.comports() if
    p.description != "n/a"]
        if len(ports) == 0:
            # If there are no devices connected, print this
            print("Found no devices connected to this computers Serial ports\n")
            # If there are devices connected...
            print(f"Found the following devices connected to this computers serial ports:")
            # Print each of the devices out
            print(f"   n {'port':<15} {'description':<15} {'manufacturer':<15} {'product':<15}")
            for i, p in enumerate(ports):
                device = f"[{p.device}]"
                print(f"  [{i}]{device:<15} {p.description:<15} {p.manufacturer if not p.manufacturer is None else 'None':<15} {p.product if not p.product is None else 'None':<15}")
    def is_suitable_device(port) -> bool:
        Return true if any of the Strings in the list PORT_IDENTIFIERS is found in
        a ports description or manufacturer
        in_description = any(x in port.description for x in PORT_IDENTIFIERS)
        in_manufacturer = any(x in port.manufacturer for x in PORT_IDENTIFIERS) if not port.manufacturer is None else False
        return in_description or in_manufacturer
    def find_first_arduino_port():
        This function returns the first device connected to this computers
    serial port, whose description matches with any string in the list
        PORT_IDENTIFIERS. If nothing is found print a message and wait
        # Get a list of devices which have any of the strings from the list
        # PORT_IDENTIFIERS in their description
        ports = [p for p in serial.tools.list_ports.comports() if is_suitable_device(p)]
        # When there are no devices found, just try again every second until
        # a device is found or the program is stopped
        while len(ports) == 0:
                print("  No serial port with Arduino found, not connected? Stop program with [Ctrl] + [c]", end='\r', flush=True)
                ports = [p for p in serial.tools.list_ports.comports() if is_suitable_device(p)]
            except KeyboardInterrupt:
            print("", end='\r', flush=True)
        # If a device is found, print a message and return the first one
        port = ports[0]
        print(f"  Found a suitable device connected at {port.device}: {port.description}")
        return port.device
    # -----------------------------------------------------------------------
    print("Trying to establish a connection to Arduino...")
    # List all devices connected to this computers Serial Ports
    # Find the first devices that seems to be an Arduino
    arduino_port = find_first_arduino_port()
    arduino = serial.Serial(port=arduino_port, baudrate=115200, timeout=.1)
    print(f"Established a serial connection to device at {arduino_port}")
    print(f"Creating OSC client which will send OSC data to {OSC_IP}:{OSC_PORT}")
    client = udp_client.SimpleUDPClient(OSC_IP, OSC_PORT)
    print("\nListening for incoming messages:")
    while True:
            serialdata = arduino.readline()
            received_string = serialdata.decode("utf-8").strip()
            if received_string != "" and ":" in received_string:
                address, value = received_string.split(":")
                print(f"  {arduino_port} ⟶ {value} ⟶ {OSC_IP}:{OSC_PORT}{address}")
                value = float(value)
                client.send_message(address, value)
            elif received_string != "" and not ":" in received_string:
                address = "/chn/1"
                value = float(received_string)
                print(f"  {arduino_port} ⟶ {value} ⟶ {OSC_IP}:{OSC_PORT}{address}")
                client.send_message(address, value)
        except KeyboardInterrupt:


    This the Arduino Code (upload onto the arduino via Arduino IDE):

    int led = 13;
    float pot = 0.0;
    float increment = 0.1;
    // Create a Buffer to hold characters for the messages
    String buffer;
    void setup() {
      pinMode(led, OUTPUT);
      // Reserve memory for the messages
    // the loop routine runs over and over again forever:
    void loop() {
      pot = analogRead(A0)
      // Send OSC message to this address
      sendOSC("/ch/1", pot);
    // /ch/1:5.234
    void sendOSC(String address, float value) {
        buffer += address;
        buffer += ":";
        buffer += String(value);
        buffer = "";