Using a Stream deck and a raspberry pi to create a remote control panel to adjust marshall cameras over ip with rs-485 control

At my church, we have 4 of these cameras: Marshall CV503

Marshall CV503 Miniature Camera

We use them during services to capture shots of the instruments (drums, keys, etc.) and whatever is happening on stage. They are great little action-style cameras, and they have SDI out on them so they are super easy to integrate into our video system.

They have a lot of adjustment options to them via a local joystick-style controller at the camera, but obviously, that’s challenging to use during a service if we needed to adjust the camera’s exposure. The menu is OSD and shows up on the live output. Plus they’re all over the stage and we can’t walk there during the service!

While I wish they were IP-controllable directly, this particular model does not have that option. They do, however, come with RS-485 serial connectors.

So we decided to create a remote shading system using a stream deck running Bitfocus Companion. The Marshall cameras support the VISCA protocol over RS-485. In fact, if you’re a Windows user, Marshall provides free software to control the cameras over RS-485.

Marshall provides this program to control, if you have Windows and want to connect your cameras directly to that computer.

We don’t use a lot of Windows computers around here, and that program requires that the computer running their software be the one physically connected to the cameras via serial. Not ideal for us because the cameras are on a stage and our computers typically are not. Marshall also actually makes a nice hardware RCP – but we didn’t want to pay for that.

So we did what you probably already guessed – put in a Raspberry Pi with a USB to RS-485 adapter that we could control remotely.

We have several wallplates across the stage with network tie lines on them that feed back to the rack room in a patchbay. So we made cables that connect to the RS-485 ports at each camera that then go back to a wall plate into a RJ45 port. We utilized the blue/white-blue pair on CAT6 cable. We used that pair because these are data pins in a normal network connection, which means if someone ever accidentally connected it straight to a switch or something, there would not be any unintended voltage hitting the cameras.

Each camera is set to its own camera ID (1-4), and the matching baud rate of 9600 (the default). Then in the rack room, we made a custom loom to take the 4 connections and bring them into a jack, which then feeds into the USB to RS-485 adapter on the Pi.

The Pi is a 4 model with 4GB of ram. Honestly, for what this thing is doing, we probably could have just run it off of a Pi Zero, but I wanted it hardwired to my network, and the bigger Pi’s come with ethernet ports built in.

I bought this adapter off Amazon:

DSD TECH SH-U10 USB to RS485 Converter with CP2102 Chip

When connected, it represents itself as serial port /dev/ttyUSB0. We originally planned to use the socat program in Linux to listen for UDP traffic coming from Companion:

sudo socat -v UDP4-LISTEN:52381 open:/dev/ttyUSB0,raw,nonblock,waitlock=/tmp/s0.locak,echo=1,b9600,crnl

To actually send the UDP data, we’re using the Sony VISCA module already built into Companion. The Marshall cameras use the same protocol over RS-485.

Using the socat method, we quickly found that it would only listen to UDP traffic coming from one instance of the module. We need 4 instances of the Companion module because we have 4 cameras, each with a different camera ID.

However, nothing a small Node.JS program can’t solve. So I wrote a program that opens the specified UDP port, opens the specified serial port, and sends any data received at that UDP port straight to the serial port. You just configure a new instance in Companion for each camera with the same IP of the Pi running the udp-to-serial program, and the camera ID that you configured at the Marshall camera.

Here’s a video that shows it all in action:

