BytesAvailableFcn is not triggered when serial data does not contain a terminator, but while loop works (even with serial options ,'BytesAvailableFcnMode','byte','InputBufferSize',1,'Terminator','')
Show older comments
I have a problem that the BytesAvailableFcn is not triggered when serial data does not contain a terminator. I set the serial options
- 'BytesAvailableFcnMode','byte',
- 'InputBufferSize',1,
- 'Terminator',''
so that is should not require a terminator, and run the callback as soon as a single byte is available (please tell me if I missed something here...).
A while loop checking for BytesAvailable will properly get the data.
I tried different callback functions, including @instrcallback.
Please see the example below. I'm using an Arduino Uno to generate the serial data.
When using Serial.println on the arduino (e.g., the AnalogReadSerial official example sketch), we can use the default serial settings (option 1 in my program) and both options A (while loop) and B (callback) will work.
When using Serial.print on the arduino (e.g., the SerialCallResponse official example sketch), we should not wait for a terminator (option 2 in my program) and option A (while loop) still works, but option B (callback) won't.
Setting the BytesAvailableFcn in the serial(...) command or setting it before fopen does not make any difference.
Tested with MATLAB 2017b and 2018a on Windows10.
P.S. I know MATLAB has an add-on for arduino, but my problem is with data received over the serial port, not necessarily from an arduino.
% Try this with Arduino and
% * AnalogReadSerial (File->Examples->Basics) sketch
% Note: Arduino will send data terminated with a new-line character
% --> "default" settings work with both while loop and callback function
% * SerialCallResponse (File->Examples->Communication) sketch
% Note: Arduino will send "A" without new-line termination every 0.3s
% --> "single byte" reception works with while, but not with callback...
clear
port='COM4';
choice=input('Choose [1] for default (new-line terminated) or [2] for single byte (non-terminated) data reception.>');
switch(choice)
case 1
hCOM=serial(port,'BAUD',9600); % default settings with terminator
case 2
hCOM=serial(port,'BAUD',9600,'BytesAvailableFcnMode','byte','InputBufferSize',1,'Terminator','');
end
choice=input('Choose [A] for while loop or [B] for callback function.>','s');
fopen(hCOM);
switch(choice)
case 'A'
tic;
while(toc<5)
if hCOM.BytesAvailable
disp(fgets(hCOM)); % or % data=fgetl(hCOM); % or % data=fscanf(hCOM);
else
pause(.001); % wait a little (otherwise CPU will go to 100%)
end
end
case 'B'
hCOM.BytesAvailableFcn = 'disp(fgets(hCOM));'; % set the callback function.
% hCOM.BytesAvailableFcn = @instrcallback;
% hCOM.BytesAvailableFcn = @(src, event) disp(fscanf(src, '%s')); % set the callback function.
pause(5)
end
fclose(hCOM);
6 Comments
Sarabjit Kheberi
on 17 Aug 2018
Can you try setting the property 'BytesAvailableFcnCount' to 1? This property Specifies the number of bytes that must be available in the input buffer to generate a bytes-available event. The default value for the property is 48.
In the current example, it looks like the callback function is waiting for 48 bytes of data to be available before it gets triggered.
Walter Roberson
on 17 Aug 2018
Right. Remember that it takes time for the BytesAvailableFcn to be called and the user to pull the data out, and in the meantime data can still be coming in. BufferSize reflects how much buffer space might be needed at peak to store data that has been read in and notified together with any additional data that might have accumulated since then. BufferSize does not control the point at which the notification is to occur.
Daiichiro Matsunaga
on 20 Aug 2018
Edited: Daiichiro Matsunaga
on 20 Aug 2018
Walter Roberson
on 20 Aug 2018
Edited: Walter Roberson
on 20 Aug 2018
That line about read operation being terminated is talking about one of the ways that it knows to end a read: when the buffer is full. There are other ways it can know to terminate the read: due to a timeout, or due to the fact that it has read in as many bytes as you asked for when you used fread()
When you are using Byte mode, you should always be using fread() and asking for the size you want. fgetl() and fgets() and fscanf() should only be used when you are using Terminator mode.
Daiichiro Matsunaga
on 20 Aug 2018
Daiichiro Matsunaga
on 20 Aug 2018
Answers (0)
Categories
Find more on MATLAB Support Package for Arduino Hardware in Help Center and File Exchange
Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!