I am implementimg a BTC from matlab to the SHARC ADSP-21369 EZ-Kit to edit parameters for a simple 3-band-EQ during the board's runtime.
I have a class in MatLAB including the methods for accessing, writing and reading the BTC and i have initialized the channels in VisualDSP++ like shown in the getting started example.
My problem is as follows:
I transmit filter coefficients for a biquad filter, so the numerator-coefficients are 3x1 cell array, and the denominator-coeffs are a 2x1 cell array
If i try to send these values through the BTC, the BTC memory window shows me that only one single coefficient of the array is edited, the others get 0. A very interesting point is, that in the 3x1 cell array the 2nd coefficient is edited, the first and the third get zero.
I need to present this work on Monday, so quick solutions are appreciated.
The function code is below.
classdef accessBTC < handle
properties
numChannels = [];
isInitialized = 0; %Logical 0 or 1 to indicate if the class is instantiated to connect to the VisualDSP session
end
properties(SetAccess = private)
channelList = {}; % Array of channel objects
end
methods
function initialize(obj)
a = actxserver('VisualDSP.ADspApplication');
btcPlugin = a.PluginList.invoke('Item','BtcManager');
btcManager = btcPlugin.Open;
btcChannelList = btcManager.ChannelList(int16(0)); % Get the channel list in processor #0 (always INT16)
obj.numChannels = btcChannelList.Count;
disp(['Total Number of Channels: ', num2str(obj.numChannels)]);
% Create the BTC Channel interfaces
for i = 1: obj.numChannels
obj.channelList{i} = btcChannelList.invoke('Item',int32(i-1));
end
obj.isInitialized = 1;
% S=saveobj(obj);
end % End of Method: INITIALIZE
function outVal = read(obj,channelNum,width)
% Default width is 32; other possible values: 16, 8
% Channel num starts frm 0
if nargin ==2
width = 32;
end
widthStr = ['btcWidth',num2str(width)];
btcChan = obj.channelList{channelNum};
out_val = btcChan.Read(widthStr);
outVal = cell2mat(out_val);
end % End of Method: READ
function write(obj, channelNum, val)
% input val needs to be a scalar or a vector of int32 or in16 or
% int8 values
% Channel num starts frm 0
if nargin ~=3
error('WRITE method for accessBTC object needs 2 inputs.')
end
btcChan = obj.channelList{channelNum+1};
btcChan.Write('btcWidth32',num2cell(val));
end %End of Method: WRITE
function reset(obj)
obj.numChannels = [];
obj.isInitialized = 0;
obj.channelList = [];
end %End of Method: RESET
end
so if i sending for example these single arrays
num_1 = [1.324; -1.45; 0.83]
den_1 = [-1.45; 0.74]
i am getting in my BTC memory window as floating point
num_1 = [0.0000000; -1.45; 0.0000000]
den_1 = [-1.45; 0.0000000]
has anybody an idea how to fix this?
i will add some pictures now, that you can cisualize my problem:
matlab-debug
vdsp-debug
thanks a lot and best regards,
markus
Related
I am having difficulty in uploading an arbitrary waveform on to the DS345 function generator via the Instrument Control Toolbox in Matlab.
I have used the manual provided here (see page 3-8) to try to achieve this. The code I use is:
%% Instrument Control of DS345 Signal Generator
clear all
clc
COMtype = 'COM4';
% Find the a serial port object
obj1 = instrfind('Type', 'serial', 'Port', COMtype , 'Tag', '');
% Create the serial port object if it does not exist
% otherwise use the object that was found.
if isempty(obj1)
obj1 = serial(COMtype);
else
fclose(obj1);
obj1 = obj1(1);
end
N = 512;
Sum = 0;
number = 10;
data = zeros(number,1);
X = zeros(number,1);
Y = zeros(number,1);
obj1.OutputBufferSize = N;
fopen(obj1);
checkConnection =strcat( query(obj1,'*IDN?') );
if strcmp(checkConnection,'StanfordResearchSystems,DS345,43862,1.04') ~=1
disp(['Device Connection not working... Query msg ' ...
checkConnection])
else
disp(['Connection to ' checkConnection(25:29) ' established.'])
end
% Generating Function
for i = 1:number
X(i) = 1*i;
Y(i) = 0;
data(2*i-1) = i;
data(2*i) = 0; %8*i*(-1 + 2*(mod(i,2)));
Sum = Sum + (data(2*i-1) + data(2*i));
end
figure(1)
plot(X,Y)
grid minor
checksumdata = sum(data);
data(2*number+1) = checksumdata;
% size(data)
% convert into 16-bit binary array
data = int16(data);
dataBin = dec2bin(data,16);
checkLDWF = strcat(query(obj1,['LDWF? 1,' num2str(2*number)]));
if checkLDWF =='1'
disp('Ready to Download...')
end
pause(1)
disp('downloading...')
disp('sending DataBin...')
fwrite(obj1,dataBin,'short','async')
stopasync(obj1)
fclose(obj1);
In the code, I generate an array of straight lines and I want to upload an arbitrary vector waveform, which means using the LDWF command.
The manual suggests that I should send the 16-bit binary data followed by a checksum which is simply the sum of the data array.
The error I get is 'LOADING ERROR...' which implies that it has been waiting for 10s for the data stream and nothing has arrived. so it timeouts with the 'loading error'. Would appreciate any help/guidance possible.
I don't see anything wrong with your code.
Unfortunately I don't have access to Matlab right now.
In the meantime you might want to take a look at the method I proposed here.
It will allow you to see what is really on your port while you are sending data from Matlab to your function generator. This way you can be sure the data you are sending is correct and in particular if you are sending the right amount.
I'm trying to solve differential equation using the ode45 function. Consider the following code,
[t1,X2] = ode45(#(t,x)fun(t,x,C1,C2,C3,C4),t0,X01);
where parameters C1, C2, C3 and C4 are column vectors, which should be available to the function that ode45 is referring to (fun.m). I want the values to change after every iteration, so for example, at the beginning the entry of C1 I want in is C1(1), in the next iteration it's C1(2), etc.
How can I implement that?
You may have noticed that the official docs are not too helpful in this scenario (as they pretty much force you to use global variables - which is doable, but discouraged). Instead, I'll show you how this can be done with classes and function handles. Consider the following:
classdef SimpleQueue < handle
%SIMPLEQUEUE A simple FIFO data structure.
properties (Access = private)
data
position
end
methods (Access = public)
function obj = SimpleQueue(inputData)
%SIMPLEQUEUE Construct an instance of this class
obj.data = inputData;
rewind(obj);
end % constructor
function out = pop(obj, howMany)
%POP return the next howMany elements.
if nargin < 2
howMany = 1; % default amount of values to return
end
finalPosition = obj.position + howMany;
if finalPosition > numel(obj.data)
error('Too many elements requested!');
end
out = obj.data(obj.position + 1 : obj.position + howMany);
obj.position = finalPosition;
end % pop
function [] = rewind(obj)
%REWIND restarts the element tracking
% Subsequent calls to pop() shall return elements from the beginning.
obj.position = 0;
end % rewind
end % methods
end % classdef
How to use this? Simple:
C1q = SimpleQueue(C1);
C2q = SimpleQueue(C2);
C3q = SimpleQueue(C3);
C4q = SimpleQueue(C4);
[t1,X2] = ode45(#(t,x)fun(t,x,#C1q.pop,#C2q.pop,#C3q.pop,#C4q.pop),t0,X01);
As you can see, inside fun we use C1q() instead of C1.
I have a function that is part of an object that I have name TestData. Here are the properties and its constructor:
classdef TestData
properties
metaData = []; % stores meta data in Nx2 array
data = []; % stores data in PxQ array
colLabels = []; % labels columns
colUnits = []; % provides units
temp = []; % temporary to bypass setters while structuring data
end
methods
%% Constructor
function this = TestData(varargin) % Will take in a variable number of inputs
if (nargin == 0)
return;
end
if (nargin == 1 && ischar(varargin{1})) % Case of the input being a file (.txt, .s*p, etc..)
this = readDataFromFile(this, varargin{1});
return;
elseif (nargin == 4) % Case of the input being raw data. Note that the order matters.
this.metaData = varargin{1};
this.colLabels = varargin{2};
this.colUnits = varargin{3};
this.data = varargin{4};
return
else
error('Not enough input arguments.');
end
end
Now, let us say that I have 42 text files that I want to pass into the object. I have created a function for this called extractData that sifts through the data and finds a user input x-axis and y-axis. It does so by first calling a function readDataFromFile, which sets the property arrays that are outlined in the code above. It is a fairly long function and I won't include it for the time being, but I will say that I do know it is working.
The problem: I make an object of the class called myTestData and perform this operation in the CW, myTestData=myTestData.extractData('Tip Type','Tip S/N'). This will look for the Tip Type and Tip S/N. As you can see in the code, the type and S/N are in column 3 of the matrix. If the string is found, it takes the row it was found on, accesses column 3 of that row, and places that value into the temp array. In my case, the type is passive and the S/N is AM66191. It will write this to the temp array, but then on the second iteration of the for loop it will write something else over the first row and the passive and AM66191 will be displayed on the second row. It will do this all the way until the end, where on row 42 I will see the type and S/N, but all the other rows are just garbage. I have attached an image of what the temp array looks like after the second iteration of the for loop. Here is the code for the extractData function:
function this = extractData(this, xAxis, yAxis)
s = dir('*.txt'); % Gather all text files
disp(length(s))
for i=1:length(s) % Loop through and gather data until last element of strcuct
j = 1;
fid = s(i).name; % Open file in read-only mode
this = this.readDataFromFile(fid);
disp(fid)
x = this.metaData(find(contains(this.metaData(:,1), xAxis)),3);
this.temp(i,j) = x;
disp(this.temp(i,j))
j = j+1;
y = this.metaData(find(contains(this.metaData, yAxis)),3); %#ok<*FNDSB>
this.temp(i,j) = y;
disp(this.temp(i,j))
end %for
end %extractData
This is a followup to a previous issue I was having.
I want to give an offset to a signal then add some delay in it and calculate RMSE for that but when taking difference I am having the following issue:
I would like to ask the following things:
How can I solve the above problem?
Will anybody please explain in simple words what iddata does - because I have studied different portals including MATLAB but remained unable to get a good concept.
How can I store data of type iddata in cell for subtraction in the last part of my code?
Code with Problem :
drv(1)=load('123.mat');
t = drv(1).x;
ref = drv(1).y;
angle = drv(1).z;
Fs = 1000;
t1 =t';
ref1= ref';
d_data = iddata(ref1, t1, 1/Fs);
%% Add offset:
x = 1;
afterOffset1= {};
for i = 100:10:130
T = getTrend(d_data);
% <detrend data if needed>
T.InputOffset = i;
T.OutputOffset = i;
afterOffset = retrend(d_data,T);
afterOffset1{x,1}= afterOffset;
x= x+1 ;
end
%% Add delay:
y=20;
afterDelay1= {};
for i = 1:1:4
% delaySamples = i; % Must be a non-negative value
% afterDelay = iddata([NaN(delaySamples,1); d_data.OutputData],...
% [d_data.InputData; NaN(delaySamples,1)], 1/Fs);
afterOffset1{i}.Tstart = y;
afterDelay1{i,1}= afterOffset1{i};
y= y+10;
end
%% Plot:
n = size(afterDelay1,1);
figure();
for i=1:1:n
subplot(2,2,i);
plot(d_data);
hold all
plot(afterDelay1{i});
end
sig_diff = angle(1)-afterDelay1;
square_error(i,:) = (sig_diff(i)).^2;
mse(i,:)= mean(square_error(i));
rmse(i,:) = sqrt(mse(i));
sig_diff = d_data_1 - afterDelay; % <<<<<<<<<<<<<<<<<<<<<< Problem is here
% square_error = (sig_diff).^2;
% mse= mean(square_error);
% rmse = sqrt(mse);
end
You most likely want the OutputData attribute from the iddata object which is the output or y signal of your problem:
sig_diff = angle(1)-afterDelay1.OutputData;
Also note that this will give you a column vector, but your code later on assumes it's a row vector. You may want to transpose this data after you perform the above calculation before proceeding:
sig_diff = angle(1)-afterDelay1.OutputData;
sig_diff = sig_diff.';
In general, iddata is a function that creates an object that represents input and output time or frequency domain data. Take note that when you create an iddata object, the input matrix can potentially have multiple sources and so each column dictates a source. The same can be said for the output where each column dictates an output. Therefore, it is very important that you transpose your data prior to using this function to ensure that each signal is in a separate column, or just use a single column to represent one input / output.
Inside the object has a variety of attributes, including the sampling time or sampling frequency, the valid domain and range that the function takes on and finally accessing the input and output data. OutputData is one of these fields. I'd recommend looking at the documentation that talks about all of the attributes that you can access with iddata. OutputData is clearly defined here: https://www.mathworks.com/help/ident/ref/iddata.html
I have tried to generate a square pulsed clock. But it gives error. I tried this:
function pll( block)
setup(block);
function setup(block)
% Register number of ports
block.NumInputPorts = 1;
block.NumOutputPorts = 1;
% Override input port properties
block.InputPort(1).Dimensions = 1;
block.InputPort(1).DatatypeID = 8; % boolean
block.InputPort(1).Complexity = 'Real';
block.InputPort(1).DirectFeedthrough = false;
% Override output port properties
block.OutputPort(1).Dimensions = 1;
block.OutputPort(1).DatatypeID = 0; %double
block.OutputPort(1).Complexity = 'Real';
block.NumDialogPrms = 1;
block.DialogPrmsTunable = 0;
ts = 1/24000000'; %'
block.sample times= [ts 0];
block.SimStateCompliance = 'DefaultSimState'
function Outputs(block)
t = [0:1/(24000000):0.000001];
l = 0.1*exp(-6);
c = 220*exp(-9) + 60*exp(-9);
f = 1/(2*pi*sqrt(l*c));
block.OutputPort(1).Data = square(2*pi*f*t);
function Terminate(block)
But it gives me the error
"Error evaluating registered method 'Outputs' of M-S-Function 'pll' in
'untitled/Level-2 M-file S-Function'. Invalid assignment in
'untitled/Level-2 M-file S-Function': attempt to assign a vector of
width 24001 to a vector of width 1."
the error indicates on the line
block.OutputPort(1).Data = square(2*pi*f*t);
so what can be done to overcome this error?
It seems from your example that you're not really familiar with the way Simulink works. At each time step, each block in a Simulink model outputs a value (i.e the block's output value) corresponding to the current simulation time. In your case, within the block.Output function you are trying to output all time points at every simulation time step.
It appears that what you really want is to replace
t = [0:1/(24000000):0.000001];
with
t = block.CurrentTime;
And replace
block.OutputPort(1).Data = square(2*pi*f*t);
with
block.OutputPort(1).Data = sign(sin(2*pi*f*t));
Also, some other things to consider:
you don't seem to be registering the block's output method using:
block.RegBlockMethod('Outputs',#Output);
Why have you defined the block to have an input when it doesn't seem to require one?
Why are you doing this in an S-Function when a From Workspace block (or one of the many other ways to get data into a model) would seem to make more sense?