#1 2017-06-16 11:21:23

Mondi851
Учасник
Зареєстрований: 2017-06-16
Повідомлень: 4

Измерение частоты, помогите найти ошибку в алгоритме суммирования

Измеряю частоту, помогите найти ошибку в алгоритме суммирования импульсов, вероятно она в  функции Isr_Timer()

External_counter считает импульсы по внешнему прерыванию

Isr_Timer() вызывается 64 раза в сек  и записывает  в текущий элемент скользящего буфера ( она на 64 элемента) подсчитанное в External_counter количество импульсов.

Тк колич элементов  буфера= количеству отсчетов в минуту, то сумма всех элементов буфера и есть частота. Сумму считаю двумя разными способами sum_A и sum_B и если бы не было моей ошибки (где она?), то суммы А и Б должны быть всегда равны, но они равны только тогда, когда External_counter стабилен хотя бы в течение периода обновления буфера, те 64 входа в функцию:

сумма Б = простое суммирование в цикле всех элементов буфера, а  сумма А =сумма А + External_counter минус самый старый элемент буфера, на место которого в текущий  раз будет записано значение  External_counter.

При изменяющемся External_counter sum_A и sum_B различаются примерно на значение одного элемента скользящего буфера.

Программа:

#define SZMB 64 // Размер буфера для усреднения частоты,  "равен" частоте прерываний по таймеру
static volatile int MB[SZMB]; // Moving Average Buffer = MBA
static volatile byte indexMB=0; // индекс текущей ячейки буфера

volatile int sum_A=0; // сумма буфера, быстрый способ  
volatile int sum_B=0; // сумма буфера, медленный способ
volatile int External_counter=0; // колич импульсов за 1 тик таймера 


void IRQ_routine(void){  External_counter++; /* счет импульсов*/}

void setup(void)
{
  Serial.begin(115200);
  int i;   for(i=0; i<SZMB; i++) MB[i]=0;
  //attachInterrupt(0, IRQ_routine,FALLING; // счет импулmсов 
  delay(200);  
  Serial.println("Begin------------------");
}

void loop(void)
{
 int ri; //"random" I 
  
  for(ri=0; ri<20; ri++) {External_counter=ri; Isr_Timer();}
  Serial.println("----stabile External_counter, qty of calls > 64---------");
  for(ri=0; ri<66; ri++) {External_counter=20; Isr_Timer();} // стабильный External_counter, колич вызовов >64
  Serial.println("----stabile External_counter end---------");
  for(ri=25; ri>0; ri--) {External_counter=ri; Isr_Timer();}
  for(ri=15; ri<21; ri++) {External_counter=ri; Isr_Timer();}
 
 }


void Isr_Timer()
//ISR (TIMER2_COMPA_vect) // вызывается по таймеру "64" раза в секунду
{
  byte i;
   // столько импульсов пришло за период между вызовами:
  Serial.print("ExtCnt=");Serial.print(External_counter); 
 
  sum_A = sum_A - MB[indexMB] + External_counter ;// сумма=сумма-(значение самого старого элемента буфера)+(значение, которое будет записано на его место в этом цикле)
  MB[indexMB]=External_counter; //  пишем колич импульсов в текущий элемент буфера
  External_counter=0; //сброс счетчика
  sum_B=0;  for(i=0; i<SZMB; i++) sum_B=sum_B+MB[indexMB]; // медленный способ расчета суммы скользящего буфера MB
  indexMB=(indexMB+1)&(SZMB-1); // остаток от деления на 63
  
  Serial.print(",  A=");Serial.print(sum_A);
  Serial.print(",   B="); Serial.println(sum_B);
  
  return;    
}

Печать отладки:

