嵌入式单片机 Arduino,在 loop 函数内多次使用过滤器会输出异常?

2022-04-13 20:19:48 +08:00
 ALLROBOT

说明

如果 loop 只运行一个模拟引脚,并且使用一个过滤器,即可正常输出( 0~500 ),但是创建数组储存多个过滤后的模拟引脚数值就有问题了,输出异常(1000~20000)

输出正常的代码

#include "EMGFilters.h"
const int SensorInputPin[] = {A0, A1, A2, A3, A4, A5};
EMGFilters myFilter;
SAMPLE_FREQUENCY sampleRate = SAMPLE_FREQ_500HZ;
NOTCH_FREQUENCY humFreq = NOTCH_FREQ_50HZ;
void setup() 
{
  myFilter.init(sampleRate, humFreq, true, true, true);
  Serial.begin(115200);
}
void loop() 
{
    Serial.println(square(myFilter.update(analogRead(SensorInputPin[0]))));
}
long unsigned int square(unsigned int x)
{
    return (x * x);
}

正常输出

输出异常的代码

只修改 loop

void loop()
{
    int envelops[12] = {0};
    for (int i = 0; i < 2; i++)
    {
        for (int x = 0; x < 6; x++)
        {
            envelops[i * 6 + x] = square(myFilter.update(analogRead(SensorInputPin[x])));
        }
        delayMicroseconds(50);
        Serial.println(envelops[i * 6 + 1]);
    }
}

异常输出

检查

我搞不懂了,逐次打印看看变量名

void loop() 
{
    int envelops[12];
    for (int i = 0; i < 2; i++)
    {
        int ii = 0;
        for (int x = 0; x < 6; x++)
        {
            Serial.printf("i:%d  x:%d\n", i, x);
            envelops[((i * 6) + x)] = square(myFilter.update(analogRead(SensorInputPin[x])));
            Serial.printf("Output:%d index: %d\n", envelops[((i * 6) + x)], ((i * 6) + x));
        }
        ii++;
        delay(1000);
    }

}
long unsigned int square(unsigned int x) {
    return (x*x);
}

输出

搞不明白,咋输出上万的值了呢?

再看看正常输出的

void loop() 
{
    int x1= square(myFilter.update(analogRead(SensorInputPin[0])));
    Serial.printf("analogRead:%d\n",analogRead(SensorInputPin[0]));
    Serial.printf("output:%d\n",x1);
    delay(1000);

}

输出

这很正常啊,怎么一用 for 循环函数就有问题了😂

然后尝试

void loop() 
{
    int x1= square(myFilter.update(analogRead(SensorInputPin[0])));
    int x2=square(myFilter.update(analogRead(SensorInputPin[1])));
    int x3=square(myFilter.update(analogRead(SensorInputPin[2])));
    int x4=square(myFilter.update(analogRead(SensorInputPin[3])));
    int x5=square(myFilter.update(analogRead(SensorInputPin[4])));
    int x6= square(myFilter.update(analogRead(SensorInputPin[5])));
        Serial.printf("analogRead:%d\n",analogRead(SensorInputPin[0]));
    Serial.printf("output:%d\n",x1);
    delay(1000);

}

输出

发现原本输出动辄几万的,已经下降到一千左右了,但仍然是异常输出

过滤器就是一个函数计算输出的,怎么调用的时候出现问题了?

loop 仅用一条指令Serial.println(square(myFilter.update(analogRead(每个模拟引脚输入)))),正常输出 0~500 的值,如果用多个变量或 for 啥,就输出上万的值了。。。我尝试创建多个过滤器,给每个输入单独用Filter1,Filter2等等,问题依旧。。。

过滤器代码链接:https://github.com/oymotion/EMGFilters/blob/master/EMGFilters.cpp

咋解决啊😂

1306 次点击
所在节点    程序员
16 条回复
Eiden
2022-04-13 20:33:21 +08:00
每一路输入都需要新建一个过滤器对象吧
ALLROBOT
2022-04-13 20:39:42 +08:00
@Eiden #1 我曾经尝试这么做,EMGFilters myFilters[6]; 先初始化然后在 loop 使用 envelops[i * 6 + x] = square(myFilters[x].update(analogRead(SensorInputPin[x])));,问题依旧
Eiden
2022-04-13 20:40:01 +08:00
@Eiden #1 没看到后面...
villivateur
2022-04-13 21:15:10 +08:00
具体是什么单片机啊?如果有 FPU 的话尝试把 FPU 关掉试试看
ALLROBOT
2022-04-13 22:08:12 +08:00
@villivateur #4 用的 Seeeduino XIAO

