Detecting a serial port valid after disconnect/reconnect

I asked before with a long question and got no answers, so let's keep it simpler.
Serial port is connected to Arduino
Arduino resets, so I need to:
1. Detect that it's gone without throwing an error
2. Reconnect
Results:
Connected and callback set
K>> app.Pico
ans =
Serialport with properties:
Port: "COM16"
BaudRate: 57600
NumBytesAvailable: 0
Hit reset on Pico get following error message ( but it doesn't stop my program from running)
Unable to detect connection to the serialport device. Ensure that the device is plugged in and create a new serialport object.
If there is no "keep alive" function for serial ports ( Walter Roberson in https://www.mathworks.com/matlabcentral/answers/1722140-cant-read-the-serial-port) then what is generating this error? How can I catch it without constantly checking the connection myself?
If I could trap the error here that would be a great start.
So let's look at where we are:
K>> app.PicoCom
ans =
Serialport with properties:
In 'testmeaslib:CustomDisplay:PropertyWarning',
data type supplied is incorrect for parameter {0}.
Not useful, but I can check it right?
K>> isvalid(app.PicoCom)
ans =
logical
1
Really? It's still valid? Let's try
K>> serialportlist("available")
ans =
1×2 string array
"COM1" "COM16"
OK, at least I can see it's back in the list of available ports. Is this the best (fastest) way to find out?
Also I can't check in the input call back because then it's too late. Error thrown already.
K>> delete(app.PicoCom)
K>> app.PicoCom
ans =
handle to deleted Serialport
K>> isvalid(app.PicoCom)
ans =
logical
0
At least once deleted it's not valid. Let's reconnect:
K>> app.PicoCom = serialport()
K>> app.PicoCom
ans =
Serialport with properties:
Port: "COM16"
BaudRate: 57600
NumBytesAvailable: 0
ByteOrder: "little-endian"
DataBits: 8
StopBits: 1
Parity: "none"
FlowControl: "none"
Timeout: 10
Terminator: "CR/LF"
Back to normal as soon as I add
K>> configureCallback(app.PicoCom,"terminator",@app.PicoInput);
So I think I've got recovery OK. How about detecting when coms are lost?
BTW serialportfind is only useful when teh prot is there. If it's missing then looking throws an error...
K>> serialportfind
ans =
Serialport with properties:
In 'testmeaslib:CustomDisplay:PropertyWarning',
data type supplied is incorrect for parameter {0}.
Apparently it's a valid question to ask, just not a useful answer.
K>> isvalid(serialportfind)'
ans =
logical
1

3 Comments

Note: the lack of keep-alives for serialport() does not necessarily imply that there are no keep-alives for ports opened with arduino(), even if arduino() uses serialport() internally.
I'm using an Arduino, but NOT Matlab's Arduino module. Just the serial port. I don't want any ML hand holding or interference in my Arduino code.
Now I'm really confused. I've been using my workaround to check if the port is connected and now...
K>> serialportlist
ans =
1×2 string array
"COM1" "COM16"
So the device is there, but
K>> serialportlist("available")
ans =
"COM1"
But either Windows or Matlab won't let me have it back!
Other than rebooting the computer is there a way to fix this trap?
I've limited the computer to only be alloweed to have 2 COM ports, the built in COM1 and my USB port to simplify things. Here's the code I'm using to check what's up and I'm getting code 3 returned. There but not there.
function b = CheckAvailPort(app) % v61 depends on 2 serial ports on system
% returns 0 if properly connected
ports = serialportlist("available");
portCT = size(ports,2);
if portCT == 2 % Not connected
delete(app.PicoCom); % Leaves a "valid" dead deleted port!
app.PicoCom = []; % Clean it up
app.RebootPicoButton.BackgroundColor = 'yellow';
b = 1; % one port to connect, Init will work
else
% Make sure we have a COM port if it seems to be connected
if portCT == 1
try % If PicoComm isn't a valid port this will fail
if regexp(app.PicoCom.Port, regexptranslate('wildcard', 'COM*'))
b = 0; % all good
app.RebootPicoButton.BackgroundColor = 'white';
else
app.RebootPicoButton.BackgroundColor = 'red';
b = 2; % Something strange, haven't seen this problem yet
end
catch
app.RebootPicoButton.BackgroundColor = 'red';
warningMessage = sprintf(...
'No Pico USB device. Check connection and that Pico LED is flashing.');
uialert(app.MouseOdor,warningMessage,"No Pico found", "Icon","error");
b = 3; % Maybe Arduino has the port, or Pico locked up and not seen by Windoze
end
else
warningMessage = sprintf(...
'Too many USB devices. This program will not work.');
uialert(app.MouseOdor,warningMessage,"Extra USB devices found.", "Icon","error");
b = 4;
end
end
end

Sign in to comment.

 Accepted Answer

You may want to set the ErrorOccurredFcn property of serialport:
S=serialport('COM4',9600);
S.ErrorOccurredFcn=@(varargin)disp(varargin);

4 Comments

Thanks that shoud help with part 1
I tried it but I guess I don't have the syntax right I did this:
function PicoError(app) % more to add?
AddDebugText(app,"!!! Pico Error trapped");
app.RebootPicoButton.BackgroundColor = 'red';
end
and set it up like this:
ports = serialportlist("available");
app.PicoCom = serialport(ports(1,2),57600); % attach 2nd port
configureTerminator(app.PicoCom,"CR/LF"); % What Pico returns to trigger callback
app.PicoCom.ErrorOccurredFcn=@app.PicoError;
%-------------- later when INIT is done I add
configureCallback(app.PicoCom,"terminator",@app.PicoInput);
% to capture the async input, and that works
I don't understand what is the simplest form of (varargin)disp(varargin) that I can use to just let me know there is an error.
What I get is:
Warning: Error while executing listener
callback for Custom event. Source has been deleted:
Error using MouseOdor62/PicoError
Too many input arguments.
Error in
MouseOdor62>@(varargin)app.PicoError(varargin{:})
(line 460)
app.PicoCom.ErrorOccurredFcn=@app.PicoError;
^^^^^^^^^^^^^
Error in
matlabshared.transportlib.internal.client.GenericClient/errorCallbackFunction
(line 953)
obj.ErrorOccurredFcn(ex);
^^^^^^^^^^^^^^^^^^^^^^^^
And so on for a few pages...
Getting it to work in AD is not so easy as the M example given I suspect.
The official documentation doesn't give a function signature for ErrorOccurredFcn, so you'll have to try it yourself. I don't know how many input arguments I need, too, so I used varargin to accept any number of arguments. You can also use varargin, or disp varargin like I did and see how many inputs there are.
Thanks for the help. I hadn't understood if varargin was literal or something I have to substitute for. After experimenting it turns out this works:
app.PicoCom.ErrorOccurredFcn=@(~)app.PicoError
So it wants one to start but doesn't care about it. A little doc could go a long way.
So now that I trap the error when it occurs I can deal with it.

Sign in to comment.

More Answers (0)

Products

Release

R2024b

Asked:

on 21 Jan 2025

Commented:

on 27 Jan 2025

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!