Is there an API function call for this board that would allow me to generate a clock signal on an output at 500 kHz while running some other code on the board? Thanks in advance for the advices.
According to the Supported Hardware documentation, version 2.8 or greater of the Data Acquisition Toolbox is needed to support a Measurement Computing USB-1024HLS device. Assuming you have version 2.8 or newer, the following should come close to a solution for you...
The first step would be to get the hardware ID for the device. The function DAQHWINFO should help with this:
deviceInfo = daqhwinfo('mcc');
The hardware ID gotten from the structure deviceInfo can then be used to create a Digital I/O Object (DIO) using the DIGITALIO function:
dio = digitalio('mcc',hardwareID);
Next, you have to add two output lines (for a clock signal and a pulse-width modulation (PWM) signal) using ADDLINE:
addline(dio,0:1,'out');
Then, you have to set a few DIO properties.
set(dio,'TimerPeriod',0.000002); % i.e. 500 kHz
set(dio,'TimerFcn',#update_outputs);
The function update_outputs is called once every timer period and should set the output pins to the appropriate values. The clock signal is simply going to switch back and forth between 0 and 1 every timer period. The PWM signal will likely alternate between 0 and 1 as well, but it will not change every timer period, remaining in each state for a set amount of time based upon the sort of pulse-width modulation you want. Here's what your update_outputs function may end up looking like:
function update_outputs(obj,event)
currentValues = getvalue(obj);
clockValue = ~currentValues(1);
pwmValue = pwm_compute();
putvalue(obj,[clockValue pwmValue]);
end
Note that this uses PUTVALUE and GETVALUE to set/get the values of the output pins. You will have to write the function pwm_compute such that it computes a new PWM value for each time period. Since pwm_compute will likely have to know how many values have been output already (i.e. how many times it has already been called), you can track that using a persistent variable:
function newValue = pwm_compute
persistent nValues;
if isempty(nValues)
nValues = 0;
else
nValues = nValues+1;
end
...
% Compute the new value for the (nValues+1) time period
...
end
This is just one possible solution. You could potentially precompute the PWM signal and pull the value for each timer period from a vector or data file, or you could potentially use the event data structure passed to update_outputs to get the time of the timer event (relative to the DIO timer start, I believe).
Finally, you have to start the DIO:
start(dio);
...and, once you're finished using it, delete it and clear it from memory:
delete(dio);
clear dio;
One potential stumbling block...
Generating a 500 kHz signal could be difficult. It's such a high frequency that you may run into problems, specifically with the 'TimerFcn', which is called once every timer period. If the 'TimerFcn' takes longer than 0.000002 seconds to run, some timer events may not be processed, leading to an output that is actually of a lower frequency. I have a feeling you may have to use a lower signal frequency for things to work properly, but I could be wrong. =)
I found Example: Generating Timer Events in the Data Acquisition Toolbox documentation.
dio = digitalio('nidaq','Dev1');
addline(dio,0:7,'in');
set(dio,'TimerFcn',#daqcallback)
set(dio,'TimerPeriod',5.0)
start(dio)
pause(11)
delete(dio)
clear dio
Related
I would like to get peak value from STM32 adc samples. I have written the below code and I've managed to get peak value however most of the time this value includes the biggest noise. In order to eliminate noise effects, I have decided to apply averaging method. I would like to get 5 measurements' averages. Then I'd like to compare these averages and use the biggest one(biggest average). Can anybody suggest a code?
Regards,
Umut
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc)
{
ADC_raw = HAL_ADC_GetValue(hadc);
Vdd = 3.3 * (ADC_raw)/4095;
if (Vdd > Vmax)
{
Vmax = Vdd;
}
At first, I would remove as much code as possible from the Callback function because it is still inside the interrupt context which should be as short as possible. This is mentioned in a lot of answears here so I will not go into details on how to handle this.
For averaging the measurement, there are multiple ways you can go.
Automatic avarage
Use the ADCs oversampling function. The controller will sample the signal multiple times (configure using OVFS register) and calculate an average value before triggering the interrupt.
Manual average
Using the HAL_ADC_ConvCpltCallback function Store the numer of desired value into an array and calculate the average in the main loop.
Manual average using DMA
Let the DMA store the number of samples you want to use in an array using the function HAL_ADC_Start_DMA. When all samples have been collected you will be notified. This will reduce the processor load because you don't have to shift the data into the array yourself.
You can also combine the oversampling (most of the time a good idea) and one of the other methods depending on your Use-Case.
I am implementing a scheme in Matlab in which a particular node A waits for time period t(defined by the distance between the farthest node within A's range and the propagation speed of the signal) for acknowledgements from a set of nodes after sending a message. If it does not receive any acknowledgement with in time period t, it takes some action.
I have no idea how to implement time in Matlab. Is it possible or I'll have to find some way around?
You can use MATLAB's powerful datetime:
For example: you want to check if the signal is received within the acceptable delay (in this example, 40 milliseconds):
% t = datetime(Y,M,D,H,MI,S,MS);
send = datetime(2016,08,31,06,01,00,00);
receive=datetime(2016,08,31,06,01,00,100);
acceptableDelay=datenum(40/(24*60*60*1000));
if ((receive-send)<acceptableDelay)
disp('Well received!')
else
disp('Late!')
end
I've done a function playSound(f) which looks like this:
function playSound(f)
fs = 44100;
t = 0:1/fs:1;
y = sin(2.*pi.*f.*t);
sound(y,fs,16);
end
I'm using this function in another function with the following code:
while i <= y
b = bin2dec(bits(i:i+k-1));
freq = 2000-frequencyInterval+b*deltaFreq;
playSound(freq);
pause(1);
i = i + k;
end
What I'm expecting from the last piece of code is getting a succession of sinusoids with different frequencies each lasting one second and one after another. But I've noticed that this is completely unreliable and I'm not getting exactly one second of one sin directly followed by another one.
Is there a more precise way to tell Matlab to play my sounds one by one, each during a certain time (no more no less) and without interruptions (or anything else in the middle)?
Matlab pause does not provide millisecond precision, even when measured by its internal tic-toc timer. For example:
tic;pause(1);toc
Elapsed time is 1.006905 seconds.
tic;pause(0.001);toc
Elapsed time is 0.018834 seconds.
If you can't 'pre-render' the entire sound sequence as suggested in the comments, I'd use a tool such as Psychophysics toolbox that can take care both of timing and audio playback.
Playing sound elegantly requires some low-level access and buffering and what not. Matlab's sound() function does not provide such access, and will not do what you want, unfortunately. However, if you've a recent Matlab, you will find audioplayer does do what you want, that's exactly the role it's designed for. Because of the need to 'play nice' with your sound hardware, you will have to invest a little more time in making it behave.
Start at "doc audioplayer".
I am trying to use matlab for data acquisition with a licor820 instrument. The instrument outputs data at 2 hertz.
I have tried many different methods using infinite loops with asynchronous sampling (readasync) and timed readings but I am unable to get 2 hertz data. I am getting reads in the .51 s range. here are three examples of my methods. Any advice on what I may be doing wrong or how to properly sample at the highest frequency would be greatly appreciated!
example1: using readasync
tinit=tic; %initialization timer
s=serial('COM4') %,'InputBufferSize',40);
fopen(s)
while toc(tinit)<2 %allow time to initialize
end
while 1<2 %infinite loop for continuous sampling
readasync(s)
data=fscanf(s)
toc %allows me to see time between data acquisitions
tic
end
example 2: using bytes available.
My thinking here is to acquire data when I have the minimum amount of bytes necessary. Although I am unsure exactly how to determine how many bytes are necessary for my instrument, besides through visually looking at the data and narrowing it down to around 40 bytes:
while 1<2 %infinite loop for continuous sampling
if s.BytesAvailable >35
scandata=fscanf(s);
toc
tic
end
end
example 3: time forcing.
Since I need 2 hertz data my thinking here was to just force read the buffer every .49 seconds. The weird thing I see here is that it initially provides samples every .49 seconds, but while I monitor the bytes available at the port I see it steady dropping from 512 until it gets to 0 and then I stop getting .49 second samples. I guess I don't really understand how to use serial efficiently.
while 1<2 %infinite loop
if toc(t2)>=.49 %only sample after .49 seconds have passed
t2=tic; %reinitiate the tic for this forced time loop
bytes=s.BytesAvailable %to monitor how many bytes there are at the port
scandata=fscanf(s);
if ~isempty(scandata) && length(scandata)== 3 %checks for successful read
toc
tic
end
end
end
I feel there must be some way to sample completely in sync with the an instrument but I can't figure it out. Any help, suggestions, or ideas would be greatly appreciated! Thanks!
Dont rely on tic and toc. These functions use the time supplied by the OS calls. Mathworks claims to use high resolution timers, but do not rely on this! If you do not use a realtime OS these measurements are subject to unknown variation.
Sampling should be performed by realtime capable hardware. In your case I suspect that your sampling rate is actually controlled by your instrument. The output of the instrument is buffered by your serial interface. Therefore it seems to me that Matlab does not influence the sampling rate at all. (As long as the buffer does not overflow)
Try to acquire about 2000 samples or more and see how long it takes. Then divide the total time by the number of samples (-1) and compare this to the expected 0.5 s. If there is a difference, try adjusting the configuration of your instrument.
The matlab recording function"record ( recordObj, samplingTime )" needs 0.8 second plus the sampling time to be executed.
this means that if i want to record for only 0.2 second the execution time of this function will be 1 second.
I am working on a real time processing project in which I need to record 0.2 second files with high frequency and make real time processing on each file.
So i tried to record a long record and access it every 0.2 second.
So I wonder if i can access recordObj while the recording function is in progress .
I tried this code but i got error as the matlab couldn't access "myvoise" while recording is in progress. thanks in advance
clc
% clear all
% myVoice = audiorecorder;
% % Define callbacks to show when
% % recording starts and completes.
% myVoice.StartFcn = 'disp(''Start speaking.'')';
% myVoice.StopFcn = 'disp(''End of recording.'')';
% record(myVoice,20);
% y=getaudiodata(myVoice);
Unfortunately, Matlab is not really designed for real time processing. But if you really need it, look into the DSP Systems Toolbox, which provide this functionality.
You couldn't access myVoice because record is a not blocking function, this means that after execution of record(myVoice,20) immediately getaudiodata is executed but myVoice has not yet captured any data. If instead you use recordblocking(myVoice,20) then this will block flow of your code for 20 seconds. So myVoice now will contain data for 20 seconds and getaudiodata will be successfully executed.
Because you want real time operation I suggest set myVoice.TimerFcn = 'callbackfcn(myVoice)' and also set myVoice.TimerPeriod=period. Where callback fcn will be a user specified function in which you call data = getaudiodata(myVoice). This function will be called every period seconds during execution. So in this way you can call record(myVoice,20) and after period(s) getaudiodata will be successfully executed because myVoice already has period(in s) of audio data.
Be aware of that every time getaudiodata is executed will acquire all data of my voice from the beggining of recording, so you can skip every period the previous acquired data (i*period/Fs) where i is the time the callback function is executed(beginning from zero). Be also awhere of that myVoice will be buffered in memory, so if you record for a long period of time at high sampling frequency matlab performance will deteriorate