Как запрограммировать Arduino Uno для сбора данных с помощью прерывания таймера и анализа этих данных в matlab?
Я работаю над проектом, где я хочу собрать данные датчика (от датчика), и я хочу проанализировать первые 20 образцов данных (например, найти диапазон, линию тренда и т. д.). Я знаю, как скомпилировать прерывание таймера в Arduino IDE (используя таймер ISR), но как бы я мог сделать это что-то подобное (таймер ISR) в MATLAB. Причина в том, что я хочу собрать свои сенсорные данные ровно на 20 Гц, и использование функции задержки может оказаться неточным. Кроме того, когда я запускаю примерную программу, которая собирает данные в MATLAB, мои частоты образца изменяются от 15 Гц до даже 24 Гц (как показано ниже) . У кого-нибудь есть какие-нибудь предложения о том, как я могу это сделать? Если вопрос недостаточно ясен, я могу подробнее остановиться на нем в комментариях.
Это мой код MATLAB:
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
% %График зависимости напряжения от времени
v1 = v1(1:i);
v2 = v2(1:i);
x = x(1:i);
p = v1;
n = v2;
%График зависимости напряжения от времени
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) % Всегда удалять объекты таймера после их использования.
Выход есть
>> 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.
>>
Прошу прощения за длинный вывод. Но, как вы можете видеть, я указал время паузы 0,00001, что должно дать мне значительно большую частоту дискретизации 20 Гц. Но я получаю только 76 сэмплов/5 секунд = 15,2 Гц. Кроме того, иногда, когда я запускаю эту программу, она может собирать 79sample/5secons или даже 121sample/5seconds. Это просто непоследовательно. Я надеялся решить эту проблему с помощью прерывания таймера, которое будет жестко закодировано в MATLAB для сбора данных ровно на частоте 20 Гц. Пожалуйста, дайте мне знать, что вы все думаете. Спасибо.
@Dema Govalla, 👍2
Обсуждение2 ответа
Каждая связь с Arduino занимает 20 мс, у вас есть два в цикле, так что в идеальных условиях вы могли бы получить 25 показаний в секунду. Смотрите здесь источник
Это также зависит от размера запрашиваемых данных.
Я думаю, что это именно то, что вы ищете, но я не могу дать вам никакого совета, так как у меня нет Matlab, а у Octave нет этой функции.
Я настроил таймер по-другому, используя его свойство UserData. Таймер будет обновлять данные каждый фиксированный период для заданного количества выборок.
close all;
clear all;
% Некоторые полезные константы.
NUM_SAMPLES = 20;
PERIOD = 0.05;
global a;
a = arduino('com4', 'uno');
% Инициализировать данные. Он будет обновляться по таймеру.
data.i = 0;
data.v1 = zeros(NUM_SAMPLES, 1);
data.v2 = zeros(NUM_SAMPLES, 1);
data.x = (1:NUM_SAMPLES) * PERIOD;
% Инициализировать таймер на фиксированный период для определенного количества выборок.
t = timer;
t.ExecutionMode = 'fixedRate';
t.Period = PERIOD;
t.TasksToExecute = NUM_SAMPLES;
t.TimerFcn = @TimerCallback;
t.UserData = data;
% Запустите таймер и дождитесь его завершения.
start(t);
wait(t);
stop(t);
data = t.UserData; % Получить обновленные данные.
delete(t);
% График зависимости напряжения от времени.
figure(1);
plot(data.x, data.v1, '-', data.x, data.v2, '-');
xlabel('Прошедшее время (s)');
ylabel('Напряжение (V)');
title('Данные о напряжении');
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
- Получение BPM из данного кода
- ATtiny85 AC Phase Control для регулировки яркости лампочки
- Как измерить ультразвуковой датчик без импульсного метода?
- Проблемы с передачей данных через RF24
- Получение точных показаний скорости от IMU
- Как определить, когда выходной сигнал датчика значительно меняется?
- Отправка данных перед повышением края часов
- Является ли плохой практикой многозадачность без ограничений по времени
Это Arduino SE, поэтому мы можем рассказать вам, как использовать прерывание таймера в Arduino. Но мы не являемся экспертами по Matlab, так что ваш вопрос здесь не по теме. В настоящее время частота дискретизации напрямую зависит от времени выполнения всех задействованных вызовов функций, включая " readVoltage ()", я думаю, вы этого не учли. Я не знаю, что именно делает эта функция и какая прошивка у вас есть на Arduino. В зависимости от этого вам, возможно, придется написать свою собственную прошивку, которая может быть лучше приспособлена к вашей цели. Функция "readVoltage ()" может быть слишком медленной., @chrisl
1. Я согласен с Крислом: это больше похоже на вопрос Matlab, чем на вопрос Arduino. 2. Я не думаю, что Matlab-это правильный выбор для выборки в реальном времени. Вместо этого вы могли бы позволить Arduino обрабатывать тайминги и отправлять данные через последовательный порт, а затем обрабатывать данные в Matlab., @Edgar Bonet
Задержка для matlab с arduino - известная проблема. Хорошим началом было бы изменить скорость связи по умолчанию на 9600 бод, @Dorian
В вашем названии говорится, что вы хотите собрать данные с помощью Uno и проанализировать их с помощью MATLAB, но ваше описание предполагает, что вы также пытаетесь собрать некоторые данные с помощью MATLAB. Какой из них правильный? Если это так, как говорится в названии, то MATLAB вообще не нуждается в выборке; ему нужно только прочитать собранные данные из Uno, постфактум., @JRobert
У вас есть Arduino в вашем проекте, который запускает циклы ISR с очень точными интервалами. Нет смысла добавлять время на стороне приемника. Просто отметьте данные и соберите их по мере поступления., @PMF