Begin------------------
ExtCnt=0,  A=0,   B=0
ExtCnt=1,  A=1,   B=64
ExtCnt=2,  A=3,   B=128
ExtCnt=3,  A=6,   B=192
ExtCnt=4,  A=10,   B=256
ExtCnt=5,  A=15,   B=320
ExtCnt=6,  A=21,   B=384
ExtCnt=7,  A=28,   B=448
ExtCnt=8,  A=36,   B=512
ExtCnt=9,  A=45,   B=576
ExtCnt=10,  A=55,   B=640
ExtCnt=11,  A=66,   B=704
ExtCnt=12,  A=78,   B=768
ExtCnt=13,  A=91,   B=832
ExtCnt=14,  A=105,   B=896
ExtCnt=15,  A=120,   B=960
ExtCnt=16,  A=136,   B=1024
ExtCnt=17,  A=153,   B=1088
ExtCnt=18,  A=171,   B=1152
ExtCnt=19,  A=190,   B=1216
----stabile External_counter, qty of calls > 64---------
ExtCnt=20,  A=210,   B=1280
ExtCnt=20,  A=230,   B=1280
ExtCnt=20,  A=250,   B=1280
ExtCnt=20,  A=270,   B=1280
ExtCnt=20,  A=290,   B=1280
ExtCnt=20,  A=310,   B=1280
ExtCnt=20,  A=330,   B=1280
ExtCnt=20,  A=350,   B=1280
ExtCnt=20,  A=370,   B=1280
ExtCnt=20,  A=390,   B=1280
ExtCnt=20,  A=410,   B=1280
ExtCnt=20,  A=430,   B=1280
ExtCnt=20,  A=450,   B=1280
ExtCnt=20,  A=470,   B=1280
ExtCnt=20,  A=490,   B=1280
ExtCnt=20,  A=510,   B=1280
ExtCnt=20,  A=530,   B=1280
ExtCnt=20,  A=550,   B=1280
ExtCnt=20,  A=570,   B=1280
ExtCnt=20,  A=590,   B=1280
ExtCnt=20,  A=610,   B=1280
ExtCnt=20,  A=630,   B=1280
ExtCnt=20,  A=650,   B=1280
ExtCnt=20,  A=670,   B=1280
ExtCnt=20,  A=690,   B=1280
ExtCnt=20,  A=710,   B=1280
ExtCnt=20,  A=730,   B=1280
ExtCnt=20,  A=750,   B=1280
ExtCnt=20,  A=770,   B=1280
ExtCnt=20,  A=790,   B=1280
ExtCnt=20,  A=810,   B=1280
ExtCnt=20,  A=830,   B=1280
ExtCnt=20,  A=850,   B=1280
ExtCnt=20,  A=870,   B=1280
ExtCnt=20,  A=890,   B=1280
ExtCnt=20,  A=910,   B=1280
ExtCnt=20,  A=930,   B=1280
ExtCnt=20,  A=950,   B=1280
ExtCnt=20,  A=970,   B=1280
ExtCnt=20,  A=990,   B=1280
ExtCnt=20,  A=1010,   B=1280
ExtCnt=20,  A=1030,   B=1280
ExtCnt=20,  A=1050,   B=1280
ExtCnt=20,  A=1070,   B=1280
ExtCnt=20,  A=1090,   B=1280
ExtCnt=20,  A=1109,   B=1280
ExtCnt=20,  A=1127,   B=1280
ExtCnt=20,  A=1144,   B=1280
ExtCnt=20,  A=1160,   B=1280
ExtCnt=20,  A=1175,   B=1280
ExtCnt=20,  A=1189,   B=1280
ExtCnt=20,  A=1202,   B=1280
ExtCnt=20,  A=1214,   B=1280
ExtCnt=20,  A=1225,   B=1280
ExtCnt=20,  A=1235,   B=1280
ExtCnt=20,  A=1244,   B=1280
ExtCnt=20,  A=1252,   B=1280
ExtCnt=20,  A=1259,   B=1280
ExtCnt=20,  A=1265,   B=1280
ExtCnt=20,  A=1270,   B=1280
ExtCnt=20,  A=1274,   B=1280
ExtCnt=20,  A=1277,   B=1280
ExtCnt=20,  A=1279,   B=1280
ExtCnt=20,  A=1280,   B=1280
ExtCnt=20,  A=1280,   B=1280
ExtCnt=20,  A=1280,   B=1280
----stabile External_counter end---------
ExtCnt=25,  A=1285,   B=1600
ExtCnt=24,  A=1289,   B=1536
ExtCnt=23,  A=1292,   B=1472
ExtCnt=22,  A=1294,   B=1408
ExtCnt=21,  A=1295,   B=1344
ExtCnt=20,  A=1295,   B=1280
ExtCnt=19,  A=1294,   B=1216
ExtCnt=18,  A=1292,   B=1152
ExtCnt=17,  A=1289,   B=1088
ExtCnt=16,  A=1285,   B=1024
ExtCnt=15,  A=1280,   B=960
ExtCnt=14,  A=1274,   B=896
ExtCnt=13,  A=1267,   B=832
ExtCnt=12,  A=1259,   B=768
ExtCnt=11,  A=1250,   B=704
ExtCnt=10,  A=1240,   B=640
ExtCnt=9,  A=1229,   B=576
ExtCnt=8,  A=1217,   B=512
ExtCnt=7,  A=1204,   B=448
ExtCnt=6,  A=1190,   B=384
ExtCnt=5,  A=1175,   B=320
ExtCnt=4,  A=1159,   B=256
ExtCnt=3,  A=1142,   B=192
ExtCnt=2,  A=1124,   B=128
ExtCnt=1,  A=1105,   B=64
ExtCnt=15,  A=1100,   B=960
ExtCnt=16,  A=1096,   B=1024
ExtCnt=17,  A=1093,   B=1088
ExtCnt=18,  A=1091,   B=1152
ExtCnt=19,  A=1090,   B=1216
ExtCnt=20,  A=1090,   B=1280
ExtCnt=0,  A=1070,   B=0
ExtCnt=1,  A=1051,   B=64
ExtCnt=2,  A=1033,   B=128
ExtCnt=3,  A=1016,   B=192
ExtCnt=4,  A=1000,   B=256
ExtCnt=5,  A=985,   B=320
ExtCnt=6,  A=971,   B=384
ExtCnt=7,  A=958,   B=448
ExtCnt=8,  A=946,   B=512
ExtCnt=9,  A=935,   B=576
ExtCnt=10,  A=925,   B=640
ExtCnt=11,  A=916,   B=704
ExtCnt=12,  A=908,   B=768
ExtCnt=13,  A=901,   B=832
ExtCnt=14,  A=895,   B=896
ExtCnt=15,  A=890,   B=960
ExtCnt=16,  A=886,   B=1024
ExtCnt=17,  A=883,   B=1088
ExtCnt=18,  A=881,   B=1152
ExtCnt=19,  A=880,   B=1216
----stabile External_counter, qty of calls > 64---------
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=875,   B=1280
ExtCnt=20,  A=871,   B=1280
ExtCnt=20,  A=868,   B=1280
ExtCnt=20,  A=866,   B=1280
ExtCnt=20,  A=865,   B=1280
ExtCnt=20,  A=865,   B=1280
ExtCnt=20,  A=866,   B=1280
ExtCnt=20,  A=868,   B=1280
ExtCnt=20,  A=871,   B=1280
ExtCnt=20,  A=875,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=886,   B=1280
ExtCnt=20,  A=893,   B=1280
ExtCnt=20,  A=901,   B=1280
ExtCnt=20,  A=910,   B=1280
ExtCnt=20,  A=920,   B=1280
ExtCnt=20,  A=931,   B=1280
ExtCnt=20,  A=943,   B=1280
ExtCnt=20,  A=956,   B=1280
ExtCnt=20,  A=970,   B=1280
ExtCnt=20,  A=985,   B=1280
ExtCnt=20,  A=1001,   B=1280
ExtCnt=20,  A=1018,   B=1280
ExtCnt=20,  A=1036,   B=1280
ExtCnt=20,  A=1055,   B=1280
ExtCnt=20,  A=1060,   B=1280
ExtCnt=20,  A=1064,   B=1280
ExtCnt=20,  A=1067,   B=1280
ExtCnt=20,  A=1069,   B=1280
ExtCnt=20,  A=1070,   B=1280
ExtCnt=20,  A=1070,   B=1280
ExtCnt=20,  A=1090,   B=1280
ExtCnt=20,  A=1109,   B=1280
ExtCnt=20,  A=1127,   B=1280
ExtCnt=20,  A=1144,   B=1280
ExtCnt=20,  A=1160,   B=1280
ExtCnt=20,  A=1175,   B=1280
ExtCnt=20,  A=1189,   B=1280
ExtCnt=20,  A=1202,   B=1280
ExtCnt=20,  A=1214,   B=1280
ExtCnt=20,  A=1225,   B=1280
ExtCnt=20,  A=1235,   B=1280
ExtCnt=20,  A=1244,   B=1280
ExtCnt=20,  A=1252,   B=1280
ExtCnt=20,  A=1259,   B=1280
ExtCnt=20,  A=1265,   B=1280
ExtCnt=20,  A=1270,   B=1280
ExtCnt=20,  A=1274,   B=1280
ExtCnt=20,  A=1277,   B=1280
ExtCnt=20,  A=1279,   B=1280
ExtCnt=20,  A=1280,   B=1280
ExtCnt=20,  A=1280,   B=1280
ExtCnt=20,  A=1280,   B=1280
----stabile External_counter end---------
ExtCnt=25,  A=1285,   B=1600
ExtCnt=24,  A=1289,   B=1536
ExtCnt=23,  A=1292,   B=1472
ExtCnt=22,  A=1294,   B=1408
ExtCnt=21,  A=1295,   B=1344
ExtCnt=20,  A=1295,   B=1280
ExtCnt=19,  A=1294,   B=1216
ExtCnt=18,  A=1292,   B=1152
ExtCnt=17,  A=1289,   B=1088
ExtCnt=16,  A=1285,   B=1024
ExtCnt=15,  A=1280,   B=960
ExtCnt=14,  A=1274,   B=896
ExtCnt=13,  A=1267,   B=832
ExtCnt=12,  A=1259,   B=768
ExtCnt=11,  A=1250,   B=704
ExtCnt=10,  A=1240,   B=640
ExtCnt=9,  A=1229,   B=576
ExtCnt=8,  A=1217,   B=512
ExtCnt=7,  A=1204,   B=448
ExtCnt=6,  A=1190,   B=384
ExtCnt=5,  A=1175,   B=320
ExtCnt=4,  A=1159,   B=256
ExtCnt=3,  A=1142,   B=192
ExtCnt=2,  A=1124,   B=128
ExtCnt=1,  A=1105,   B=64
ExtCnt=15,  A=1100,   B=960
ExtCnt=16,  A=1096,   B=1024
ExtCnt=17,  A=1093,   B=1088
ExtCnt=18,  A=1091,   B=1152
ExtCnt=19,  A=1090,   B=1216
ExtCnt=20,  A=1090,   B=1280
ExtCnt=0,  A=1070,   B=0
ExtCnt=1,  A=1051,   B=64
ExtCnt=2,  A=1033,   B=128
ExtCnt=3,  A=1016,   B=192
ExtCnt=4,  A=1000,   B=256
ExtCnt=5,  A=985,   B=320
ExtCnt=6,  A=971,   B=384
ExtCnt=7,  A=958,   B=448
ExtCnt=8,  A=946,   B=512
ExtCnt=9,  A=935,   B=576
ExtCnt=10,  A=925,   B=640
ExtCnt=11,  A=916,   B=704
ExtCnt=12,  A=908,   B=768
ExtCnt=13,  A=901,   B=832
ExtCnt=14,  A=895,   B=896
ExtCnt=15,  A=890,   B=960
ExtCnt=16,  A=886,   B=1024
ExtCnt=17,  A=883,   B=1088
ExtCnt=18,  A=881,   B=1152
ExtCnt=19,  A=880,   B=1216
----stabile External_counter, qty of calls > 64---------
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=880,   B=1280
ExtCnt=20,  A=875,   B=1280
ExtCnt=20,  A=871,   B=1280
ExtCnt=20,  A=868,   B=1280
ExtCnt=20,  A=866,   B=1280
ExtCnt=20,  A=865,   B=1280
ExtCnt=20,  A=865,   B=1280
ExtCnt=20,  A=866,   B=1280
ExtCnt=20,  A=868,   B=1280
ExtCnt=20,  A=871,   B=1280

