Ви не увійшли.
Измеряю частоту, помогите найти ошибку в алгоритме суммирования импульсов, вероятно она в функции 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
Неактивний
Вы не учитываете эффект округления выборок. При таком методе ошибка будет в 64 раза большей чем при прямом. Используйте аппаратные возможности таймеров для решения вашей задачи.
Вячеслав, я начинающий. Можно подробнее ошибка чего - суммы количества импульсов?
Что такое прямой метод и какие аппаратные возможности таймеров советуете использовать для измерения частоты?
Частота может изменяться в пределах 0-1500 Гц, усредняю на интервале 1 сек, обновление интервалами по 1/64 сек
Неактивний
Mondi851 пише:Частота может изменяться в пределах 0-1500 Гц, усредняю на интервале 1 сек, обновление интервалами по 1/64 сек
В вашем случае, для прямого метода, ошибка по частоте будет не менее 64 Гц. Усреднив вы не получите что то среднее, поскольку закон распределения ошибок не случайный а зависит от соотношения измеряемой частоты и частоты измерений.
Непонятно происхождение ошибки в 64 Гц.
Если бы я измерял количенство импульсов за 1/64 сек и умножал бы на 64 тогда да, тк любой лишний или недостающий импульс в интервале 1/64 при умножении на 64 даст ошибку не менее 64 Гц.
Неактивний
А всегда ли получится строго 1/64 сек от таймера?
При тактовой частоте 16 МГц никогда не получится строго 64 Гц, так как прескалером и счетным регистром нацело не делится, а дробное значение счетного регистра 244,1406 физически невозможно.
Так что реальная частота при 244 получается 64,0369 Гц - такая погрешность меня вполне устраивает.
Прерывания от других источников не мешают?
В этом проекте не мешают, а в принципе такое возможно.
Неактивний