ofSerial doesn't find devices plugged in after the program has started

Hi all,

I’m a long time user of openFrameworks (5+ years) but this is my first time posting.

I raised this as an issue (see link below) but now I’m just here to try to find a workaround.

As I cannot attach a file I have posted (at the end) the source code of a modified copy of the serial example to recreate the issue with the steps below:

  • Unplug the Arduino USB cable from the PC.
  • Start/run the OF program.
  • Press any key to find connected serial devices.

Example output:
serial device found:
Intel(R) Active Management Technology - SOL (COM3) ID: 0 Port: COM3
serial device found:
Standard Serial over Bluetooth link (COM9) ID: 1 Port: COM9
serial device found:
Standard Serial over Bluetooth link (COM8) ID: 2 Port: COM8

  • Connect the Arduino USB cable to the PC while the OF program is still running.
  • Press any key to find connected serial devices.

Example output:
serial device found:
Intel(R) Active Management Technology - SOL (COM3) ID: 0 Port: COM3
serial device found:
Standard Serial over Bluetooth link (COM9) ID: 1 Port: COM9
serial device found:
Standard Serial over Bluetooth link (COM8) ID: 2 Port: COM8
serial device found:
Intel(R) Active Management Technology - SOL (COM3) ID: 0 Port: COM3

The expected output which I get if the Arduino USB cable is already connected before I start the OF program:

serial device found:
Intel(R) Active Management Technology - SOL (COM3) ID: 0 Port: COM3
serial device found:
Standard Serial over Bluetooth link (COM9) ID: 1 Port: COM9
serial device found:
Standard Serial over Bluetooth link (COM8) ID: 2 Port: COM8
serial device found:
Arduino Due (COM7) ID: 3 Port: COM7

The same correct output above is obtained even if Arduino is disconnected and reconnected while the OF program is still running and a key is pressed to detect serial devices.

Is there any workaround that will allow the program to detect the Arduino even if the USB is connected after the OF program is started?

Any help would be much appreciated.

Thanks,
Joe

Source code:

ofApp.h

#pragma once

#include "ofMain.h"

class ofApp : public ofBaseApp{
	
	public:
		void setup();
		void update();
		void draw();

		void keyPressed  (int key);
		void keyReleased(int key);
		void mouseMoved(int x, int y );
		void mouseDragged(int x, int y, int button);
		void mousePressed(int x, int y, int button);
		void mouseReleased(int x, int y, int button);
		void mouseEntered(int x, int y);
		void mouseExited(int x, int y);
		void windowResized(int w, int h);
		void dragEvent(ofDragInfo dragInfo);
		void gotMessage(ofMessage msg);
		
		ofTrueTypeFont		font;

		bool		bSendSerialMessage;			// a flag for sending serial
		char		bytesRead[3];				// data from serial, we will be trying to read 3
		char		bytesReadString[4];			// a string needs a null terminator, so we need 3 + 1 bytes
		int			nBytesRead;					// how much did we read?
		int			nTimesRead;					// how many times did we read?
		float		readTime;					// when did we last read?		

		vector<int> deviceIds;
		vector<string> deviceNames;	
		vector<string> comPorts;

		int currentDeviceIndex = 0;

		ofSerial	serial;
};

ofApp.cpp

#include "ofApp.h"

//--------------------------------------------------------------
void ofApp::setup(){
	ofSetVerticalSync(true);
	
	bSendSerialMessage = false;
	ofBackground(255);	
	ofSetLogLevel(OF_LOG_VERBOSE);
	
	font.load("DIN.otf", 32);
	
	serial.listDevices();
		
	nTimesRead = 0;
	nBytesRead = 0;
	readTime = 0;
	memset(bytesReadString, 0, 4);
}

