嵌入式单片机 Arduino,在 loop 函数内多次使用过滤器会输出异常? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
请不要在回答技术问题时复制粘贴 AI 生成的内容
ALLROBOT
V2EX    程序员

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

  •  
  •   ALLROBOT 2022 年 4 月 13 日 1688 次点击
    这是一个创建于 1392 天前的主题,其中的信息可能已经有所发展或是发生改变。

    说明

    如果 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); } 

    正常输出

    2022-04-13--16-59-08_fps=8_scale=720_max_colors=128|404x500

    输出异常的代码

    只修改 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

    咋解决啊

    第 1 条附言    2022 年 4 月 14 日
    尝试一个个的增加过滤器以及模拟引脚,输出第一个和第二个没什么问题

    ```C
    \\略
    EMGFilters out1;
    out1.init(sampleRate, humFreq, true, true, true);
    \\略
    void loop()
    {
    int x[2]= {square(out1.update(analogRead(SensorInputPin[0]))), square(out2.update(analogRead(SensorInputPin[1])))};
    Serial.printf("%d %d\n", x[0], x[1]);
    }
    ```




    我发现模拟输入当增加到第三个时输出异常

    ```C
    void loop()
    {
    int x[3]= {square(out1.update(analogRead(SensorInputPin[0]))), square(out2.update(analogRead(SensorInputPin[1]))), square(out3.update(analogRead(SensorInputPin[2])))};
    Serial.printf("%d %d %d\n", x[0], x[1], x[2]);
    }
    ```



    loop 函数只使用第三个模拟输入,不使用其它模拟引脚的过滤器转换输出,是正常输出的

    Eiden
        1
    Eiden  
       2022 年 4 月 13 日
    每一路输入都需要新建一个过滤器对象吧
    ALLROBOT
        2
    ALLROBOT  
    OP
       2022 年 4 月 13 日
    @Eiden #1 我曾经尝试这么做,EMGFilters myFilters[6]; 先初始化然后在 loop 使用 envelops[i * 6 + x] = square(myFilters[x].update(analogRead(SensorInputPin[x])));,问题依旧
    Eiden
        3
    Eiden  
       2022 年 4 月 13 日
    @Eiden #1 没看到后面...
    villivateur
        4
    villivateur  
       2022 年 4 月 13 日
    具体是什么单片机啊?如果有 FPU 的话尝试把 FPU 关掉试试看
    ALLROBOT
        5
    ALLROBOT  
    OP
       2022 年 4 月 13 日
    @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
        6
    ALLROBOT  
    OP
       2022 年 4 月 14 日
    @Eiden #1 @villivateur #4 发现在 loop 函数使用 1,2 个传感器的过滤器,是正常输出的,但增加过滤器时就异常输出了

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

    btw ,这个东西你好像捣鼓蛮久了
    ALLROBOT
        8
    ALLROBOT  
    OP
       2022 年 4 月 14 日
    @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
        9
    sujin190  
       2022 年 4 月 14 日
    不滤波也异常的那那就是读取问题?似乎看不出来是滤波异常还是读取异常啊
    ALLROBOT
        10
    ALLROBOT  
    OP
       2022 年 4 月 14 日
    @sujin190 #9 两个开发板都试了,每个 ADC 读数都不一致,应该是读数的问题
    DataSheep
        11
    DataSheep  
       2022 年 4 月 14 日 via iPhone
    @ALLROBOT 你没理解我意思,你既然选择的频率是 500 ,那么采样间隔需要控制在 2 毫秒。
    也就是 update 间隔需要严格控制在 2 毫秒,而且一般也是用定时器中断来控制,不过 arduino 一般不用中断。所以如果你要用我 delay 来控制采样间隔的话,需要把函数运行时间也加进去,那么延时时间会在 0-2 毫秒之间,具体需要计算一下你的函数运行时间是多久。
    darkengine
        12
    darkengine  
       2022 年 4 月 14 日
    应该把 square(myFilter.update(analogRead(SensorInputPin[x]))) 这里每个调用的中间结果打出来,才知道是哪个函数调用出的问题吧。
    ALLROBOT
        13
    ALLROBOT  
    OP
       2022 年 4 月 14 日
    @DataSheep #11 这样的话,也只是在 loop 函数加 long time=millis();在执行过滤器语句的下面( loop 函数末尾)增加 while((millis()-time)<2){delayMicroseconds(100);}

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

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



    只要连续读取 A0 ,A1 模拟引脚没问题,连续读取 A0,A1,A2,A3,A4 就产生了问题,不知道为啥
    ALLROBOT
        16
    ALLROBOT  
    OP
       2022 年 4 月 14 日
    @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 也许你说得对。。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     3984 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 28ms UTC 09:46 PVG 17:46 LAX 01:46 JFK 04:46
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86