我想在纯Simulink模型中实现一个非常巨大的(10^6元素 - 固定大小)循环缓冲区(没有其他工具箱,没有S-Function)。Simulink中的循环缓冲区
在某些时候,我需要阅读一些元素(任何地方,不只是开始或结束)。
下面的解决方案我无法使用:
- “队列块”或“缓冲块”(我没有信号处理工具箱提供)
- “离散延迟”(我需要一个休缓冲区不会将10^6延迟到模型)
- “SIM事件”(我需要从这个模型生成代码)
的“S-功能”我试图不但是,我正在寻找替代解决方案。
你知道甚么?
我想在纯Simulink模型中实现一个非常巨大的(10^6元素 - 固定大小)循环缓冲区(没有其他工具箱,没有S-Function)。Simulink中的循环缓冲区
在某些时候,我需要阅读一些元素(任何地方,不只是开始或结束)。
下面的解决方案我无法使用:
的“S-功能”我试图不但是,我正在寻找替代解决方案。
你知道甚么?
首先,让我恭维你对纯粹的Simulink的追求!这很有可能,但是,Mathworks代码生成器不处理此用例。这是非常草率的,并创建整个队列的缓冲副本。这里有一个例子:
然后,看看一些代码。哎呀!
/* Model output function */
static void queue_output(int_T tid)
{
{
real_T rtb_MathFunction;
/* DataStoreRead: '<S1>/Data Store Read' */
memcpy((void *)(&queue_B.DataStoreRead[0]), (void *)(&queue_DWork.A[0]),
100000U * sizeof(uint16_T));
/* Outport: '<Root>/Out1' incorporates:
* DataStoreRead: '<S1>/Data Store Read1'
* Selector: '<S1>/Selector'
*/
queue_Y.Out1 = queue_B.DataStoreRead[(int32_T)queue_DWork.idx];
/* If: '<Root>/If' incorporates:
* ActionPort: '<S2>/Action Port'
* Constant: '<Root>/Constant'
* SubSystem: '<Root>/WriteToQueue'
*/
if (queue_P.Constant_Value > 0.0) {
/* DataStoreRead: '<S2>/Data Store Read3' */
memcpy((void *)(&queue_B.Assignment[0]), (void *)(&queue_DWork.A[0]),
100000U * sizeof(uint16_T));
/* Math: '<S2>/Math Function' incorporates:
* Constant: '<S2>/Constant1'
* Constant: '<S3>/FixPt Constant'
* DataStoreRead: '<S2>/Data Store Read2'
* Sum: '<S3>/FixPt Sum1'
*/
rtb_MathFunction = rt_mod_snf(queue_DWork.idx +
queue_P.FixPtConstant_Value, queue_P.Constant1_Value);
/* Assignment: '<S2>/Assignment' incorporates:
* Constant: '<S2>/Constant'
*/
queue_B.Assignment[(int32_T)rtb_MathFunction] = queue_P.Constant_Value_h;
/* DataStoreWrite: '<S2>/Data Store Write' */
memcpy((void *)(&queue_DWork.A[0]), (void *)(&queue_B.Assignment[0]),
100000U * sizeof(uint16_T));
/* DataStoreWrite: '<S2>/Data Store Write1' */
queue_DWork.idx = rtb_MathFunction;
}
}
Memcpy 10000 uint16's every loop!在Mathworks以稳健的方式解决这个问题之前,这里是一个initial attempt that requires hard coding indices,S-函数是唯一的方法。
一个简单的循环缓冲器可以用MATLAB FCN块创建:
function y = CircularBuffer(u, N)
%#codegen
% Function to implement a simple N element circular buffer
% Define the internal buffer variable as persistent so
% so that it will maintain its values from one time step
% to the next.
persistent buffer writeIdx
% Initialize the buffer the first time through
if isempty(buffer)
% Initialize the buffer
buffer = zeros(N,1);
writeIdx = 1;
else
buffer(writeIdx) = u;
if (writeIdx == N)
writeIdx = 1;
else
writeIdx = writeIdx+1;
end
end
% Output the buffer
y = buffer;
这完全支持代码生成(并且不做的memcpy)。
如果需要,您可以很容易地更改缓冲区的数据类型,但是如果您希望在输入和输出信号上具有不同的采样率(与信号处理模块集中的缓冲区一样),则需要恢复使用S功能。
为什么不使用MATLAB功能块并将您的缓冲区声明为MATLAB代码中的永久数据? – Navan
据我所知,Matlab功能模块在旧版的Matlab/Simulink版本中(2011年之前)不可用。我正在寻找一种向下兼容的方法。对于只有更新的版本,我会采用Matlab功能块(巫婆Matlab编码器)和Phil Goddard发布的解决方案。 – ToBe