Индикатор длительности и количества импульсов
- Войдите на сайт для отправки комментариев
Вс, 07/05/2017 - 16:35
Доброго времени суток участникам форума.
Не так давно заинтересовался МК Ардуино. С электротехникой знаком, а вот с программированием не очень.
Хочу сконструировать индикатор длительности и количества импульсов. На порты поступают импульсы, на первом порту необходимо измерять длительность импульсов за время Т(например 1 сек.) и усреднять. Далее выводить на индикатор. С второго порта необходимо считывать количество импульсов за время Т (1 сек), усреднять и выводить на дисплей.
Сложность для меня в том, что длительность импульсов и частота постоянно меняются, каким образом можно фиксировать первичные параметры импульсов, и как усреднять в непрерывном процессе?
Изучите функции
класс титановый велосипед StopWatch.
Длительность импульсов Вам измерит функция pulseIn, см. раздел http://arduino.ru/Reference .
Количество импульсво лучше всего считать прерыванием. См. attachInterrupt в том же разделе.
И вообще, проштудируйте тот раздел целиком, чтобы по каждой ерунде вопрос не возникало.
Ну а как бы Вы в жизни без компьютера усредняли?
Заводите две переменные в котроых изначально нули. В первой переменной накапливаете сумму длительностей всех поступивших импульсо по мере их поступления. Вот второй накапливаете количество поступивших импульсов (т.е. просто прибаляете туда 1 вский раз, когда импульс поступил.
В любой момент, поделив первую переменную на вторую получаете среднюю длительность всех поступивших к данному моменту импульсов.
Только следите за переполнением (правильно тип выбирайте) и не забывайте об особенностях целочисленного деления.
Благодарю за помощь. Про среднее значение я имел ввиду, за последнюю секунду. Частота примерно изменятся от 20 до 200 Гц. Длительность импульса от 1 до 15мс. Про сумму длительности/кол-во импульсов мысли были, но мне необходимо за отрезок времени. Импульсы идут непрерывно и имеют разброс, если их выводить на экран, то показания быдут прыгать. Чтобы не было резких скачков, хочу выводить среднее значение, т.е. для примера брать цепочку в 20 импульсов и обрабатывать их. Думаю использовать 20 переменых, которые изменяют значения с каждым импульсом(обновляются), и далее из них выводится среднее на экран.
Также возник вопрос по отображению на дисплее. Есть предположение, что если выводить на экран с каждым циклом, то будет все мелькать. Думаю стоит выводить 2-5 раз в секунду.
А справитесь? Создаете структуру указывающую саму на себя. Создаете 3 функции: добавление новой в начало, убирание последней в конце, подсчет средней в очереди. Потом делаем кучу . И запускаем измерение с выводом на экран.
Конечно хочется справиться. Цепочку вроде представляю, но вот как увязать правильно пока только изучаю.
Блин, ну почему новички никогда не говорят что именно им нужно, а всегда просят подсказать реализацию их собвтсенных (зачастую в корне неверных) подходов?
Не нужна Вам никакая средяя за секунду. Считать её у Вас никакой памяти не хватит.
Вам нужен фильтр низких частот.
Простейшая реализация описана вот здесь - http://www.poprobot.ru/theory/low_pass_filter
Почти тоже самое, но более гибко и почти также просто делается то, что биржевики называют Exponential Moving Average (EMA). См. описание EMA здесь - https://www.metatrader5.com/ru/terminal/help/indicators/trend_indicators/ma
Наконец, есть продвинутые фильтры типа вот такого.
Попробуйте разные и реализуйте тот, который окажется более адекватным Ваше задаче.
В моей задаче используются дискретные сигналы без шумов. Пока буду решать задачу для одного порта с длительностью импульса. Частота изменяется от15 до 100 герц. Длительность верхнего фронта импулься от1 до 15 мс. Усреднение хочу использовать для плавного изменения значений и отображения на дисплее (экране). Точные значения длительности нужны будут позднее.
Скопировано:
Простое, или арифметическое, скользящее среднее рассчитывается путем суммирования цен закрытия инструмента за определенное число единичных периодов (например, за 12 часов) с последующим делением суммы на число периодов.
Примерно таким же образом я и хотел усреднять. Значения 20 последних импульсов приводить к среднму, тогда конечный результат будет изменятся плавно.
В моей задаче используются дискретные сигналы без шумов. Пока буду решать задачу для одного порта с длительностью импульса. Частота изменяется от15 до 100 герц. Длительность верхнего фронта импулься от1 до 15 мс. Усреднение хочу использовать для плавного изменения значений и отображения на дисплее (экране). Точные значения длительности нужны будут позднее.
Скопировано:
Простое, или арифметическое, скользящее среднее рассчитывается путем суммирования цен закрытия инструмента за определенное число единичных периодов (например, за 12 часов) с последующим делением суммы на число периодов.
Примерно таким же образом я и хотел усреднять. Значения 20 последних импульсов приводить к среднму, тогда конечный результат будет изменятся плавно.
В моей задаче используются дискретные сигналы без шумов. Пока буду решать задачу для одного порта с длительностью импульса. Частота изменяется от15 до 100 герц. Длительность верхнего фронта импулься от1 до 15 мс. Усреднение хочу использовать для плавного изменения значений и отображения на дисплее (экране). Точные значения длительности нужны будут позднее.
Скопировано:
Простое, или арифметическое, скользящее среднее рассчитывается путем суммирования цен закрытия инструмента за определенное число единичных периодов (например, за 12 часов) с последующим делением суммы на число периодов.
Примерно таким же образом я и хотел усреднять. Значения 20 последних импульсов приводить к среднму, тогда конечный результат будет изменятся плавно.
В моей задаче используются дискретные сигналы без шумов. Пока буду решать задачу для одного порта с длительностью импульса. Частота изменяется от15 до 100 герц. Длительность верхнего фронта импулься от1 до 15 мс. Усреднение хочу использовать для плавного изменения значений и отображения на дисплее (экране). Точные значения длительности нужны будут позднее.
Скопировано:
Простое, или арифметическое, скользящее среднее рассчитывается путем суммирования цен закрытия инструмента за определенное число единичных периодов (например, за 12 часов) с последующим делением суммы на число периодов.
Примерно таким же образом я и хотел усреднять. Значения 20 последних импульсов приводить к среднму, тогда конечный результат будет изменятся плавно.
Вы главной мысли не поняли. Суммирование за какой-то период предполагает запоминание значений и времени, чтобы потом выбрасывать из суммы старые значения. На это у Вас нет памяти. Поэтому я Вам предложил несколько вариантов "усреднения" БЕЗ необходимости суммирования. Что ФНЧ, что EMA не требуют суммирования и запоминания. Понимаете?
Теперь понял. Просто пока не умею использовать более сложные механизмы, простые арифметические действия привычнее, а вот более сложное надо пробовать. Хочется так сказать прощупать процесс, знать что от чего зависит и уметь его контролировать. Буду пробовать по мере возможности.
Теперь понял. Просто пока не умею использовать более сложные механизмы, простые арифметические действия привычнее, а вот более сложное надо пробовать. Хочется так сказать прощупать процесс, знать что от чего зависит и уметь его контролировать. Буду пробовать по мере возможности.
Теперь понял. Просто пока не умею использовать более сложные механизмы, простые арифметические действия привычнее, а вот более сложное надо пробовать. Хочется так сказать прощупать процесс, знать что от чего зависит и уметь его контролировать. Буду пробовать по мере возможности.
Кстати, для реализации датчика дождя тоже нужно считать число ударов капель ... чем чаще "бьют", тем полагаю, сильнее дождь. Прикинул, при сильном ливне на 1 квадратный дециметр примерно падает 30 - 40 капель в секунду. Так что, возможно, идеи для ТС пригодятся и мне
Кстати, для реализации датчика дождя тоже нужно считать число ударов капель ... чем чаще "бьют", тем полагаю, сильнее дождь. Прикинул, при сильном ливне на 1 квадратный дециметр примерно падает 30 - 40 капель в секунду. Так что, возможно, идеи для ТС пригодятся и мне
ПОсмотрите в проектах - там есть счетчик Гейгера. Программная чать, думаю, практически идентична.
ПОсмотрите в проектах - там есть счетчик Гейгера. Программная чать, думаю, практически идентична.
Ок, спасибо
Прикинул, при сильном ливне на 1 квадратный дециметр примерно падает 30 - 40 капель в секунду. Так что, возможно, идеи для ТС пригодятся и мне
По моим прикидкам при самом сильном ливне (по Википедии 100 мм/ч) примерно вчетверо больше.
Доброго времени суток. Наконец то добрался до компьютера и риступил к реализации программы. Пока что наваял часть для измерения длительности и усреднения. Испытания на коленке прошли успешно. ) Получился вот такой вот код. Светодиод использовался для первоночальной отладки. Сильно не ругать, первый самостоятельный скетч. Буду рад предложениям , как упростить.
#define IMPULS_PIN 5 #define LED_LAMP_PIN 7 boolean ImpulsState = LOW; // предыдущее состояние входа boolean ImpulsPin = LOW; // текущее состояние входа unsigned int interval = 100; // ??? интервал между опросом входа, 100мкс unsigned long currentImpMicros = 0; unsigned long previousImpMicros = 0; // предыдущее время измерения импульса unsigned long T_impuls = 0; // ??? Длительность импульса long T_prom = 0; // ??? промежуточная переменная 1= 100мкс unsigned long t1 = 0; unsigned long t2 = 0; unsigned long t3 = 0; unsigned long t4 = 0; unsigned long t5 = 0; unsigned long t6 = 0; unsigned long t7 = 0; unsigned long t8 = 0; unsigned long t9 = 0; unsigned long t10 = 0; unsigned long t11 = 0; unsigned long t12 = 0; unsigned long t13 = 0; unsigned long t14 = 0; unsigned long t15 = 0; unsigned long t16 = 0; unsigned long t17 = 0; unsigned long t18 = 0; unsigned long t19 = 0; unsigned long T_sred = 0; int second = 1; void setup() { pinMode(IMPULS_PIN, INPUT); // задаем режим входа для порта, pinMode(LED_LAMP_PIN, OUTPUT); Serial.begin(9600); // передаём заголовок нашей таблицы в текстовом виде, иначе // говоря печатаем строку (англ. print line). Символы «\t» — // это специальная последовательность, которая заменяется на // знак табуляции (англ. tab): 8-кратный выровненный пробел Serial.println("T_impuls\tT_sred"); } void loop() { unsigned long previousMicros = 0; // предыдущее время измерения опроса входа unsigned long currentMicros = micros(); //проверяем не прошел ли нужный интервал, если прошел то if(currentMicros - previousMicros >= interval) { previousMicros = currentMicros; // сохраняем время последнего переключения boolean ImpulsPin = digitalRead(IMPULS_PIN); // присваеваем состояние входа if (ImpulsState == LOW && ImpulsPin == HIGH ) // Выполняем проверку входа,начало импульса { unsigned long currentImpMicros = micros(); // начало импульса previousImpMicros = currentImpMicros; // предыдущее время измерения импульса ImpulsState = ImpulsPin; // присваиваем новое значение } if (ImpulsState == HIGH && ImpulsPin == LOW ) // Выполняем проверку входа,конец импульса { currentImpMicros = micros(); T_impuls = currentImpMicros - previousImpMicros; // вычисляем длительность импульса ImpulsState = ImpulsPin; // присваиваем новое значение T_sred = (t1+t2+t3+t4+t5+t6+t7+t8+t9+t10+t11+t12+t13+t14+t15+t16+t17+t18+t19+T_impuls)/20000 ; // расчет среднего знаения импульса t1 = t2; t2 = t3; t3 = t4; t4 = t5; t5 = t6; t6 = t7; t7 = t8; t8 = t9; t9 = t10; t10 = t11; t11 = t12; t12 = t13; t13 = t14; t14 = t15; t15 = t16; t16 = t17; t17 = t18; t18 = t19; t19 = T_impuls; // присвоение скользящих значений Serial.println(T_impuls); Serial.print("\t"); Serial.println(T_sred); } } boolean ImpulsPin = digitalRead(IMPULS_PIN); if (ImpulsPin == HIGH) { digitalWrite(LED_LAMP_PIN, HIGH); } else { digitalWrite(LED_LAMP_PIN, LOW); } digitalWrite(LED_LAMP_PIN, LOW); } // конец циклаВот так попроще:
unsigned long t[20]; for (int x = 0; x<20; x++){ t[x] =0;}T_sred = (t1+t2+t3+t4+t5+t6+t7+t8+t9+t10+t11+t12+t13+t14+t15+t16+t17+t18+t19+T_impuls)/20000 ; // расчет среднего знаения импульса t1 = t2; t2 = t3; t3 = t4; t4 = t5; t5 = t6; t6 = t7; t7 = t8; t8 = t9; t9 = t10; t10 = t11; t11 = t12; t12 = t13; t13 = t14; t14 = t15; t15 = t16; t16 = t17; t17 = t18; t18 = t19; t19 = T_impuls; // присвоение скользящих значенийА вот тут так
T_sred = t[0]; for (int x = 0; x<19; x++){ T_sred += (t[x] = t[x+1]);} t[19] = T_impuls; T_sred +=T_impuls; T_sred /=20000;Не пойму только, почему делим на 20000, а не просто на 20
вместо
unsignedlongpreviousMicros = 0;напиши staticunsignedlongpreviousMicros = 0;иначе между вызовами loop previousMicros запоминаться не будетну и код не то что сырой, с него прям слеза льёца.Делим на 20000 , потому что микросекунды переводим в миллисекунды.