//--------------------------------------------------------------
void ofApp::update(){
	
	if (bSendSerialMessage){
		
		// (1) write the letter "I" to serial:
		serial.writeByte('I');
		serial.writeByte('\n');
		
		// (2) read
		// now we try to read 3 bytes
		// since we might not get them all the time 3 - but sometimes 0, 6, or something else,
		// we will try to read three bytes, as much as we can
		// otherwise, we may have a "lag" if we don't read fast enough
		// or just read three every time. now, we will be sure to 
		// read as much as we can in groups of three...
		
		nTimesRead = 0;
		nBytesRead = 0;
		int nRead  = 0;  // a temp variable to keep count per read
		
		unsigned char bytesReturned[3];
		
		memset(bytesReadString, 0, 4);
		memset(bytesReturned, 0, 3);
		
		while( (nRead = serial.readBytes( bytesReturned, 3)) > 0){
			nTimesRead++;	
			nBytesRead = nRead;
		};
		
		memcpy(bytesReadString, bytesReturned, 3);
		
		bSendSerialMessage = false;
		readTime = ofGetElapsedTimef();
	}
}

//--------------------------------------------------------------
void ofApp::draw(){
	if (nBytesRead > 0 && ((ofGetElapsedTimef() - readTime) < 0.5f)){
		ofSetColor(0);
	} else {
		ofSetColor(220);
	}
	string msg;
	msg += "press any key to scan for & connect to arduino:\n";
	msg += "left mouse click to test serial:\n";
	msg += "nBytes read " + ofToString(nBytesRead) + "\n";
	msg += "nTimes read " + ofToString(nTimesRead) + "\n";
	msg += "read: " + ofToString(bytesReadString) + "\n";
	msg += "(at time " + ofToString(readTime, 3) + ")";
	font.drawString(msg, 50, 100);
}

//--------------------------------------------------------------
void ofApp::keyPressed  (int key){ 

vector <ofSerialDeviceInfo> deviceList = serial.getDeviceList();

for(int i = 0; i < deviceList.size(); i++)
{

	deviceIds.push_back(deviceList[i].getDeviceID());
	deviceNames.push_back(deviceList[i].getDeviceName());

	//Workaround attempt 1
	comPorts.push_back(deviceList[i].getDevicePath());

	//Workaround attempt 2
	//size_t comPortStartPos = deviceNames[i].find("(COM") + 1;			 //Obtain the position of "C" in the COM port name.
	//size_t comPortEndPos = deviceNames[i].find(")", comPortStartPos + 4); //Obtain the position of ")" in the COM port name.
	//size_t comPortLength = comPortEndPos - comPortStartPos;					 //Obtain the length of the COM port name. 
	//comPorts.push_back(deviceNames[i].substr(comPortStartPos, comPortLength)); //Obtain the COM port name. 

	if(deviceNames[i].find("Arduino") != string::npos){ currentDeviceIndex = i; }

	//DEBUGGING.
	cout << "serial device found: " << endl;
	cout << deviceNames[i] << "   ID: " << deviceIds[i] << "   Port: " << comPorts[i] << endl;
}

if(serial.isInitialized() == false) serial.setup(comPorts[currentDeviceIndex], 9600);
	
cout << endl << endl;

}

//--------------------------------------------------------------
void ofApp::keyReleased(int key){ 
	
}

//--------------------------------------------------------------
void ofApp::mouseMoved(int x, int y){
	
}

//--------------------------------------------------------------
void ofApp::mouseDragged(int x, int y, int button){
	
}

//--------------------------------------------------------------
void ofApp::mousePressed(int x, int y, int button){
	bSendSerialMessage = true;
}

//--------------------------------------------------------------
void ofApp::mouseReleased(int x, int y, int button){
	
}

//--------------------------------------------------------------
void ofApp::mouseEntered(int x, int y){

}

//--------------------------------------------------------------
void ofApp::mouseExited(int x, int y){

}

//--------------------------------------------------------------
void ofApp::windowResized(int w, int h){
	
}

//--------------------------------------------------------------
void ofApp::gotMessage(ofMessage msg){
	
}

//--------------------------------------------------------------
void ofApp::dragEvent(ofDragInfo dragInfo){ 
	
}