If you want to try this out for yourself, I’ve made the udp-to-serial repository available here:


  1. I’m trying to connect one camera (at the moment), and I’m not getting any response from the camera. What pins are you using on the serial adapter? In the video, it appears that there are 4 wires connected to the serial adapter, but the camera only uses 2.


      1. ok, still not seeing a response from the camera. I set the ID, are there any other settings I need to change to allow remote control? I’m starting with the same Gain controls, and I’d love to be able to do white balance as well.


    1. Iv got 1 Marshall CV503 and am using a Windows 10 PC instead. I connected a 2 core cable to the RS-485 connector on the camera and the other end to the USB adapter you recommended. Iv plugged this into the PC which finds the driver and automatically installs it.
      In the Companion software i use the Sony Visca module and input the IP address of the PC and the ID of the camera (ID1). Iv installed gain up and gain down buttons but it does not work, pressing either button has no affect. Iv tested the cable using the Marshall Camera Control software and that works fine.
      Any ideas?


      1. Phil, you didn’t mention it, but I’m assuming you’re running my udp to serial program?
        I thought i only needed this if i was going RS-485 into a network? Im going cable only RS-485 camera to USB adapter into PC?


      2. Thanks Joseph now I understand. Do you know how to set this up in windows 10. Do I have to download java, if so what version, where do i get your script to run etc. Thanks again


  2. Update: I discovered that I needed to set the AE setting to full manual for the controls to work, that would be something helpful to add to the directions. The only hiccup now is that the server doesn’t run automatically. Here’s what I get: pi@raspberrypi:~/udp-to-serial $ pm2 startup index.js –name udp-to-serial
    [PM2] Init System found: systemd
    PM2 detected systemd but you precised index.js
    Please verify that your choice is indeed your init system
    If you arent sure, just run : pm2 startup
    [PM2] To setup the Startup Script, copy/paste the following command:
    sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup index.js -u pi –hp /home/pi
    pi@raspberrypi:~/udp-to-serial $ pm2 startup
    [PM2] Init System found: systemd
    [PM2] To setup the Startup Script, copy/paste the following command:
    sudo env PATH=$PATH:/usr/bin /usr/lib/node_modules/pm2/bin/pm2 startup systemd -u pi –hp /home/pi
    pi@raspberrypi:~/udp-to-serial $


  3. Got this working on Windows 10.
    I have the button “WB Indoor” set to Indoor
    I have the button “WB Push” set to White Balace Mode ATW
    I have the button “Gain Up” set to Gain Up and “Gain Down” set to Gain Down
    BUT gain up and down does not work. Holding the butons down or quickly pressing them has no effect on the Gain?


  4. Thank you Joseph, will that AE setting also allow the shutter and iris to be controlled via the relevant companion buttons?


  5. One last question in your config.json you have “/dev/ttyUSB0” for the port_serial. Do you know what to put in here for a windows PC?


  6. This has given me an idea. I have 2 P2 Panasonic Cameras but they don’t have any remote control protocol’s but they do have a 2.5mm jack for Zoom,S/S and 3.5mm jack for Focus/Iris. I was wondering if I get a RS-232 serial adapter to 2.5mm/3.5mm cable to then an IP based controller like the Global Cache I then could remotely shade that camera. But then I would need to figure what module I would need to you use to control it. You think this could work Joesph?


  7. Thanks for all of the insight and work you have done to facilitate this.
    I am attempting to replicate with a slight variation but have come across an error I’m trying to correct and looking to see if you are familiar with it or an idea on correcting.

    When running the node index.js I receive the following error

    Error: Error: bind EADDRINUSE

    I am running it on a pc to verify the process works before investing in another pi



  8. Thanks so much for this!! I do have one question. we are controlling three of the cv503’s using companion like you show in the video. do you know what sony visca commands to use to send the menu button (on screen display, like you’re using the joystick on the camera cable), as well as the arrow buttons? TIA!


      1. I can access them using the software from Marshall, so I should be able to send them from companion, i think… let me ask this: is there a way to set up something on a windows computer that would allow the Marshall software to connect to a virtual com port that would send these commands from the Marshall software to the raspberry pi? so I can connect the software AND/OR companion to the raspberry pi?


  9. I have never used their software, so I don’t know how it works. You might be able to run Wireshark to figure out what commands are being sent by the program, and then recreate that in Companion using the generic TCP/UDP module to then send commands over UDP to the Pi. Let me know what the commands are because I’d like to be able to do this also.


  10. Hi Joseph! I’m running into an error when starting the udp-to-serial program. I’ve tried everything but am out of options.

    chiel@ubuntu:~/Desktop/udp-to-serial$ node index.js
    Opening Serial Port: /dev/ttyUSB0
    Baud Rate: 9600
    serialPort = new SerialPort(config.port_serial, {

    TypeError: SerialPort is not a constructor
    at startup (/home/chiel/Desktop/udp-to-serial/index.js:76:15)
    at Object. (/home/chiel/Desktop/udp-to-serial/index.js:88:1)
    at Module._compile (node:internal/modules/cjs/loader:1101:14)
    at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
    at Module.load (node:internal/modules/cjs/loader:981:32)
    at Function.Module._load (node:internal/modules/cjs/loader:822:12)
    at Function.executeUserEntryPoint [as runMain] (node:internal/modules/run_main:81:12)
    at node:internal/main/run_main_module:17:47

    chiel@ubuntu:~$ npm serialport -v
    chiel@ubuntu:~$ dmesg | grep tty
    [ 11.565696] usb 2-2.1: cp210x converter now attached to ttyUSB0

    Do you have any idea what I’m doing wrong?


      1. The only possible solution I found on google suggested upgrading serial port to version 10 but that didn’t solve the problem.
        I downgrade Node from v16 to v11 and the program runs smoothly now. Thanks for your help and advice!


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s