I need to collect data using Matlab and a MCC USB-2527 card.
Everything works except triggering. Here is my code:
BoardNR=1;
Chan=[0 1 2 3];
fs = 100
duration=60
ai = analoginput('mcc',BoardNR);
ch = addchannel(ai,Chan);
set(ai,'SampleRate',fs);
set(ai,'SamplesPerTrigger',duration*fs);
set(ai,'TriggerChannel',ch(3)) %Channel 3 is the position signal of a cyclic movement
set(ai,'TriggerType','Software')
set(ai,'TriggerCondition','Leaving') %Should trigger when the position signal is not 0
set(ai,'TriggerConditionValue',[0,0])
set(ai,'TriggerDelay',1);
set(ai,'Timeout',5);
%The data collection is started
start(ai);
wait(ai, duration+1)
data=getdata(ai,fs*duration);
plot(0.01:(1/fs):duration,data); %Plotting real time vs signals
If I delete the parts with the triggering, I collect data perfectly. I need to trigger however, and when I run this code I get the error: "WAIT reached its timeout before OBJ stopped running" . I think this means that it stopped waiting for the triggering signal. I am 100 % positive that the position signal will be 0 every 20 seconds or so, so it should def. trigger.
I hope you can help. Ive tried everything, including having another TriggerCondition (like Entering, Rising, Falling) and another TriggerConditionValue.
Thanks in advance,
Henrik
I'm not sure, but I reckon, you have to set the TriggerType to Manual. Which options are possible the command 'propinfo(ai.TriggerType)' should show.
I also use USB 2527 with MatLab ;-)
Related
I am trying to plot real-time data from a sensor that has a frequency of 25 Hz. I read data from the sensor using TCPIP protocol, parse it and then plot the data. However, the plotting part is not very fast and starts to lag after some time. So for e.g. if I move the sensor, I see the response 5 seconds later. I used Serial Plotter in Arduino (which has much less specifications than my laptop) but it is able to plot real-time data without any delays / problems.
My code looks a bit like the following
IMUData = nan(1500,6);
InterfaceObject = tcpip('my_ip_address',50001);
InterfaceObject.BytesAvailableFcn ={#PlotSensorData};
And the PlotSensorData function looks like
function PlotSensorData(~,~)
RecievedData = fscanf(InterfaceObject,'%s');
Identifier = RecievedData(6); % 6th byte is the sensor identifier
DataStartIdx = 28; % For each sensor, data start position is common
if Identifier == 'I'
DataEndIdx = DataEndPosition(RecievedData, 1);
SlicedData = RecievedData(DataStartIdx:DataEndIdx);
ParsedData = textscan(SlicedData,'%f', 'Delimiter',',');
% Append new data to IMUData matrices
prevval = IMUData;
val = [prevval(2:end,:); ParsedData{1}'];
IMUData = val;
set(PlotHandle{1},'ydata',val(:,3));
set(TopAxes,'ylim',[-15 15]);
drawnow limitrate;
end
end
Also, instead using plot, I have already tried animatedLine. It seems faster initially as it plots very fast, but after sometime, it starts to lag as well and the lag is more than 10 Sec.
So my questions are
What can be done to speed up the real-time data in MATLAB.
Also, I have already tried plotting the data after a certain number of samples (say 10, 20) are received instead of plotting after every received sample, but the results are still lagging and the GUI hangs as well. Is there any other strategy that I can use? In Python I used Multi-threading, but can I use it here as well? Or is there a better approach to handle this data rate?
I understand that Arduino is only running one script but the computer has a lot of overhead, but how is Arduino able to plot the data so fast while MATLAB just hangs up?
Thanks
Reading Data Asynchronously instead of continuously solved my problem.
I have the model of a dynamic system in Simulink (I cannot change the programming framework). It can be described as an oscillator subject to periodic oscillations. I am trying to control its motion, in particular, to maximize it (for energy generation).
With latching control (a popular control strategy), the idea is to 'latch', i.e. lock in place, the device when its velocity is 0 for a predefined time, and then release it until its velocity reaches 0 again.
So, what I need to do in Simulink is to output a signal 1 once the velocity signal reaches (or is close to) 0, hold it constant for a time period (at 1), then release it (the signal becomes 0), and repeat the process once the velocity reaches 0 again.
I have found a good blog on holding signals constant in Simulink:
http://blogs.mathworks.com/simulink/2014/08/06/how-do-you-hold-the-value-of-a-signal/
However, in my case, I have two conditions for determining the signal: the magnitude of the velocity and the time within the time period. Now, the problem is that as soon as the period is finished, and the device is released (signal = 0), the velocity is still very small, which could result in an incorrect signal of 1 if an if-loop is used.
I think using an S-function may be the best solution, but then I will have to use a fixed time-step. Are there any Simulink-native solutions for this problem?
I ended up using a Matlab function as a temporary solution, and it is very effective. I have taken inspiration from https://uk.mathworks.com/matlabcentral/answers/11323-hold-true-value-for-finite-length-of-time
u is the velocity signal.
function y = fcn(u,nlatch)
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% This function is used to determine the latching signal.
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Using persistent memory:
persistent tick started sign;
% Initialize variables:
if isempty(tick)
tick = 0;
started = 0;
sign = (u>0);
end
U=0; % no latching
s=(u>0);
if s~=sign
started = 1;
end
if started
if tick<nlatch
tick=tick+1;
U = 1;
else
tick = 0;
started = 0;
sign = s;
end
end
y = U;
end
However, as I mentioned, I have to use a fixed step solver, which is no big deal to me, but it can create problems to other users.
If anyone has a more "Simulink-native" solution, please let me know!
Edit
I have now modified the function: the latching is now applied when there is a change in sign in the velocity signal rather than looking at a small magnitude as earlier on (abs(u)<0.005), which was too case-specific.
A colleague of mine has also found a Simulink-native solution:
However, the Matlab function is faster (less computing intensive) when the same time step is employed. Maybe the least computing-intensive solution is a C S-function.
I have written a MATLAB program which performs calculations on a video. I think it is a perfect candidate to adapt to multiple cpu cores as there is a lot of averaging done. I am just sturggling with the first bit of sending each section of frames to each lab. Say (for simplicity) it is a 200 frame file. I have read some guides and using SPMD gotten this.
spmd
limitA = 1;
limitB = 200;
a = floor(((limitB-limitA)/numlabs)*(labindex-1)+limitA);
b = floor((((limitB-limitA)/numlabs)*(labindex-1)+limitA)+(((limitB-limitA)/numlabs)));
fprintf (1,'Lab %d works on [%f,%f].\n',labindex,a,b);
end
It successfully outputs that each worker will work on their respective section (Eg Lab 1 works on 1:50, Lab 2 50:100 etc).
Now where I am stuck is how do actually make my main body of code work on each Lab's section of frames. Is there a tip or an easy way to now edit my main code so it knows what frames to work on based on labindex? Adding spmd to the loop results in an error hence my question.
Thanks
Following on from what you had, don't you simply need something like this:
spmd
% each lab has its own different values for 'a' and 'b'
for idx = a:b
frame = readFrame(idx); % or whatever
newFrame = doSomethingWith(frame);
writeFrame(idx, newFrame);
end
end
Of course, if that's the sort of thing you're doing, you may need to serialize the frame writing (i.e. make sure only one process at a time is writing).
I got a camera triggered by external source at a constant rate of 1/0.14s, and Matlab for-loop is used to take timed pictures for real-time measurements. However, the elapsed time for 1 execution of "getsnapshot" is so different each time. Sometimes I get 1 picture with less than 0.14s and
sometimes it takes 0.5s to take a picture. Is there anyway to synchronize the "getsnapshot"
with the external trigger? or at least make the "getsnapshot" exactly timed?
The following is my code:
vid = videoinput('camera');
preview(vid);
for i=1:100
data=getsnapshot(vid);
%...data processing...
%....
clear data
end
First, delete the preview(vid) line, this is probably why the rep. rate you are getting is weird. When you take data you don't need this preview option on, as it takes resources from your cpu.
Then, you may need to set the camera properties on the imaq toolbox to be in triggered mode. For example, for a gentl camera type this might look something like:
triggerconfig(vid, 'hardware', 'DeviceSpecific', 'DeviceSpecific');
src = getselectedsource(vid);
src.FrameStartTriggerMode = 'On';
src.FrameStartTriggerActivation = 'RisingEdge';
src.FrameStartTriggerDelayAbs = 0;
src.FrameStartTriggerSource = 'Line1';
src.FrameStartTriggerOverlap = 'Off';
Then, with some camera's you can read their trigger out, that is whenever the camera is exposing, it sends a ttl to some output. Matlab way to define it is something like:
src.SyncOut1SyncOutPolarity = 'Normal';
src.SyncOut1SyncOutSource = 'Exposing';
Again, you'll need to play with your camera's options in the imaq tool.
Also, the data processing step that you take afterwards may take some time, so benchmark it to see you can take data and analyze it on the fly without bottlenecks happening.
Last, you can use getdata instead of getsnapshot (read the documentation to see their difference) , and in the form: [img, time, metadata] = getdata(vid);
This will give you timestamps for each image taken, so you can see what's happening. Also, instead of clear data use flushdata(vid) to keep the vid object from completely filling the memory buffer (though if you only run 100 iterations in a loop, you should be fine).
I'd like to simultaneously get data from a camera (i.e. an image) and an analog voltage using matlab. For the camera I use the imaq toolbox, for reading the voltage I use the daq toolbox (reading NI-USB device), with a following code:
clear all
% Prepare camera
vid = videoinput('gentl', 1, 'Mono8');
src = getselectedsource(vid);
vid.FramesPerTrigger = 1;
vid.TriggerRepeat = Inf;
triggerconfig(vid, 'hardware', 'DeviceSpecific', 'DeviceSpecific');
src.FrameStartTriggerMode = 'On';
src.FrameStartTriggerActivation = 'RisingEdge';
% prepare DAQ
s=daq.createSession('ni');
s.addAnalogInputChannel('Dev1','ai1','Voltage');
fid = fopen('log.txt','w');
lh = s.addlistener('DataAvailable',#(src,event)SaveData(fid,event));
s.IsContinuous = true;
% Take data
s.startBackground();
start(vid)
N=10;
for ii=1:N
im(:,:,ii)=getsnapshot(vid);
end
% end code
delete(lh );
fclose('all');
stop(vid)
delete(vid)
where the function SaveData is:
function SaveData(fid,event)
time = event.TimeStamps;
data = event.Data;
fprintf(fid, '%f,%f\n ', [time data]);
end
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
For this example, the daq reads the camera triggering TTL signal (# 50 Hz), so I want to assign each TTL pulse to an image.
Addendum:
I've been searching and have found a few discussions (like this one) on the subject, and read the examples that are found in the Mathworks website, but haven't found an answer. The documentation shows how to Start a Multi-Trigger Acquisition on an External Event, but the acquisition discussed is only relevant for the DAQ based input, not a camera based input (it is also working in the foreground).
This will not entirely solve your problem, but it might be good enough. Since the synchronization signal you are after in at 50 Hz, you can use clock in order to create time stamps for both types of your data (camera image and analog voltage). Since the function clock takes practically no time (i.e. below 1e-7 sec), you can try edit to your SaveData function accordingly:
fprintf(fid, '%f,%f\n ', [clock time data]);
And in the for loop add:
timestamp(i,:)=clock;
Can you use the sync to trigger the AD board? From the USB-6009 manual...
Using PFI 0 as a Digital Trigger--
When an analog input task is defined, you can configure PFI 0 as a digital trigger input. When the digital trigger is enabled, the AI task waits for a rising or falling edge on PFI 0 before starting the acquisition. To use AI Start Trigger (ai/StartTrigger) with a digital source, specify PFI 0 as the source and select a rising or falling edge.
My experience suggests that delay between trigger and AQ is very short
I'm sorry I use Python or C for this, so I can't give you MatLab code, but you want to look at functions like.
/* Select trigger source */
Select_Signal(deviceNumber, ND_IN_START_TRIGGER, ND_PFI_0, ND_HIGH_TO_LOW);
/* specify that a start trigger is to be used */
DAQ_Config(deviceNumber, startTrig, extConv); // set startTrig = 1
/* start the acquisition */
DAQ_Start(deviceNumber, …)
If you want to take this route you could get more ideas from:
http://www.ni.com/white-paper/4326/en
Hope this helps,
Carl
This is yet no complete solution, but some thoughts that might be useful.
I do get images and a log.txt file with the daq trace (time and data), but how can I use the external triggering (that trigger the camera) or some other clock to synchronize the two?
Can you think of a way to calibrate your setup? I.e. modify your experiment and create a distinct event in both your image stream and voltage measurements, which can be used for synchronization? Just like this ...