微控制器 XIAO 一般说明: https://wiki.seeedstudio.com/Seeeduino-XIAO/

微控制器 XIAO 说明手册: https://files.seeedstudio.com/wiki/Seeeduino-XIAO/res/ATSAMD21G18A-MU-Datasheet.pdf

我是硬件半吊子的,所以才学 Arduino😂,图它 Arduino 原型设计快的,我不知道 XIAO 的 MCU 是否有 FPU
ALLROBOT
2022-04-14 00:13:23 +08:00
@Eiden #1 @villivateur #4 发现在 loop 函数使用 1,2 个传感器的过滤器,是正常输出的,但增加过滤器时就异常输出了

是单片机自己的问题吗?实在解决不了,推荐啥 Arduino 采集 MCU ?😂在 XIAO 浪费了太多时间
DataSheep
2022-04-14 08:23:51 +08:00
跟单片机应该没关系,每个滤波器新建一个实例对象是应该的,另外这个滤波器库既然有采样频率参数你应该需要控制采样间隔,好像没看到有写,注意滤波计算也是需要毫秒级时间的,根据运算能力差异非常大。根据你的描述很可能是这个原因。

btw ,这个东西你好像捣鼓蛮久了😀
ALLROBOT
2022-04-14 11:42:01 +08:00
@DataSheep #7 不好意思,嵌入式很少涉及(没学过数电模电),每月只有几天的空闲时间来研究 Arduino 的,没能折腾出什么结果

https://gist.github.com/allrobot/1d105671a5186adb792bfbc5d8bd5030

我曾经为每个输出添加 500 微秒、1 毫秒、或 5 毫秒来控制采样频率,但均为输出异常😂



上面的黄线似乎是随机的,如果 index 为 4 个,即输出 4 个滤波计算的值,第 2 ,4 个输出异常; index 为 3 个的话,第 3 个输出异常; index 再次为 4 个,第 3 个和第 4 个模拟引脚输出异常。。。
sujin190
2022-04-14 13:38:42 +08:00
不滤波也异常的那那就是读取问题?似乎看不出来是滤波异常还是读取异常啊
ALLROBOT
2022-04-14 14:51:26 +08:00
@sujin190 #9 两个开发板都试了,每个 ADC 读数都不一致,应该是读数的问题
DataSheep
2022-04-14 15:01:54 +08:00
@ALLROBOT 你没理解我意思,你既然选择的频率是 500 ,那么采样间隔需要控制在 2 毫秒。
也就是 update 间隔需要严格控制在 2 毫秒,而且一般也是用定时器中断来控制,不过 arduino 一般不用中断。所以如果你要用我 delay 来控制采样间隔的话,需要把函数运行时间也加进去,那么延时时间会在 0-2 毫秒之间,具体需要计算一下你的函数运行时间是多久。
darkengine
2022-04-14 21:32:01 +08:00
应该把 square(myFilter.update(analogRead(SensorInputPin[x]))) 这里每个调用的中间结果打出来,才知道是哪个函数调用出的问题吧。
ALLROBOT
2022-04-14 22:17:41 +08:00
@DataSheep #11 这样的话,也只是在 loop 函数加 long time=millis();在执行过滤器语句的下面( loop 函数末尾)增加 while((millis()-time)<2){delayMicroseconds(100);}

对于异常输出没有什么太大改善

就这样暂时将就吧,肌肉运动能看到一点起伏
DataSheep
2022-04-14 22:30:19 +08:00
@ALLROBOT 如果还有问题,确认 ad 读取没问题的话滤波函数可以自己写的。
这东西看你踩的坑太多了,不如上个树莓派用 python 早搞定了
ALLROBOT
2022-04-14 22:36:25 +08:00
@darkengine #12 7 小时前用 analogread 函数读数已经检测出问题所在,是 ADC 读数不一致产生了问题



只要连续读取 A0 ,A1 模拟引脚没问题,连续读取 A0,A1,A2,A3,A4 就产生了问题,不知道为啥
ALLROBOT
2022-04-14 22:43:29 +08:00
@darkengine #12 噢,好吧,收回之前的话,这是中午的测试图,现在的测试图如下:


Serial.printf("%d %d %d %d %d %d\n",analogRead(A0),analogRead(A1),analogRead(A2),analogRead(A3),analogRead(A4),analogRead(A5));

模拟输出太莫名其妙了。。。中午的电路接线结构没啥变动,到了现在输出乱七八糟了😂


@DataSheep #14 也许你说得对。。。。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/846802

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX