Hardware Control via Serial USB

Hi,
I’m starting to develop my first VST. It will be a remote control to my hardware device (synth).
In result my plugin will not process audio or midi, just control my device via serial usb.

I tried this lib:
https://github.com/cpr2323/juce_serialport

It’s work in general but i have some trouble in Ableton. For example if I open a project with a instance of my plugin it can’t connect to my device. It work only in a new empty project.

Now I’m thinking to move to an other more Professional lib: libusb (http://libusb.info/)
This project allows to control any type of parameters but seems really complicated.

So before start studying I want to be sure that it’s the correct way.

There is a better lib/projet that deserve my attention to conncect my device with my vst?
Do you have some sample to advice me?

Thank
Andrea

I didn’t work with libusb so far but afaik this library accesses a completely different layer of the USB protocol than a library interfacing with serial ports does.

So if your hardware device exposes a virtual serial port via usb, accessing the lower layers of your usb port will probably not give you access to anything meaningful to you, as the driver probably coming with your operating system already does the first translation for you so that you can access the higher abstraction layer of the serial port.
Tinkering around with the lower protocol layer is probably only useful if you are designing your own hardware with its own custom usb protocol that does not expose itself to the system as a virtual serial port. And it’s definitively a super complicated task.

So first: What device are we talking about? And second: If it works everywhere but in Ableton wouldn’t it be better to find the source of why it’s not working in Ableton instead of switching the library (there are other serial port libs out there as well…) just to find out that another library doesn’t work in Ableton too?

For any more detailed help better give us some more context and code snippets :slight_smile:

@PluginPenguin thank you very much for these precious information.

Actually in this early step I’m working with a Teensy (Arduino compatible) board, so probably usblib is not a deal for me cause it work too lower for my project.

And yes it’s a good idea try to understand why my implementation has some problem with Ableton, but before spend a lot of time to fix my code I would to know if there is a frequently used and recommended Library/Project in this kind of project.

I have tried to find other projects to evaluate but for now I have not had luck

In case I will continue with juce_serialport I will open a specific topic with my problem (with code etc etc)

Andrea

While juce_serial is a bit crufty, it continues to work for me in most cases. I have used it on numerous Arduino based projects, as well in a couple of professional projects. I will gladly take a peek if you are having issues. There are two other projects (libserialport: https://sigrok.org/wiki/Libserialport and Boost ASIO: https://www.boost.org/doc/libs/1_73_0/doc/html/boost_asio.html)I keep thinking about switching to, just because they are actively maintained, but there is more work to integrate either of these, so I haven’t attempted it yet.

@cpr I really appreciate your help!
“Crufty” is exactly what I mean. It’s a good start point but it’s strange for me can’t find a more professional project to integrate my device without having to implement a low-layer lib as libusb.

Probably I’ll continue with juce_serialport for now.
Thanks for offering to analyze my problem, it’s about the Open phase.

In particular in constructor of Process class I have:

char* portName = "\\\\.\\COM15";
pSP = new SerialPort(portName, SerialPortConfig(9600, 6, SerialPortConfig::SERIALPORT_PARITY_NONE, SerialPortConfig::STOPBITS_1, SerialPortConfig::FLOWCONTROL_NONE));

In the processBlock i have:
if (threshold_int != oldThresholdValue)
{
std::string output = “<cmd_threshold:”;
std::string output_val = std::to_string(threshold_int);

    output.append(output_val);
    output.append(">");

    int commandLength = output.length();

    if (pSP->exists())
    {

       SerialPortOutputStream* pOutputStream = new SerialPortOutputStream(pSP);
       const void* a = output.c_str();
       pOutputStream->write(a, commandLength); //write some bytes

    }
    //}
    oldThresholdValue = threshold_int;
}

The problem is:
To make it work i have to Open Ableton, new Project, Connect my Device, add the Plugin
If I open a Project with already an instance of my plugin inside and the device is already connected. It doesnt work. :frowning:

Not sure if you know, but a serial port can only be opened once. Are you expecting to be able to open the serial port more than once? ie. in your description where it fails, you say you have an instance of your plugin, which would already have the serial port open. So, it is expected that you cannot open the serial port a second time (ie. in a second instance of your plugin).

Also, btw, it’s not really a good idea to do serial port operations in processBlock.

So you are using the Arduino/Wiring framework for your programing work? In this case I still guess you’ll have a super hard time developing your own custom USB protocol, as the functionality of the USB port is deeply nested in the Teensyduino implementation. However, beneath creating your own protocol and using a serial protocol, Teensyduino has two other interesting options for you.

First is to configure your USB port as a USB MIDI interface. Pros of this: You can either use it through the host or open the device yourself in the plugin through the MIDI functionality that already comes with JUCE. With SysEx messages, you can build up nearly arbitrary complex communication patterns. Another good point of this is that the device identification is quite a lot easier, you don’t need a complex way to find out which /dev/ttyUSBModemXYZ is your device, which can become quite cumbersome if multiple usb-serial adaptors are connected. Downside is: Other MIDI-compliant applications can easily send data to your device, you might not want to enable that.

Second is to configure it as a raw HID compliant USB device. The HID device class is supported out of the box by all operating systems and while being not as flexible as a complete custom protocol it still might be sufficient for all your needs. I Always wanted to do something like that but never found time for it, but the hidapi library should get you started (I think there was a JUCE wrapper for hidapi published somewhere here on the forum some time ago) and probably this teensy example C code for Teensy: USB Raw HID - for building custom USB devices

And finally as @cpr already said, under no circumstances processBlock is neither the right place to perform any I/O hardware communication nor to perform string manipulation with std::string or alike. Always remember the golden rule of audio programming: No system calls including I/O and memory allocations (which are automatically done by std::string behind the scenes) on the audio thread. You will probably have to set up a dedicated thread for your I/O communication

@cpr yes I know it.
The problem occurs if I open a project (for example in Ableton) and this project have a instance of my plugin. This unique instance can’t connect with device. Instead when I add a new (unique) instance to a empty project it works.

Mhh I figured out that processBlock in not the correct way. Where is the correct position to communicate with serial port?

Do you know some example project where I can see the correct use?

Thank you very much

I don’t think your connection issue is in the serial library. But, as with any bug, the best way to resolve the issue is to debug it. Step into the serial port library and see what the failure is.

Where is the correct position to communicate with serial port? um, not on the audio thread… lol… sorry, but that’s the answer. You also probably don’t want it on the main/message thread, as you will end up blocking your UI. I tend to spin up threads specifically for communicating with serial ports, and then have a way for other threads to communicate with that system.

@cpr yes it’s defenitly a problem in my code. I have seen things that could be the problem.

Regarding the position, I understood that is not correct put it in audio thread, but I’m new in JUCE and t was the first solution that came to my mind :slight_smile:
I’ll try to understand how use a dedicated thread to communicate. If you know some example/project where I can find this “best practice” I apreciate that.

Thanks for your help