New serial communication with serialport()
    6 Ansichten (letzte 30 Tage)
  
       Ältere Kommentare anzeigen
    
    Julian Schmid
      
 am 18 Sep. 2019
  
    
    
    
    
    Kommentiert: Guillaume
      
      
 am 19 Sep. 2019
            Hi everyone,
I've updated to the new Release 2019b  and found that the serial communication was completly updated. Before the update, I used a tag to find the serial port object in other functions so that I could divide the functions into several parts: setup of serial connection (open/close), sending input to the device (from different functions) and reading and processing the device response. But now, I don't see a way to access the serialport object created in the beginning in other functions.
What I want to accomplish is an interface to a arduino flushed with GRBL. Therefore, I need a way to constantly (every 0.5 seconds or so) updating the device status by querring a special real_time command which returns almost instantly the current instrument state (even while there is an other command beeing processed). In addition, I have to send commands, which usually give a positive respond as soon as their execution started. 
So can I use the new configureCallback to change the callback function depending on whether I want to get the current device status or the status of my current command?
I was thinking about a buffer to store the commands send to the device and the response from the device so that I can keep track. The validation would occur as soon as we have a complete set (read and write operation done). Since the real time command is always executed and the response follows immediatly (before the response for other commands) I would place it on top of the buffer.
Thank you for your time!
function TestSerialCommunication()
    % set up serial connection for the first time
    sCon = serialport('COM3',115200);
    configureTerminator(sCon,'CR/LF')
    pause(2) % wait for instrument to get started
    % flush buffer; remove instrument welcome message
    flush(sCon);
    % send homing cycle command in order to disable the alarm state
    writeline(sCon,'$H')
    % wait for 10 seconds to finish the homing cycle command
    pause(10);
    % device response is 'ok' as soon as homing cycle has been finished
    count = sCon.NumBytesAvailable;
    homingCycleStatus = read(sCon,count,'char');
    disp(homingCycleStatus)
    % configure timer object so that we can constantly update the instrument status
    objTimer = timer('Tag','timerDeviceState',...
        'BusyMode','drop',...
        'ExecutionMode','fixedSpacing',...
        'TimerFcn',@SendStatusRequest,...
        'Period',0.5);
    % now start timer
    start(objTimer);
    % for testing purposes we move the device around while we constantly
    % update the device status via timer 
    % configure callback for movement commands
    configureCallback(sCon,'terminator',@ResponseToMovement)
    for n = 1:10
        input = strcat('Y',num2str(n));
        writeline(sCon,input) % tell the instrument to move 1 step on y-axis
    end
    % because there is no 'Tag' property for serialport() this function has
    % to be a nested function of the main function which created the
    % serialport object
    function SendStatusRequest(~,~)
        configureTerminator(sCon,'CR') % third argument is writterm
        configureCallback(sCon,"terminator",@ResponseMaschineState)
        % send status request to the instrument
        write(sCon,'?','char')
    end
end
% read the response from the device which was triggered by sending a status
% request command
function ResponseMaschineState(s,~)
    % this function is only similar to the ResponseToMovement function for
    % testing purpose. In reality they output is different and has to be
    % processed in a different manner.
    count = s.NumBytesAvailable;
    if count > 0
        data = read(s,count,'char');
        disp(data)
    end
end
% read the response from the device for the movement command
function ResponseToMovement(s,~)
    % date = dataInfo.AbsTime;
    count = s.NumBytesAvailable;
    if count > 0
        data = read(s,count,'char');
        disp(data)
    end
end
0 Kommentare
Akzeptierte Antwort
  Guillaume
      
      
 am 18 Sep. 2019
        But now, I don't see a way to access the serialport object created in the beginning in other functions
You just have to pass the serial port object to your callback. One way:
    objTimer = timer('Tag','timerDeviceState',...
        'BusyMode','drop',...
        'ExecutionMode','fixedSpacing',...
        'TimerFcn',@(~, ~) SendStatusRequest(sCon), ...  %just discard source and eventarg since you don't use them
        'Period',0.5);
with non-nested function:
function SendStatusRequest(sCon)
configureTerminator(sCon,'CR') % third argument is writterm
configureCallback(sCon,"terminator",@ResponseMaschineState)
% send status request to the instrument
write(sCon,'?','char')
end
With the 2nd part of your question, is there any reason to handle data sent/data received separately? If you send a command, don't you have to wait for the full response before sending the next one? If so, there's no reason to do the communication asynchronously. 
If you need to do asynchronous communication, then indeed sent and received buffer would be a way to handle this.
2 Kommentare
  Guillaume
      
      
 am 19 Sep. 2019
				You can pass the serial port object to all functions that need to call SendToInstrument so that in turn they can pass it to the function. You could also use a persistent variable indeed, this wouldn't be the way I'd do it but it's certainly an option. Or you could wrap the code in a class, that may be what I'd do. There are many ways to achieve the same.
You certainly don't want while loops in a UI, so yes, you want to use the serial port callback. I'm not too clear on the full details of your application, can you send another command before receiving the full reply of the previous one? If not, you would have a can't send flag that would be set once you've sent a command and unset by the callback once the full reply has been received. If the flag is set, don't allow sending a new command. As to how you store flag, received data, etc. it's up to you. If you're using GUIDE the handle variable is probably best. A structure in userData another. Or again wrap it all in class. If you're using App designer, you would already have the class wrapper.
Weitere Antworten (0)
Siehe auch
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!
