- Use the “tic” and “toc” functions: Instead of relying solely on the timer object's fixed rate, you can use the tic and toc functions to measure the elapsed time within each iteration. Internally, tic and toc do not rely on the operating system for timing. Instead, they use the high-resolution performance counter of the CPU to measure the elapsed time. It typically has a much higher resolution than the system clock used by the operating system. Here's an example:
Timer object is triggering much faster than specified?
5 ビュー (過去 30 日間)
古いコメントを表示
Hello, I have written some code to read modbus registers at a frequency of 2 Hz using a timer object, but when I examine the sampling intervals recorded, they vary from 0.05 to 0.27 s, with a median of 0.08s. Could you please help me to understand why and how to fix this? If there is a cleaner way to write this functionality, I would appreciate your comments about this too.
I have included the whole code below, but think these 3 lines are the most important for this issue:
samplingPeriod=0.5; %sampling interval in seconds
tim=timer('ExecutionMode','fixedRate','BusyMode','drop','Period',samplingPeriod,'TasksToExecute',numReadings,'StopFcn',@deltim,'TimerFcn',{@getreading},'Name','mTimer');
start(tim)
%To stop part way through, type stop(tim) into the command line
%% User definable variables
IP1='192.168.1.1'; %IP address of 1st instrument to interogate
FileNameO = "ABB_31AUG23_NoT2corr_2.csv";
measParamNamesO = ["meas1","T1","T2","Out2", "P1","Out3"];%parameter names to measure
measParamAddressO = [1, 401, 451, 453, 501, 458]; %parameter modbus addresses. Must be input register type.
runTime=4*24*60*60; %Total measuring time in seconds
samplingPeriod=0.5; %sampling interval in seconds
numReadings=round(runTime/samplingPeriod +1); %number of readings to take
%% define preset variables
format longG;
global reading
global k
global measParamNames
global measParamNum
global measParamAddress
global m1
global measParamTypes
global FileName
FileName = FileNameO;
measParamNames = measParamNamesO;
measParamAddress = measParamAddressO;
measParamNum = length(measParamNames);
measParamTypes = strings(1,measParamNum);
measParamTypes(:,:) = "single";
reading=table('VariableNames',["time","sTime",measParamNames],'VariableTypes',["double","double",measParamTypes],'Size',[numReadings,2 + measParamNum]);
k=1;
%% setup Modbus connection
% Create a Modbus Object.
m1 = modbus('tcpip', IP1);
m1.Timeout = 1;
%% Setup timer
tim=timer('ExecutionMode','fixedRate','BusyMode','drop','Period',samplingPeriod,'TasksToExecute',numReadings,'StopFcn',@deltim,'TimerFcn',{@getreading},'Name','mTimer');
start(tim)
function getreading(mTimer,~)
global reading
global k
global measParamNum
global measParamAddress
global m1
try
reading.time(k)=now;
for i=1:measParamNum
reading{k,i+2} = read(m1,'inputregs', measParamAddress(i), 1, 1, 'single');
end
k=k+1;
catch
fprintf('Error in getreading function %s\n', datestr(now,'HH:MM:SS.FFF'));
end
end
function deltim(mTimer,~)
%% Finishing func
global reading
global k
global FileName
reading(k:end,:)=[];
reading.sTime=(reading.time(1:end)-reading.time(1))*24*3600;
writetable(reading,FileName);
hold off
hold on
plot(reading.sTime,reading.meas1)
xlabel("Time (s)");
ylabel("Measured Value (%)")
hold off
figure()
histogram(reading.sTime(2:end)-reading.sTime(1:end-1))
title('Sampling period histogram');
xlabel('Sampling period (s)');
ylabel('Number of instances');
delete(mTimer);%clear timer object
clear m1 k runTime period numReadings IP1 measParamTypes measParamNum measParamNamesO measParamNames measParamAddressO measParamAddress % Clear the Modbus Object created.
disp('Logging has finished')
end
0 件のコメント
採用された回答
Varun
2023 年 9 月 4 日
編集済み: Varun
2023 年 9 月 4 日
Hi Chirs,
I understand that you are attempting to read “modbus” registers at a frequency of 2 Hz using a timer object. However, you mentioned that the recorded sampling intervals vary and are not consistent with the desired sampling period of 0.5 seconds.
The MATLAB timer object is implemented using a combination of MATLAB's event-driven architecture and the underlying operating system's timer mechanisms. It internally utilizes the operating system's timer mechanisms to trigger timer events. However, the actual timing may be affected by factors such as system load, other tasks running concurrently, handling timer queuing conflicts, and the underlying hardware capabilities. Avoid using timer objects for real-time applications.
To address this issue and achieve more accurate timing, you can consider the following suggestions:
desiredPeriod = 0.5; % desired sampling interval in seconds
numReadings = 10; % number of readings to take
tic;
for i = 1:numReadings
% Perform your modbus register reading here
% Calculate the elapsed time
elapsedTime = toc;
% Wait for the remaining time to achieve the desired period
remainingTime = desiredPeriod - elapsedTime;
if remainingTime > 0
pause(remainingTime);
end
% Reset the timer
tic;
end
2. Consider using the timer object's “StartDelay” property: You can set the “StartDelay” property of the timer object to delay the start of the timer execution, allowing for a more accurate initial timing. This can help compensate for any initialization or setup delays.
Please refer the following pages to learn more on the Limitations of “timer” object and Handling Timer Queuing Conflicts:
その他の回答 (0 件)
参考
カテゴリ
Help Center および File Exchange で Whos についてさらに検索
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!