Доброго времени суток! Решил собрать лазерный тахометр на ардуино. И все вроде бы ничего, собрал, простенький скетч написал, загрузил.. Все работает, все хорошо. Но ввиду того, что скетч именно "простенький", он не считает среднее значение. И вот на просторах интернета нарвался на проект тахометра с более серьезным подходом к расчетам. Одна беда, после заливки показывает все, что угодно, но только не реальные обороты. Может кто посмотрит и подскажет, где косяк в коде... Код (C++): #include <OLED_I2C.h> // Подключаем библиотеку OLED_I2C для работы со шрифтами и графикой OLED myOLED(SDA, SCL, 8); // Определяем пины I2C интерфейса extern uint8_t SmallFont[]; // Подключаем шрифт extern uint8_t BigNumbers[]; // Подключаем большие цифры #define LASER 5 // Задаем имя для Pin5 включения лазера const byte sensor = 7; // Задаем Pin7 для датчика лазера volatile unsigned long t_pulse_started_volatile = 0; volatile unsigned long t_pulse_duration_volatile = 0; unsigned long t_pulse_started = 0; unsigned long t_pulse_duration = 0; long rpm_sum = 0; long rpm_reading[100]; long rpm_average = 0; byte n_max = 0; byte n = 0; volatile bool timeout = 1; volatile bool newpulse = 0; void setup() { pinMode(LASER, OUTPUT); // Определяем пин Лазера как выход pinMode(sensor, INPUT); // Определяем пин Датчика как вход myOLED.begin(); // Инициируем дисплей attachInterrupt(digitalPinToInterrupt(sensor), ISR_sensor, RISING); // Запускаем прерывания } void loop() { digitalWrite(LASER,HIGH); // Определяем уровень на пине Лазера как высокий noInterrupts(); // Отключаем прерывания t_pulse_started = t_pulse_started_volatile; t_pulse_duration = t_pulse_duration_volatile; interrupts(); if(((micros() - t_pulse_started) > 2000000) && timeout == 0 && newpulse == 0) { timeout = 1; rpm_average = 0; n = 0; }; if(timeout == 0){ if(newpulse == 1){ rpm_reading[n] = (60000000 / t_pulse_duration); n_max = constrain(map(rpm_reading[n], 60, 100000, 0, 100), 0, 100); n++; newpulse = 0; if(n > n_max){ for (byte i = 0; i <= n_max; i++) { rpm_sum = rpm_sum + rpm_reading[i]; }; rpm_average = rpm_sum / (n_max + 1); rpm_sum = 0; n = 0; } } } updatedisplay(); } void updatedisplay() { byte x = 0; if(rpm_average < 10) x = 80; if(rpm_average >= 10 && rpm_average < 100) x = 62; if(rpm_average >= 100 && rpm_average < 1000) x = 44; if(rpm_average >= 1000 && rpm_average < 10000) x = 26; if(rpm_average >= 10000 && rpm_average < 100000) x = 8; if(rpm_average < 100000){ myOLED.clrScr(); // Стираем все с экрана myOLED.setFont(SmallFont); // Инициируем шрифты myOLED.print("T_A_H_O_M_E_T_R", 20, 10); // Первая строка выводим надпись "T_A_H_O_M_E_T_R" myOLED.print("ob/min", 90, 50); // Выводим надпись "ob/min" myOLED.setFont(BigNumbers); // Инициируем цифры myOLED.printNumI(rpm_average, x , 30, 5); myOLED.update(); } else { myOLED.clrScr(); // Стираем все с экрана myOLED.setFont(SmallFont); // Инициируем шрифты myOLED.print("T_A_H_O_M_E_T_R", 20, 10); // Первая строка выводим надпись "T_A_H_O_M_E_T_R" myOLED.print("MAX LIMIT", CENTER, 40); myOLED.update(); } } void ISR_sensor() { t_pulse_duration_volatile = micros() - t_pulse_started_volatile; t_pulse_started_volatile = micros(); timeout = 0; newpulse = 1; } Если я правильно понял, он определяет число замеров для вычисления среднего значения тем больше, чем выше обороты. Соответственно собрав необходимое количество замеров суммирует их и делит на это самое количество... Вроде все верно, но на выходе показания оборотов лавинообразно увеличиваются до максимума (99 000) и опять начинаются с нуля.
Попробовал... byte n_max =10; вместо byte n_max =0; и закомментил расчет n_max Все равно выдает странное.. При оборотах кулера 2600 показывает от 5000 до 12000... А не может новый импульс от датчика сбивать расчет?
Даже при изменении n_max = 1 результат так же прыгает.... По поводу алгоритма, в приведенном скетче он вроде как верный и логичный... Вот только понять не могу что с ним не так...
ну так почему не взять ваш первый скетч, который правильно считал обороты - и не добавить к нему расчет среднего, вся премудрость которого - "складываем N замеров и результат делим на N" ?