How can I get an output to Matlab command from generated code (Matlab system object)

5 views (last 30 days)
I have created a matlab system object that is called in a simulink program. I am trying to debug it by getting values in the Matlab command window or the simulink diagnostic window.
I am trying to get "obj.device" values to see if the call to my C code function "i2c_setup" works.
I have tried to do with coder.extrinsic('sprintf') and sprintf('The device ID is: %d ', obj.device);
but without success.
Do you have any suggestion ?
classdef I2C_read_custom < realtime.internal.SourceSampleTime & ...
coder.ExternalDependency
%#codegen
%#ok<*EMCA>
properties
% Public, tunable properties.
device = 0;
end
...
...
methods (Access=protected)
function setupImpl(obj) %#ok<MANU>
coder.extrinsic('sprintf')
if isempty(coder.target)
% Place simulation setup code here
else
% Call C-function implementing device initialization: int8_T i2c_setup(const uint8_T devId);
coder.cinclude('I2C_read2.h');
obj.device = coder.ceval('i2c_setup', uint8(hex2dec("0x34"))); % Slave address is hardcoded
% obj.device = coder.ceval('i2c_setup_V2'); % Slave address is hardcoded
sprintf('The device ID is: %d ', obj.device);
end
end
...
...
  2 Comments
Jonas
Jonas on 16 Feb 2023
why do u use a system object for that?
if you create the obejct using
myObj=I2C_read_custom();
you shoud be able to access the property device by
myObj.device
Sylvain
Sylvain on 16 Feb 2023
the system object is used in a simulink program that is then deployed on a Raspberry Pi. The myObj.device will be called in the stepImpl(obj), see below. I want to access myObj.device value for debugging:
...
...
sprintf('The device ID is: %d ', obj.device);
end
end
function y = stepImpl(obj) %#ok<MANU>
y = uint8(zeros(32,1));
if isempty(coder.target)
% Place simulation output code here
y = [1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32]';
else
% Call C-function implementing device output: uint8_T readBytes(uint8_T file,uint8_T *buffer,uint8_T buffer_length);
coder.ceval('readBytes',obj.device,coder.ref(y),32);
end
end
below the C code that return negative values if error occurs
int8_T i2c_setup(const uint8_T devId){
uint8_T fd=0 ;
if ((fd = open ("/dev/i2c-1", O_RDWR)) < 0)
return -1;
if (ioctl (fd, I2C_SLAVE, devId) < 0)
return -2;
return fd ;
}

Sign in to comment.

Answers (2)

Dinesh
Dinesh on 4 May 2023
Hi Sylvian,
To display values in the MATLAB command window or the Simulink diagnostic window during simulation, you can use the "disp" function with the "coder.extrinsic" command. Here's how you can modify your code to display the device ID:
  1. Inside the "setupImpl" method, add "coder.extrinsic('disp')" to declare "disp" as an extrinsic function. This allows you to call the "disp" function from within the generated code.
  2. Replace the "sprintf" line with the following code to display the device ID:
deviceIDStr = sprintf('The device ID is: %d', obj.device);
coder.extrinsic('disp');
disp(deviceIDStr);
Here's the modified "setupImpl" function with the changes:
methods (Access=protected)
function setupImpl(obj) %#ok<MANU>
coder.extrinsic('sprintf')
coder.extrinsic('disp')
if isempty(coder.target)
% Place simulation setup code here
else
% Call C-function implementing device initialization: int8_T i2c_setup(const uint8_T devId);
coder.cinclude('I2C_read2.h');
obj.device = coder.ceval('i2c_setup', uint8(hex2dec("0x34"))); % Slave address is hardcoded
% obj.device = coder.ceval('i2c_setup_V2'); % Slave address is hardcoded
deviceIDStr = sprintf('The device ID is: %d', obj.device);
disp(deviceIDStr);
end
end
end
I believe that this will resolve your issue. Let me know if you have questions.
  3 Comments
Sylvain
Sylvain on 6 May 2023
ok, I will have a try, when I have some time in my hands.
I am not sure what @Walter Roberson's comment mean for me. I am intending to use this functionality with the tune and monitor mode.
Walter Roberson
Walter Roberson on 6 May 2023
https://www.mathworks.com/help/simulink/slref/coder.extrinsic.html?s_tid=doc_ta
During standalone code generation, the code generator attempts to determine whether an extrinsic function only has a side effect (for example, by displaying a plot) or whether it affects the output of the function in which it is called (for example, by returning a value to an output variable). If there is no change to the output, the code generator proceeds with code generation, but excludes the extrinsic function from the generated code. Otherwise, the code generator produces a compilation error.
Your sprintf and disp would potentially be discovered as only being for side effects (display on the screen) and if so the call to them would simply be omitted during code generation, without error. If Coder cannot figure out that it is only for side effect then Coder will error.

Sign in to comment.


Walter Roberson
Walter Roberson on 6 May 2023
If want to emit debugging messages in a deployed executable, you have three choices:
  • you can make them into signals that are logged; Or
  • you can make them into signals that are transmitted to a device; Or
  • you can use coder.ceval() or similar to call outside routines to do the output. Hardware specific routines, or at the very least printf() to standard output and hope standard output is connected to an accessible console. With Raspberry chances are good that you could fopen() and fprintf(), maybe even to a serial port; with Arduino I don't believe fopen is available (no file system) but perhaps fopen of a device is possible.

Categories

Find more on Raspberry Pi Hardware in Help Center and File Exchange

Products


Release

R2022b

Community Treasure Hunt

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

Start Hunting!