Interfacing the Arduino with Matlab Using Events
12th February 2010
Opening a basic serial connection to the Arduino in Matlab is not difficult and is documented. Data is sent to the device using the fprintf() function and received using fscanf().
s = serial('COM3', 'BaudRate', 9600); fopen(s); fprintf(s, 'Hello World!'); line = fscanf(s); fclose(s);
If we have data continually being sent by our device there are two ways of capturing it. We can create a loop within Matlab to constantly check if any data has been received however this doesn’t seem like brilliant coding practise. Alternatively we can make use of the Matlab’s BytesAvailable event and read the input buffer only when data is received.
Unfortunately, unlike languages like C++, Matlab is only able to pass variables by value and not by reference. So if we create an array in our workspace to hold the received data, our callback function will be unable to update it. However in Matlab it is possible to nest functions within the body of another. The variables defined in the outer function will be accessible to the inner function.
% Calling the function myFunc will display the number 10. % Demonstrates that nested function has access to variables. function myFunc myVar = 10; innerFunc() function innerFunc myVar end end
The code to establish a serial connection is written into a Matlab function which also contain an array of all received data. The callback function of the BytesAvailable event is defined as a nested function and hence can add to the data array when new data is received. This allows us to perform analysis on the data in parallel to it being read.
The full sourcecode of my function is shown below:
% % SerialArduino % % Makes a serial connection via COM3 to the Arduino. Uses the % BytesAvailableFcn event to trigger a function to record data sent by % device. The recorded value and time are stored in the vectors values % and times respectively. % % Inputs: Time (in seconds) to listen to device. % Outputs: Times and Values % % Tested in Matlab 2009b % % Written 12 February 2010 % by Leo Kent % % http://leo.me.uk/ % function [times values] = SerialArduino (time) % Declare the vectors to hold time and value data. times = zeros(0,1); values = zeros(0,1); % Setup serial connection. ser = serial('COM3', 'BaudRate', 9600); % Attach the callback function. ser.BytesAvailableFcnMode = 'terminator'; ser.BytesAvailableFcn = @Callback; % Open the connection. fopen(ser); % Record the time at which we open the connection. start_time = tic; % This is the callback function for when bytes are availble. % It adds the received value to the values array and gets time. function Callback(obj, event) % Get the new values. v = str2double(fscanf(obj)); t = toc(start_time); % Update the vectors. values = [values; v]; times = [times; t]; end % Wait 5 seconds and close connection. time = 5; pause(time); % Close the serial port connection. fclose(ser); % Plot the output. plot(times, values); end