Неактивний

#2 2017-06-16 16:12:52

Mondi851
Учасник
Зареєстрований: 2017-06-16
Повідомлень: 4

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

Вячеслав Азаров пише:

Вы не учитываете эффект округления выборок. При таком методе ошибка будет в 64 раза большей чем при прямом. Используйте аппаратные возможности таймеров для решения вашей задачи.

Вячеслав, я начинающий. Можно подробнее  ошибка чего - суммы количества импульсов?
Что такое прямой метод и какие аппаратные возможности таймеров советуете использовать для измерения частоты?

Частота может изменяться в пределах 0-1500 Гц, усредняю на интервале 1 сек, обновление интервалами по 1/64 сек

Неактивний

#3 2017-06-20 11:22:31

Mondi851
Учасник
Зареєстрований: 2017-06-16
Повідомлень: 4

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

Вячеслав Азаров пише:
Mondi851 пише:

Частота может изменяться в пределах 0-1500 Гц, усредняю на интервале 1 сек, обновление интервалами по 1/64 сек

В вашем случае, для прямого метода, ошибка по частоте будет не менее 64 Гц. Усреднив вы не получите что то среднее, поскольку закон распределения ошибок не случайный а зависит от соотношения измеряемой частоты и частоты измерений.

Непонятно происхождение ошибки в 64 Гц.
Если бы я измерял количенство импульсов за 1/64 сек и умножал бы на 64 тогда да, тк любой лишний или недостающий импульс  в интервале 1/64 при умножении на 64 даст ошибку не менее 64 Гц.

