VifuLens interface, shown on top of Raspberry Pi The VifuLens is an interface designed with the aim to provide remote control for B4-mount broadcast lenses and PT(Z) head, using VISCA commands sent over a TCP network. It comprises of a microcomputer connected to the LAN, an analog interface that connects directly to the zoom, focus and iris (ZFI) connectors of the lenses and a RS-232 serial port that connects to the pan and tilt head (PT(Z)). While originally designed for Fujinon broadcast lenses and PTZOptics broadcast pan & tilt head combination, it can be adapted to other scenarios as well.

I started developing this hardware interface and its related software within a specific project I worked on, where a system consisting of several Micro Studio Camera 4K cameras, MTF B4 lens adapters, ZA17x7.6BERD lenses and PT-610 / PT-BRDCSTR-P PTZ heads had to be installed. The interface turned out to be a necessity, because the PTZ head controller model, which was specifically requested for that project, has been originally designed to connect to remote lens control of compact camcorders, not to independent B4-mount broadcast lenses type which usually equips ENG or EFP cameras.

Note: the PT-610 broadcast pan & tilt head appears now to be discontinued by PTZOptics, but it may be still available from the VHD company .

Although the PT-BRDCSTR-P proved to be an excellent product in terms of sturdiness and movement precision, it has no provisions – at least not in the version I played with – to set an absolute positioning value for zoom, because its electrical zoom interface is designed to provide relative levels voltage output, just enough for generic zoom in / zoom stop / zoom out commands. Zoom status reading (lens position feedback) is not implemented and also focus and iris status reading back of own previously given positions did not seem to be implemented either – something that was explicitly required within my specific project.

Note: in principle, driving the lenses via a serial connection (on digital series lenses providing a serial communication feature) would have been a better solution*, but because I didn’t know right from the start the exact model of the lenses, combined with the very short time I had at my disposal to get the job done on that specific project, I thought it was unrealistic to come to an end right on time – so that’s why I opted for an analog lenses driving solution, which is also somewhat more universally compatible.

* In this case, “better” means fewer wired connections to the lenses and just a little bit more accurate ZFI positioning.

The description is as follows:

  1. The interface on lenses servo side
  2. The interface on controller side
  3. Implementation example

(i) The interface on lenses servo side

The VifuLens hardware interface includes own DAC and ADC converters and analog voltage level shift circuits for each of the ZFI controls. The voltage level shift circuits translates the 0V-2.047V range of the local DAC converters to the 2.5V-7.5V range as required for lens control – and vice versa, from 2.5V-7.5V range of the lens status into the 0V-2.047V range for feedback reading with the local ADC converters. As for the precision when storing and then recalling ZFI positions, the inherent dispersion related to analog component tolerances is insignificant for human perception.

To be noted that, while each of the ZFI control has and can use its own ADC hardware converter, in current software implementation it is only the zoom that actually uses the ADC feedback – while focus and iris controls just read back the “direct drive” value as passed to their respective DACs.

The hardware interface is built on top of a Raspberry Pi 2 Model B v1.2 Industrial. I deliberately chose Pi 2 instead of Pi 3, for good reasons: Pi 3 dissipates a lot more heat and also exposes some sharing trouble – though solvable – on the UART port, all of which are disadvantageous for this project.

Raspberry Pi 2 has no native Wi-Fi interface; if wireless connection is really necessary or perhaps advantageous for a given configuration, the lack of the embedded Wi-Fi interface can be easily overcome by using a USB Wi-Fi dongle with the Raspberry Pi 2.
The heat dissipation problem applies to Raspberry Pi 3 Model B, which was the latest version available at the time I started this project; the later PI 3 Model B+ is much better designed from this point of view.

The software running the interface is written in Python. All ZFI commands are processed locally, whereas all pan and tilt commands are sent to the PT(Z) head “as is”. ZFI presets are stored locally on the micro SD card, while the PT(Z) presets are stored natively within the pan and tilt head. Up to 255 presets can be stored, which is far more than the usual range as specified under the standard CAM_Memory VISCA control commands category.

The zoom control accepts two operating command modes: a “Standard” mode for full speed zoom movement and a “Variable” mode that tries to emulate the “seesaw” mechanical control lever of the real lenses. For variable mode, there are 8 steps of progressive speed control for each zoom direction, a number which is specified during the CAM_Zoom Tele(Variable) and CAM_Zoom Wide(Variable) VISCA control commands. All these movement speeds are in turn dependent on the zoom maximum speed control knob, located on the lenses servo.

Absolute zoom positioning was not directly possible due to the relative nature of the “seesaw” command as required by the electrical interface of the lenses servo in analog drive mode, therefore I implemented a software digital comparator that keeps in sync the physical zoom position as read via the ADC converter with the CAM_Zoom Direct VISCA control command position; otherwise, when absolute zoom positioning is not required (e.g. during “normal” zoom in / zoom stop / zoom out commands), the comparator gets deactivated.

