gpt4 book ai didi

matlab - Arduino和Matlab串行同步数据传输

转载 作者:行者123 更新时间:2023-12-04 10:48:53 27 4
gpt4 key购买 nike

我正在做一个项目,我使用 Split Core CT 在 Arduino 上读取实时电流信号。我能够读取精确的交流电流并使用下面的代码在 Arduino 串行绘图仪中复制它。

void setup() {
Serial.begin(115200);
}
void loop() {
Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625 );
}

但是我必须对它做进一步的计算,比如 FFT 和 THD,所以我通过串行通信将这些数据发送到 MATLAB。下面是我的 Matlab 脚本,它读取 1000 个数据样本,将其存储在一个数组中并执行计算并最终绘制它。
clc; close all;

if ~isempty(instrfind)
fclose(instrfind);
delete(instrfind);
end
s1=serial('COM5','Baudrate',115200);
fopen(s1);

Fs=1000;
LoS = 100;
T = 1/Fs;
t = (0:LoS-1)*T;

sig = zeros(1,LoS-1);

str='';
sen=0;
for j = 1:LoS
str=fscanf(s1);
sen=str2double(str);
sig(j)=sen;
end

subplot(2,1,1);
axis([0 LoS -4 4]);
plot(t,sig);
xlabel('Counts');
ylabel('Magnitude');
title('Signal');

Y=fft(sig);

P2 = abs(Y/LoS);
P1 = P2(1:LoS/2+1);
P1(2:end-1) = 2*P1(2:end-1);
f = Fs*(0:(LoS/2))/LoS;

subplot(2,1,2);
axis([0 100 0 10]);
plot(f,P1);
title('FFT(Signal)');
xlabel('f (Hz)');
ylabel('|Power(f)|');
fclose(s1);
delete(s1);
clear s1;

问题是实际信号的频率为 60Hz,但我的代码输出峰值为 31Hz。我在 matlab 模拟正弦曲线上检查了相同的代码,它给出了准确的结果。但在真实数据上,它计算错误。我在 LABView 上实现了相同的逻辑,结果仍然是 31Hz。谁能指出我的错误?我真的被困在这个问题上。

谢谢你的时间。

最佳答案

您应该将 Arduino 采样率固定为每秒 1000 个样本。

正如 Daniel 评论的那样,Arduino 正在尽可能快地工作,而不是以 1KHz 采样(而不是每秒采样 1000 个样本)。

您可以通过确保每次迭代需要 1000 微秒来修复您的 Arduino 循环以 1KHz 采样。

下面的循环读取每次迭代开始和结束时的时间。
在每次迭代结束时,都有一个延迟,完成持续时间为 1000us。

void loop() {
unsigned long start_time_us, delta_time_us;

//Returns the number of microseconds since the Arduino board began running the current program
//https://www.arduino.cc/reference/en/language/functions/time/micros/
start_time_us = micros();

Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625 );

//Passed time in microseconds.
delta_time_us = micros() - start_time_us;

if (delta_time_us < 1000)
{
//Delay the remaining time - complete to 1000us (keep sample rate at 1000 samples per second).
//https://www.arduino.cc/reference/en/language/functions/time/delaymicroseconds/
delayMicroseconds((unsigned long)1000 - delta_time_us);
}
}

请注意:我无法验证解决方案,因为我没有 Arduino 板(或模拟器)。

备注:以文本字符串形式发送样本效率低下,并且可能会导致串口饱和。

我建议您执行以下操作:
  • 发送二进制数据(使用 Serial.write 而不是 Serial.println )。
  • 而不是将样本转换为 double在从 Arduino 发送之前,将样本发送到 short格式(两个字节):发送值 (short)(analogRead(A5) - analogRead(A0)) .
  • 在MATLAB端,读取1000个二进制样本:sig = fread(s1, 1000, 'int16');
  • 在 MATLAB 中执行双倍和缩放样本的转换:sig = double(sig) * 0.009765625 .

  • Arduino代码:

    //Serial.println( (double)(analogRead(A5) - analogRead(A0))*0.009765625  ); 
    short analog_read = (short)(analogRead(A5) - analogRead(A0));
    Serial.write((uint8_t*)&analog_read, 2); //Send two bytes in int16 binary format

    MATLAB 代码:
    % for j = 1:LoS
    % str=fscanf(s1);
    % sen=str2double(str);
    % sig(j)=sen;
    % end
    sig = fread(s1, 1000, 'int16'); % Read 1000 analog samples (each sample is int16).
    sig = double(sig) * 0.009765625; % Convert 1000 samples to physical values in double format

    上面的代码对于 Arduino 和 MATLAB 都更有效。

    备注:请记住,我没有测试代码 - 它仅用于 演示 这个概念。

    关于matlab - Arduino和Matlab串行同步数据传输,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59575107/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com