Arduino巨型队列

时间:2011-09-03 19:04:24

标签: c++ arduino android-sensors

我写了这个简单的代码,它从Sharp红外传感器读取一个长度,结束时以cm(单位)为单位显示平均米。

当为Arduino Mega板写这个代码时,Arduino启动一个闪烁的LED(引脚13),程序什么都不做。这段代码中的错误在哪里?

#include <QueueList.h>

const int ANALOG_SHARP = 0; //Set pin data from sharp.
QueueList <float> queuea;
float cm;
float qu1;
float qu2;
float qu3;
float qu4;
float qu5;

void setup() {
    Serial.begin(9600);
}

void loop() {
    cm = read_gp2d12_range(ANALOG_SHARP); //Convert to cm (unit).
    queuea.push(cm); //Add item to queue, when I add only this line Arduino crash.
    if ( 5 <= queuea.peek()) {
        Serial.println(average());
    }
}

float read_gp2d12_range(byte pin) { //Function converting to cm (unit).
    int tmp;

    tmp = analogRead(pin);
    if (tmp < 3)
        return -1; // Invalid value.

    return (6787.0 /((float)tmp - 3.0)) - 4.0;
}

float average() { //Calculate average length
    qu1 += queuea.pop();
    qu2 += queuea.pop();
    qu3 += queuea.pop();
    qu4 += queuea.pop();
    qu5 += queuea.pop();

    float aver = ((qu1+qu2+qu3+qu4+qu5)/5);
    return aver;
}

3 个答案:

答案 0 :(得分:4)

我同意peek() - &gt; vhallac列出的count()错误。但我还要指出,除非有强烈的理由,否则你应该考虑以2的幂进行平均。

原因是在微控制器上,分工很慢。通过对2(2,4,8,16等)的幂进行平均,您可以简单地计算总和,然后将其移位。

计算2的平均值:(v1 + v2) >> 1

计算4的平均值:(v1 + v2 + v3 + v4) >> 2

要计算n个值的平均值(其中n是2的幂),只需右移位和[log2(n)]的和。

只要sum变量的数据类型足够大并且不会溢出,这就容易得多,速度也快得多。

注意:这通常不适用于浮点数。实际上,微控制器并未针对浮子进行优化。您应该考虑从int(我假设您正在读取ADC)转换到平均值​​之后的而不是之前。

通过从int转换为float然后平均浮点数,除了将int转换为浮点数之外,你输出的精度要高于平均值。

其他

您正在使用+=运算符而未初始化变量(qu1qu2等) - 如果您要使用{初始化它们,那么这是一种很好的做法{1}}但看起来好像+=可以正常工作。

对于浮点数,我已将=函数写为:

average

并称之为:float average(QueueList<float> & q, int n) { float sum = 0; for(int i=0; i<n; i++) { sum += q.pop(); } return (sum / (float) n); }

您可以使用它来平均任意数量的传感器读数,然后使用相同的代码来稍后在完全不同的QueueList中平均浮点数。在需要调整它的情况下,将读数的数量作为参数传递给平均值将非常方便。

TL; DR:

我将如何做到这一点:

average(queuea, 5);

答案 1 :(得分:1)

您正在使用queuea.peek()获取计数。这只会返回队列中的最后一个元素。您应该使用queuea.count()代替。

您也可以考虑将条件tmp < 3更改为tmp <= 3。如果tmp为3,则除以零。

答案 2 :(得分:0)

很好的改进,但我的第一个问题是为什么使用queuelist而不是int数组。

作为一个例子,我会做以下事情:

int average(int analog_reading)
{
    #define NUM_OF_AVG 5
    static int readings[NUM_OF_AVG];
    static int next_position;
    static int sum;

    if (++next_position >= NUM_OF_AVG)
    {
        next_position=0;
    }
    reading[next_position]=analog_reading;

    for(int i=0; i<NUM_OF_AVG; i++)
    {
        sum += reading[i];
    }
    average = sum/NUM_OF_AVG
}

现在我使用每个读数计算一个新的滚动平均值,它消除了嵌入式设备中与动态内存分配(内存碎片,无可用内存,内存泄漏)相关的所有问题。

我理解并理解使用2,4或8的除法进行移位,但是我会因为两个原因而远离这种技术。

我认为源代码的可读性和可维护性更重要,除非您可以测试并验证鸿沟是瓶颈,否则可以节省一点时间而不是除法。

其次,我相信大多数当前的优化编译器会尽可能地进行转换,我知道GCC会这样做。

我将为下一个人留下重构for循环。