Округление среднего становится все хуже - PullRequest
0 голосов
/ 11 октября 2019

Я пытаюсь усреднить показания датчика высоты с помощью Arduino, но со временем разрешение становится все хуже и хуже, хотя исходные данные остаются неизменными.

Все переменные, которые явно не определены в этом коде, являются числами с плавающей запятой.

altTotal = 0.00;
slopeTotal = 0.00;

altitude = ps.readFloatAltitudeMeters();

//=========== Altitude averaging
for (int j = 0.00; j <=(aveNum-2); j++) {
  arrAlt[j] = arrAlt[j+1];
}

arrAlt[aveNum-1] = altitude;

for (i = 0.00; i <= (aveNum-1); i++){
  altTotal = altTotal + arrAlt[i];
}

altAve = altTotal/(i);
//============

f = f+1;
altRd = altRd + altAve;

if (f == 5) {

//======== check cycle time
unsigned long endCycle = micros();
unsigned long delta = endCycle - start;
delta = delta/1000;
unsigned long start = endCycle;


loop1 = loop2;
loop2 = delta;
loopTime = loop2-loop1;
//========

  v0 = v1;
  v1 = v2;
  v2 = altRd/f - v0 - 2*v1;
  altButt = v0 + 2*v1 + v2;

  alt1 = alt2;
  alt2 = altButt;
  climbRate = (alt2 - alt1) * (1000/loopTime); //to convert climb rate to m/s

  //climbRate = -5;

  f = 0;
  altRd = 0;

}

Я ожидаю, что выходные данные "liftRate" будут иметь согласованное разрешение, но со временем разрешение получитсяхуже, кратно двум. Сначала он начинается с разрешения 0,006, затем 0,012, затем 0,023, затем 0,047, затем 0,094 и т. Д.

Вот пример выходных данных:

0.000,m/s ,0,0.10,328ms ,0.00m altRd ,1603.11m altButt
0.000,m/s ,0,0.10,328ms ,1603.12m altRd ,1603.11m altButt
0.000,m/s ,0,0.10,328ms ,3206.23m altRd ,1603.11m altButt
0.000,m/s ,0,0.10,328ms ,4809.35m altRd ,1603.11m altButt
0.000,m/s ,0,0.10,328ms ,6412.46m altRd ,1603.11m altButt
0.023,m/s ,0,0.10,328ms ,0.00m altRd ,1603.12m altButt
0.023,m/s ,0,0.10,328ms ,1603.12m altRd ,1603.12m altButt
0.023,m/s ,0,0.10,328ms ,3206.24m altRd ,1603.12m altButt
0.023,m/s ,0,0.10,328ms ,4809.37m altRd ,1603.12m altButt
0.023,m/s ,0,0.10,328ms ,6412.51m altRd ,1603.12m altButt
0.047,m/s ,0,0.10,328ms ,0.00m altRd ,1603.13m altButt
0.047,m/s ,0,0.10,328ms ,1603.14m altRd ,1603.13m altButt
0.047,m/s ,0,0.10,328ms ,3206.28m altRd ,1603.13m altButt
0.047,m/s ,0,0.10,328ms ,4809.42m altRd ,1603.13m altButt
0.047,m/s ,0,0.10,328ms ,6412.55m altRd ,1603.13m altButt

Я не уверен, гдевозникает проблема.

У меня были некоторые переменные разных типов, но я превратил их в плавающие числа, чтобы увеличить разрешение, но безуспешно.

Ответы [ 2 ]

1 голос
/ 12 октября 2019

Я не могу сказать вам, где именно ошибка, учитывая приведенный выше пример, но я могу сказать вам, что является причиной проблемы и что нужно искать для ее устранения.

Ваш код численно нестабилен. Реальные значения выражаются через с плавающей запятой в C ++, как и в большинстве других языков (вводится новый более точный стандарт, но он не широко доступен).

float имеет 23 битадля точности значения, то есть его точность составляет около 10 ^ {- 7} от его значения. Все, что ниже этого, усекается.

Например: 2e7f + 1 == 2e7f равно true, потому что слишком мало, учитывая точность с плавающей запятой.

Скорее всего, где-то в вашем коде вы берете разницуиз двух все более больших переменных с плавающей запятой, в результате чего их разность становится все меньше и меньше с течением времени.

Чтобы исправить это, вы можете работать с double вместо float. Если вы не можете этого сделать или этого недостаточно, вам нужно сделать свой код более устойчивым в числовом отношении ... это может быть сложно ... это не легко объяснить в кратком ответе. Ищите учебники по этому вопросу.

0 голосов
/ 16 октября 2019

Так что мой код действительно численно нестабилен. Источником этого являются большие числа со многими десятичными знаками, которые в конечном итоге просто усекаются в вычислениях. Я не могу изменить ни одно из чисел, чтобы сделать их меньше, так как мне нужно использовать весь диапазон. Поэтому вместо того, чтобы перестроить решение, я просто применил следующее исправление:

Раз в минуту я просто сбрасываю все числа, которые вызывают проблему, к нулю. Небольшая неточность, которую я получаю, пренебрежимо мала, и мой код остается точным с точностью до трех знаков после запятой (я проверял его в течение 24 часов, и он работает отлично).

Спасибо за помощь.

...