Неактивний

#4 2017-06-20 14:42:15

Green
Учасник
Зареєстрований: 2015-11-08
Повідомлень: 593

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

А всегда ли получится строго 1/64 сек от таймера? Прерывания от других источников не мешают?

Остання редакція Green (2017-06-20 14:42:46)

Неактивний

#5 2017-06-20 15:00:00

Mondi851
Учасник
Зареєстрований: 2017-06-16
Повідомлень: 4

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

Green пише:

А всегда ли получится строго 1/64 сек от таймера?

При тактовой частоте 16 МГц никогда не получится строго 64 Гц, так как  прескалером и счетным регистром нацело не делится, а дробное значение счетного регистра 244,1406 физически невозможно.
Так что реальная частота при 244 получается 64,0369 Гц - такая погрешность меня вполне устраивает.

Green пише:

Прерывания от других источников не мешают?

В этом проекте не мешают, а в принципе такое возможно.

Неактивний

#6 2017-06-20 22:05:56

Green
Учасник
Зареєстрований: 2015-11-08
Повідомлень: 593

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

Обычно ворота формируются либо когда никто не мешает, но и тогда приходится считать до каждого такта, либо аппаратно.

Неактивний

#7 2017-06-20 23:29:58

Green
Учасник
Зареєстрований: 2015-11-08
Повідомлень: 593

Re: Измерение частоты, помогите найти ошибку в алгоритме суммирования

На низкой частоте (относительно). На высокой же - наоборот. А ежели с прескаллером?

Неактивний

Швидке повідомлення

Введіть повідомлення і натисніть Надіслати

Підвал форуму