The circuit schematic diagram can be seen here . Although fully functional, the circuit is at its first incarnation and may receive further improvements. For example, I may add an additional electronic switch circuit for the focus and iris command to the lenses, so that the remote control on these can be deactivated programmatically. At the moment, only the zoom provides such a switch circuit.

I designed the actual PCB using the Sprint Layout program, which for me is still the most convenient method to create printed circuit boards. However, I assume that the printed circuit board can also be designed based on – for example – the project that I created using the KiCad program just for drawing the diagram.

The software that runs on Raspberry Pi is available below for download. It should run under Python 3 and requires the Adafruit_Python_ADS1x15 library that must be installed under Python 3.

Current software version is 2.0 (click here for versions history).
The software is published under the GPLv3 license.

Important: in case the VifuLens software is set to autorun in unattended mode via rc.local script or the like, then the PRINTe parameter in the “” file must be set to False.

The following VISCA control commands are implemented:

command set command command packet comments
CAM_Zoom Stop 8x 01 04 07 00 FF  
Tele (Standard) 8x 01 04 07 02 FF  
Wide (Standard) 8x 01 04 07 03 FF  
Tele (Variable) 8x 01 04 07 2p FF p: speed parameter, 0 (Slow) to 7 (Fast)
Wide (Variable) 8x 01 04 07 3p FF
Direct 8x 01 04 47 0p 0q 0r 0s FF pqrs: zoom data, 0x0000 (Wide) to 0x0FFF (Tele)
CAM_Focus Stop 8x 01 04 08 00 FF  
Far (Standard) 8x 01 04 08 02 FF  
Near (Standard) 8x 01 04 08 03 FF  
Far (Variable) 8x 01 04 08 2p FF p: speed parameter, 0 (Low) to 7 (High)
Near (Variable) 8x 01 04 08 3p FF
Direct 8x 01 04 48 0p 0q 0r 0s FF pqrs: focus data, 0x0000 (Close) to 0x0FFF (Infinity)
Infinity 8x 01 04 18 02 FF forced infinity
CAM_Iris Reset 8x 01 04 0B 00 FF defaults to f5.6 approx.
Up 8x 01 04 0B 02 FF single step iris opening
Down 8x 01 04 0B 03 FF single step iris closing
Direct 8x 01 04 4B 00 00 0p 0q FF pq: iris data, 0x00 (fully closed) to 0x11 (fully open),
in 17 steps equivalent to c, f28, f22, f19, f16, ...,
..., f2.8, f2.4, f2.0, f1.8 approx.
CAM_Memory Clear 8x 01 04 3F 00 pq FF pq: maximum 255 presets, from 0x00 to 0xFE
Set 8x 01 04 3F 01 pq FF
Recall 8x 01 04 3F 02 pq FF
Note: for VISCA over IP, camera address “x” is locked to 1.
command set command packet inquiry packet comments
CAM_ZoomPosInq 8x 09 04 47 FF y0 50 0p 0q 0r 0s FF pqrs: zoom position
CAM_FocusPosInq 8x 09 04 48 FF y0 50 0p 0q 0r 0s FF pqrs: focus position
CAM_IrisPosInq 8x 09 04 4B FF y0 50 00 00 0p 0q FF pq: iris position
Note: for VISCA over IP, camera address “x” is locked to 1 and camera address “y” is locked to 9.

Any other VISCA command not mentioned above is passed directly to the PT(Z) head through the RS-232 serial port (9600 8N1).

The software uses a built-in TCP socket server that listens to port number 5678. The port number can be changed with parameter SERVER_PORT (currently on line 36 of the “” file).

