Clear Filters
Clear Filters

HC-SR04 Measures Really Slow in Simulink with Arduino IO(Legacy)

3 views (last 30 days)
Hello everyone,
I'm trying to measure some distance with HC-SR04 on Matlab Simulink. And I want to do it by creating my own custom block on Arduino IO Package in Simulink.
What I did so far is,
Modified Adioes.m as below; Included these lines at the beginning of the code
#include <NewPing.h>
NewPing sonar(12, 11, 200);[/code]
Also added these lines to the switch case:
[code]case 400:
int distance;
delay(50); // Wait 50ms between pings (about 20 pings/sec). 29ms should be the
//I also tried without delay(50) line.
shortest delay between pings.
distance = sonar.ping_cm();
s=-1; /* we are done with the aux function so -1 */
I uploaded this code successfully to my Uno then added these lines to Arduino.m.
% Ultrasound
function val=Ultrasound(a)
% roundTrip(a,byte); sends something to the arduino and back
% The first argument, a, is the arduino object.
% The second argument, byte, is any integer from 0 to 255.
% The output is the same byte, which was received from the
% arduino and sent back along the serial connection unchanged.
% This is provided as an example for people that want to add
% their own code to this arduino class (the section handling
% this dummy function in the pde file is handled as "case 400:",
% one might take the parameter, perform some potentially useful
% operation, and then send any result back via serial connection).
% Examples:
% roundTrip(a,48); % sends '48' to the arduino and back.
% a.roundTrip(53); % sends '53' to the arduino and back.
%%%%%%%%%%%%%%%%%%%%%%%%%ARGUMENT CHECKING %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% check arguments if a.chkp is true
% if a.chkp,
% % check nargin
% if nargin~=2,
% error('Function must have one argument');
% end
% % check argument (must be a byte)
% errstr=arduino.checknum(byte,'byte',0:255);
% if ~isempty(errstr), error(errstr); end
% end
% % check a.aser for validity if a.chks is true
% if a.chks,
% errstr=arduino.checkser(a.aser,'valid');
% if ~isempty(errstr), error(errstr); end
% end
%%%%%%%%%%%%%%%%%%%%%%%%%SEND ARGUMENT ALONG %%%%%%%%%%%%%%%%%%%%%%%%%%%%%
if strcmpi(get(a.aser,'Port'),'DEMO'),
% handle demo mode
% minimum analog output delay
% sets the output
% check a.aser for openness if a.chks is true
if a.chks,
if ~isempty(errstr), error(errstr); end
% send mode and byte
% get value back
end % Ultrasound
the line fwrite(a.aser,[88],'uchar'); simply sends "88" to Arduino via Serial and the number 88 triggers a case which is "400" in our case. After Arduino execute the "case 400" it sends the distance from sonar.ping_cm() line.
So lastly I create a msfunction to call with a block on simulink. Here it is the code for msfunction:
function msfun_arduino_ultrasound(block)
% Level-2 M-File S-Functions, Copyright 2014, The MathWorks, Inc.
% instance variables
myArduino = [];
myPin = 0;
function setup(block)
% Register the number of ports.
block.NumInputPorts = 0;
block.NumOutputPorts = 1;
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).SamplingMode = 'sample';
% Set up the states
block.NumContStates = 0;
block.NumDworks = 0;
% Register the parameters.
block.NumDialogPrms = 3; % arduinoVar, arduinoPin, Sample Time
block.DialogPrmsTunable = {'Nontunable', 'Nontunable', 'Nontunable'};
% Set the sample time
block.SampleTimes = [block.DialogPrm(3).Data 0];
block.SetAccelRunOnTLC(false); % run block in interpreted mode even w/ Acceleration
block.SimStateCompliance = 'DefaultSimState';
% the ArduinoIO Setup block uses the Start method to initialize the arduino
% connection; by using InitConditions, we ensure that we don't access
% the variable before it is created
block.RegBlockMethod('CheckParameters', @CheckPrms); % called during update diagram
% block.RegBlockMethod('Start', @Start); % called first
block.RegBlockMethod('PostPropagationSetup', @PostPropSetup);
block.RegBlockMethod('InitializeConditions', @InitConditions); % called second
block.RegBlockMethod('Outputs', @Output); % called first in sim loop
% block.RegBlockMethod('Update', @Update); % called second in sim loop
block.RegBlockMethod('Terminate', @Terminate);
function CheckPrms(block)
validateattributes(block.DialogPrm(1).Data, {'char'}, {'nonempty'}); % Name of arduino instance
validateattributes(block.DialogPrm(2).Data, {'numeric'}, {'real', 'scalar', 'nonnegative'}); % pin
errstr=arduino.checknum(block.DialogPrm(2).Data,'pin number',2:69);
if ~isempty(errstr), disp(errstr); error(errstr); end
validateattributes(block.DialogPrm(3).Data, {'numeric'}, {'real', 'scalar', 'nonzero'}); % sample time
catch %#ok<CTCH>
error('Simulink:ArduinoIO:invalidParameter', 'Invalid value for a mask parameter');
function PostPropSetup(block)
st = block.SampleTimes;
if st(1) == 0
error('The ArduinoIO library blocks can only handle discrete sample times');
function InitConditions(block)
% fprintf('%s: InitConditions\n', getfullname(block.BlockHandle));
customData = getSetupBlockUserData(bdroot(block.BlockHandle), block.DialogPrm(1).Data);
myArduino = customData('arduinoHandle');
%myPin = block.DialogPrm(2).Data;
%myArduino.pinMode(myPin, 'input');
function Output(block)
% fprintf('%s: Output\n', getfullname(block.BlockHandle));
duration = myArduino.Ultrasound();
if isempty(duration )
duration = 0;
block.OutputPort(1).Data = duration ;
function Terminate(block) %#ok<INUSD>
% The ArduinoIO Setup block handles cleanup of myArduino
You can see the result in the picture below. I get correct measurements, however, to get the distance measurement for 1.6 seconds I need to wait 10-15 seconds. So it's not real time anymore. There is a huge delay. What is your opinion about this delay?
  1 Comment
AC on 19 Mar 2019
Did you fix this problem ? I also want to measuse distance with HC-SR04 sensor on Simulink..

Sign in to comment.

Answers (1)

Muharrem Akkaya
Muharrem Akkaya on 19 Mar 2019
Unfortunately, I wasn't able to use HC-SR04 sensor properly in Simulink by using Arduino IO(Legacy).
I believe it's not possible or at least not an easy task to use HC-SR04 with IO(Legacy). Because the sensor sends Pulses and wait for the Response during operation so it blocks the communication between Arduino and Simulink.
I believe you can use Matlab Support package with HC-SR04 Add-On Library for Arduino to get data from the sensor. Then you can write an S-Function to pass your data to your Simulink model. However, using an Infrared Proximity Sensor would be less painful if you are okay with the price.
Good Luck! and Please share your results if you achieve your goal.


Find more on Arduino Hardware in Help Center and File Exchange




Community Treasure Hunt

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

Start Hunting!