2

I working on a project where I want to collect sensor data (from a sensor) and I want to analyze the first 20 data sample (e.g., find the range, trendline e.t.c.). I know how to compile a timer interrupt in Arduino IDE (using an ISR timer), but how would I be able to do this something similar (ISR timer) in MATLAB. The reason being, I want to collect my sensor data at exactly 20 Hz and using a delay function can prove to be inaccurate. Also, when I run a sample program that collects data in MATLAB, my sample frequencies change from 15Hz to even 24Hz (as shown below) . Does anyone have any suggestion on how I can do this? If the question is not clear enough I can elaborate more in the comments.

This is my MATLAB code:

clear all;
a = arduino('com4', 'uno');
i = 0;
v1 = zeros(1e4,1);
v2 = zeros(1e4,1);
x = zeros(1e4,1);
t = timer('TimerFcn', 'stat=false; disp(''Timer!'')',... 
                 'StartDelay',5,'Period', 1);
start(t)

stat=true;
tic
while(stat==true)
   %while i<60
    i = i + 1;
    v1(i) = readVoltage(a, 'A0');
    v2(i) = readVoltage(a, 'A1');
    x(i) = i;
    disp(x(i));
    pause(.00001);
   
  % end
end
toc


% %Plot voltage versus time
v1 = v1(1:i);
v2 = v2(1:i);
x = x(1:i);

p = v1;
n = v2;
%Plot voltage versus time
figure(1);
plot(x,p,'-',x,n,'-')
xlabel('Elapsed time (sec)')
ylabel('v')
title('Ten Seconds of voltage Data')
%set(gca,'xlim',[t(1) t(i)])
legend('v1', 'v2');

%
delete(t) % Always delete timer objects after using them.

Output is

>> Timer
     1

     2

     3

     4

     5

     6

     7

     8

     9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    46

    47

    48

    49

    50

    51

    52

    53

    54

    55

    56

    57

    58

    59

    60

    61

    62

    63

    64

    65

    66

    67

    68

    69

    70

    71

    72

    73

    74

    75

Timer!
    76

Elapsed time is 5.032553 seconds.
>> 

I apologize for the long output. But as you can see, I specified a pause time of .00001, which should give me well over a 20Hz sampling frequency. But I only get 76 samples/5 seconds = 15.2Hz. Also, sometime when I run this the program may collect 79sample/5secons, or even 121sample/5seconds. It just is not consistent. I was hoping to solve this with a timer interrupt that will be hard coded in MATLAB to collect data at exactly 20Hz. Please let me know what y'all think. Thank you.

5
  • This is Arduino SE, so we can tell you how to use a timer interrupt in Arduino. But we are no Matlab experts, so your question is off topic here. Currently the sample frequency is directly dependent on the execution time of all the involved function calls, including readVoltage() you didn't account for that I guess. I don't know, what exactly that function does and what firmware you have on the Arduino. Depending on that you might need to write your own firmware, that can be better fitted to your goal. The readVoltage() function might be too slow.
    – chrisl
    Mar 9 at 10:35
  • 1. I agree with chrisl: this looks more like a Matlab question than an Arduino question. 2. I don't think Matlab is the right choice for real-time sampling. You could instead let the Arduino handle the timings and send the data through the serial port, then process the data on Matlab. Mar 9 at 10:38
  • The latency for matlab with arduino is a known issue. A good start would be to change the default communication speed of 9600 baud
    – Dorian
    Mar 9 at 18:58
  • Your title says you want to collect the data with an Uno and analyze it with MATLAB, but your description suggests you are also trying to collect some data with MATLAB. Which one is correct? If it's as the title says, MATLAB doesn't need to sample at all; it only needs to read the collected data from the Uno, after the fact.
    – JRobert
    Mar 10 at 16:46
  • You have an Arduino in your project, which runs ISR loops at very precise intervals. There's no point in adding timing on the receiver side. Just timestamp the data and collect it as it comes in.
    – PMF
    Mar 10 at 16:54
1

I've configured the timer differently making use of its UserData property. The timer will update the data every fixed period for a specified number of samples.

close all;
clear all;

% Some useful constants.
NUM_SAMPLES = 20;
PERIOD = 0.05;

global a;
a = arduino('com4', 'uno');

% Initialise data. It will be updated by the timer.
data.i = 0;
data.v1 = zeros(NUM_SAMPLES, 1);
data.v2 = zeros(NUM_SAMPLES, 1);
data.x = (1:NUM_SAMPLES) * PERIOD;

% Initialise timer for a fixed period for a specific number of samples.
t = timer;
t.ExecutionMode = 'fixedRate';
t.Period = PERIOD;
t.TasksToExecute = NUM_SAMPLES;
t.TimerFcn = @TimerCallback;
t.UserData = data;

% Run the timer and wait for it to complete.
start(t);
wait(t);
stop(t);
data = t.UserData;  % Retrieve the updated data.
delete(t);

% Plot voltage versus time.
figure(1);
plot(data.x, data.v1, '-', data.x, data.v2, '-');
xlabel('Elapsed time (s)');
ylabel('Voltage (V)');
title('Voltage Data');
st = sprintf("%0.3f seconds", NUM_SAMPLES * PERIOD);
subtitle(st);
legend('v1', 'v2');

function TimerCallback(obj, event)
    global a;
    obj.UserData.i = obj.UserData.i + 1;
    obj.UserData.v1(obj.UserData.i) = readVoltage(a, 'A0');
    obj.UserData.v2(obj.UserData.i) = readVoltage(a, 'A1');
end
0

Each communication with Arduino takes 20ms, you have two in the loop so in the ideal conditions you could get 25 readings/second. See here the source

This also depends on the size of the data you request.

I think this is what you are looking for but I cant give you any advice since I don't have Matlab and Octave is not having this feature.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.