At power-up, the software tries to load preset 0 in order to set initial ZFI position values – and the same should normally go for the PTZ head on its own. If preset 0 is not found as in case it was never saved or prior deleted, then the power-up position values for ZFI are set by parameters TEMP_ZOOM_DAC, TEMP_FOCUS_DAC and TEMP_IRIS_INDX (currently on lines 110, 111 and 112 of the “” file.

No default enclosure is provided, yet. The VifuLens circuit board requires 5V power supply with minimum 2.5A capability and provides its own DC connector. The Raspberry Pi does not require a separate power supply. To be noted that the hardware includes a few operational amplifiers that requires 12V power supply, which is taken from the lenses servo through the Hirose connectors (the required current for the op amps is negligible).

VifuLens & RPi overall assembly view
Quick view of the VifuLens & RPi assembly
Connection to bottom of the lenses
VifuLens connections to zoom & focus lenses connectors

(ii) The interface on controller side

One way to control the VifuLens interfaces – and so the camera system – is by using a hardware joystick controller, equipped with a serial communication interface**. Actually that was the situation in my case, so I had to develop a serial to IP converter: the result is RS2IPVIS, a software companion for VifuLens that may be suitable for use in other scenarios as well.

** Other way to control the VifuLens interface is by means of a software camera control application (like, for example, PTZ Controller , Camera Controller , D70 Commander or Visca Camera Controller ), but this becomes outside the scope of this article.

The RS2IPVIS software is written in Python and can serve up to 2 joystick controllers – which in VISCA terms that means control for up to 7+7 cameras. Right from the start I designed it to run either on Raspberry Pi or on BeagleBone Black.

The Raspberry Pi has only one UART on it, while BeagleBone has four; however, all their UARTs are at TTL-like logic levels, which means a suitable hardware interface must be used with either of their UARTs in order to be able to use standard RS-232 connections. Because that means another hardware hassle and because the Raspberry Pi has only one native UART anyway (while I needed to control 2 separate joystick controllers), I ended up using two ATEN UC-232A USB to RS-232 adapters, which are using Prolific PL2303 chipset.

The software is available below for download. It should run under Python 3, the IP camera addresses must be set at parameters AVAILABLE_ADDRESSES_1 (for one group of up to 7 cameras) and AVAILABLE_ADDRESSES_2 (for the other group of up to 7 cameras) in the “” file and may require further customization based on the actual UART or USB to serial adapter as used in practice.

Current software version is 1.8 (click here for versions history).
The software is published under the GPLv3 license.

Important: in case the RS2IPVIS software is set to autorun in unattended mode via rc.local script or the like, then the PRINTe parameter in the “” file must be set to False.

As is, the configuration is for use with Raspberry Pi 3 Model B+ with two USB to RS-232 adapters inserted into its left (either upper or lower) and right (either upper or lower) USB ports. If required, the parameters from lines under # valid for RPi and/or lines under # valid for BeagleBone in the “” file must be modified. Provisions are already there for Raspberry Pi 2 Model B v1.2 using either its single native UART or two USB to RS-232 adapters inserted into its left and right USB ports, or for Raspberry Pi 3 Model B+ using two USB to RS-232 adapters inserted into its left and right USB ports (actual config), or for BeagleBone Black using its native UARTs 1 & 2.

If USB to RS-232 adapters are used, the respective USB ports must be make persistent. As an example, in case of using Raspberry Pi and ATEN UC-232A adapters, a file “/etc/udev/rules.d/99-usb-serial.rules” must be created with the following content:

SUBSYSTEM=="tty", KERNELS=="1-1.1.2", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.1.2"
SUBSYSTEM=="tty", KERNELS=="1-1.1.3", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.1.3"
SUBSYSTEM=="tty", KERNELS=="1-1.2", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.2"
SUBSYSTEM=="tty", KERNELS=="1-1.3", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.3"
SUBSYSTEM=="tty", KERNELS=="1-1.4", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.4"
SUBSYSTEM=="tty", KERNELS=="1-1.5", ATTRS{idVendor}=="0557", ATTRS{idProduct}=="2008", SYMLINK+="Prolific_PL2303_1-1.5"

The KERNELS value as used by the actual USB port and the ATTRS{idVendor} and ATTRS{idProduct} values as used by the actual USB to serial adapter manufacturer can be determined with the command:
udevadm info --attribute-walk --path=/sys/bus/usb-serial/devices/ttyUSB0

The KERNELS values 1-1.2, 1-1.3, 1-1.4 and 1-1.5 are for Raspberry Pi 2 Model B v1.2 and values 1-1.1.2, 1-1.1.3, 1-1.3 and 1-1.2 are for Raspberry Pi 3 Model B+, when the enumerated order for the USB ports is upper-left, lower-left, upper-right and lower-right. The file “99-usb-serial.rules” can hold several line parameters specified at once, regardless if just one or perhaps two USB ports are used at any one time or even for an USB port that does not exists or is not used on a given Raspberry Pi model (like when changing the same microSD card between different RPi models).

You should find more info on this on the internet by searching something like Linux persistent USB.

(iii) Implementation example

Below is the principle diagram of a PTZ control system using the VifuLens interface and the RS2IPVIS software companion (click on the image for a PDF version):

Note: for the clarity of the drawing, only camera 1 from each of the two groups of cameras is highlighted.

Implementation example: VifuLens System at the Romanian Chamber of Deputies
VifuLens System (principle) as installed at the plenary room of the Romanian Chamber of Deputies
(Romanian: Camera Deputaților)

In the actual case of the above example, the cameras are organized in left-right groups – i.e. one controller for the cameras on the left side of the plenary room and the other controller for the cameras on the right side of the plenary room (as viewed by the technical operator).

Matter of fact, the VifuLens system as depicted here replaced a previous AMX controller based system, which worked in conjunction with the Shure DIS conference system who serves the plenary room. Given that the CoD ordinary sessions generally requires a more statical approach, the VifuLens system proved to be a more reliable solution considering the video equipments there.


Go to top