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.
Related
Good evening, May I please get advice with the following Matlab code? Here it is:
%% CLEAR ALL
close all
clear all
clc
%% LOAD MODEL AND LHC FILE
tic %start the clock
idx=1;
model = 'PG_PN_basic_rev1'; %This is the simulink file you wish to run.
load_system(model);
load 'LHC_input.mat' %Call in the file created by LHC_Final.m
LHC = (LHC1_input);
k_dc = LHC((1:5),1);
k_r = LHC((1:5),2);
a_1 = LHC((1:5),3);
b_1 = LHC((1:5),4);
Kg_PG = LHC((1:5),5);
Kg_PN = LHC((1:5),6);
for i = length(k_dc):-1:1
in(i) = Simulink.SimulationInput('PG_PN_basic_rev1');
in(i) = in(i).setVariable('k_dc',k_dc(i));
for j = length(k_r):-1:1
in(j) = in(j).setVariable('k_r',k_r(j));
for k = length(a_1):-1:1
in(k) = in(k).setVariable('a_1',a_1(k));
for l = length(b_1):-1:1
in(l) = in(l).setVariable('b_1',b_1(l));
for m = length(Kg_PG):-1:1
in(m) = in(m).setVariable('Kg_PG',Kg_PG(m));
for n = length(Kg_PN):-1:1
in(n) = in(n).setVariable('Kg_PN',Kg_PN(n));
end
end
end
end
end
end
out = parsim(in, 'ShowProgress', 'on');
% eval(['PN_batch', int2str(idx),' =PN;']);
% data = eval(['PN_batch', int2str(idx)]);
% a{idx} = data;
% idx=idx+1;
% run = idx
timeElapsed = toc %How long did you code run for?
I wish to be able to generate an output file per parsim run (PN_batch1, PN_batch2,...etc.). However, the data often falls under just 1 output, and isn't divided up into readable workspace objects that I can read later with another script. Any advice would be greatly appreciated. Thank you.
out is a vector of length equal to the number of simulations with the data of a simulation stored in each entry. If you have to workspace blocks in your model, you can access that data per simulation using out(10).NameOftoWorkspaceData, in case you want to get the data of the 10th simulation. More info on the out variable can be found here on the Mathworks site.
Tip: run the model and check out the variable out, then you can explore its structure
I'm trying to plot in 'real time' in Matlab from Arduino. I have the following code to get the data:
clear all; close all;clc;delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.BaudRate=115200;
fopen(puerto);
for i=1:1000
a=fscanf(puerto, '%d');
v(i)=a;
++i;
end
fclose(puerto);
delete(puerto);
However, sometimes I get an error saying the following (in reference to variable a):
In an assignment A(I) = B, the number of elements in B and I must be the same.
Error in (line 8)
v(i)=a;
So I have 3 questions:
How can I avoid the error I mentioned?
How can I plot (v) continuously?
Is there a way to send an array of integers from Arduino to Matlab?
Try something like this. Using the BytesAvailableFcn of the serial port.
See Documentation
function serialTest()
lineHandle = plot(now,0);
hold on;
delete(instrfind({'port'},{'COM12'}));
puerto=serial('COM12');
puerto.InputBufferSize = 200; %Set to an appropriate number of bytes see docs
puerto.BaudRate=115200;
puerto.BytesAvailableFcnCount = 100; %Set to an appropriate number see docs.
set(puerto,'BytesAvailableFcn',{#bytesFcnCallback,lineHandle});
drawnow
fopen(puerto);
function bytesFcnCallback(puerto,evtData,lineHandle)
temp = fgetl(puerto); %Read a single line from the com port.
C = textscan(temp,'%f');
lineHandle(1).YData= [lineHandle(1).YData C{1}];
lineHandle(1).XData(end+1) = now;
Edit: Update to show how to continuously update a plot.
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
My code is below. In the code, I am evaluating only the data in the 'fb2010' file. I want to add other files" 'fb2020', 'fb2030', and 'fb2040' and evaluate their data by the same code. My question is how to apply a for loop and include the other data files. I tried, but I got confused by the for loop.
load('fb2010'); % loading the data
x = fb2010(3:1:1502,:);
% y_filt = filter(b,a,x); % filtering the received signal
y_filt= filter(b,a,x,[],2);
%%%%%%% fourier transform
nfft = length(y_filt);
res = fft(y_filt,nfft,2)/nfft;
res2 = res(:,1:nfft/2+1); %%%% taking single sided spectrum
res3 = fft(res2,[],2);
for i = 3:1:1500 %%%% dividing each row by first row.
resd(i,:) = res3(i,:)./res3(1,:);
end
I'm assuming that your files are MAT-files, not ASCII. You can do this by having load return a struct and using dynamic field referencing:
n = 4;
for i = 1:n
vname = ['fb20' int2str(i) '0']; % Create file/variable name based on index
s = load(vname); % Load data as struct (overwriting previous s)
x = s.(vname)(3:1:1502,:); % Access struct with dynamic field reference
% Rest of your code
...
end
If you're using a plain ASCII file, load won't produce a struct. However, such files are much simpler (see documentation for load/save). The following code would probably work:
n = 4;
for i = 1:n
vname = ['fb20' int2str(i) '0']; % Create file/variable name based on index
s = load(vname); % Load data as matrix (overwriting previous s)
x = s(3:1:1502,:); % Directly index matrix
% Rest of your code
...
end
It would be a good idea to add the file extension to your load command to make your code more readable.
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