Официальный сайт компании Arduino по адресу arduino.cc
Некорректно отрабатывает таймер.
- Войдите или зарегистрируйтесь, чтобы получить возможность отправлять комментарии
Сб, 03/07/2021 - 01:21
Доброго времени суток. Помогите найти ошибку. Задача у меня такая. Есть датчик, который производит сигнал около 1500 Гц и мне этот сигнал нужно конвертировать с понижающим коэффициентом 9.35, т.е он должен уменьшить частоту в 9.35 раза. Имитируя датчик, подаю сигнал 1500 Гц, но на выходе получаю 60 Гц, если на входе устанавливаю до 300 ГЦ, то передаточное отношение, более менее совпадает...Причем , если в таймере жестко указать величину итерации, сигнал получается расчетный.
Вот мой код:
uint32_t tmr,src; bool state; void setup() { pinMode(5, OUTPUT); pinMode(A0, INPUT); } void loop() { src = pulseInLong(A0,LOW)/9; if (micros() - tmr >= src) { tmr += src; state = !state; digitalWrite(5, state); } }
Может я уже слабо соображаю сегодня, но, как минимум: зачем длительность импульса делить на 9, если частоту нужно уменьшить на 9,35?
"Более-менее" совпадает - это случайность.
И таймер тут уж точно невиновен.
Про скважность сигнала на входе и выходе забыли добавить.
Делитель я произвольно поставил целочисленный. На самом деле, если частоту уменьшать , то период нужно увеличивать.т.е. умножать на коэффициент.
Скважность 50%. Выводил переменную "src " в порт - измерения и расчет производятся правильно. Какой-то ступор с digitalWrite, либо переменная src не должна быть произвольной....например, как delayMicroseconds только до 16383.
для проверки использую осциллограф.
Иногда потрясает глубина невежества. Браться за задачу не изучив исходные данные оборудования, а если изучил, то не применить для простейших прикидочных расчётов возможности применения - вызывает только желание сильно поглумиться. Таймер работает только с целыми числами. Если нужна какая то дробная величина (9.35), то надо сначала перевести всё в целый диапазон (935) а потом посмотреть, сможет ли таймер, тактируемый от кварца и имеющий дискретный шаг изменения выходной частоты как то вписаться в поставленную задачу.
Мне кажется, если мы работаем с микросекундами, то дроби можно вообще не вводить...
Почему ниже приведенный код работает, а тот который в первом посту нет?
Посмотрите внутрь функции pulseInLong - как она производит замер и подумайте - может ли остальной код выполняться быстрее, чем она сама.
Я поставил искуственную задержку( delayMicroseconds(500)), вместо pulseInLong.
И код сразу перестал работать. Как заставить задачи выполнятся параллельно?
Как заставить генерировать выход, пока ведется измерение?
Представляете, как раз об этом подумал. Спасибо.
Если делать на прерываниях, то код наверное будет тоже тормозить, т.к входная частота до 1500 Гц.
Если делать на прерываниях, то код наверное будет тоже тормозить, т.к входная частота до 1500 Гц.
откуда такой странный вывод? Это зависит от того, как напишете. Но вообще ардуина на прерываниях способна нормально измерять частоты в десятки и сотни КГц, а у вас всего-то...
например, как delayMicroseconds только до 16383.
это что за магическое число такое? :)))
Таймер это аппаратное устройство. Его выход никак не зависит от того, что делает программа. Даже если программа зависнет таймер всё равно будет генерить выходной сигнал. Всё что ему надо - в регистр управления записать параметр деления. Это единицы микросекунд. Всё остальное время можно отдать на измерение входной частоты и расчёту делителя для таймера. Если измерение сделать на прерываниях, то процессор вообще можно на долго спать отпрвлять. И никаких тормозов.
Я поставил искуственную задержку( delayMicroseconds(500)), вместо pulseInLong.
И код сразу перестал работать. Как заставить задачи выполнятся параллельно?
Как заставить генерировать выход, пока ведется измерение?
На таймере1 измеряешь частоту через инпут-капча стандартным способом, таймер2 генерит частоту. loop() - пустой, совсем пустой. Можно в нем чо-нить умное написать. Слово какое-никакое. ;))
(я про 328 контроллер, ессно)
Извините за неточность. таймером я назвал циклическое условие, например вот это.
Вот такой код у меня получился.
Вроде работает....)
Можно ли к переменной uint32_t применять коэффициент с десятичной точкой, например 9.32?
Я поставил искуственную задержку( delayMicroseconds(500)), вместо pulseInLong.
И код сразу перестал работать. Как заставить задачи выполнятся параллельно?
Как заставить генерировать выход, пока ведется измерение?
На таймере1 измеряешь частоту через инпут-капча стандартным способом, таймер2 генерит частоту. loop() - пустой, совсем пустой. Можно в нем чо-нить умное написать. Слово какое-никакое. ;))
(я про 328 контроллер, ессно)
Чувствую это еще лучше. Не могли бы Вы показать пример или направить почитать ресурс с требуемой инфой.
Если стараться не уходить от упрощений Ардуино, то можно генерировать частоту при помощи tone();
Возможны произвольные длительности в моменты изменения частоты, но если менять как в последнем коде раз в секунду, то может быть это не будет оказывать влияния.
Параметр 9,35 - ни о чем.
Допустимые отклонения периода и скважности мы не знаем, а без них что гадать?
Не могли бы Вы показать пример или направить почитать ресурс с требуемой инфой.
Я дико извиняюсь, но читать нужно ДШ на контроллер. ;))
А пример - пожалуйста!
Не могли бы Вы показать пример или направить почитать ресурс с требуемой инфой.
Я дико извиняюсь, но читать нужно ДШ на контроллер. ;))
А пример - пожалуйста!
Целый день потратил на поиск ошибки. время упущено, оставлю пока, как есть...
.Всем откликнувшимся спасибо. А тем кто подсказывает умные мысли - вдвойне!
Извините за неточность. таймером я назвал циклическое условие, например вот это.
Простите, но о каких дробных значениях частоты можно говорить с таким подходом? Частота будет плавать в довольно широком диапазоне из за неопределённости времени выполнения такого цикла, связанного с прерываниями.
Извините за неточность. таймером я назвал циклическое условие, например вот это.
Наверное, Вы правы! Но для данной схемы - оно работает! И перемножение дробного коэффициента на uint32_t работает. Входной сигнал достаточно инерционный и имеет диапазон от 0 до 1500 Гц (скваж 50). Выходной сигнал должен быть от 0 до 169 Гц (скваж 50). Я тестировал с входным сигналом даже до 5 кГц - отрабатывает четко.
Если у Вас есть другое решение и Вам не жалко, то покажите как бы Вы это решали?
Описание проекта такое(на автомобиле испорчен механизм датчика скорости - не показывает спидометр).
Система ABS оснащена индуктивным датчиком скорости, который на максимальной скорости генерирует синус 1500Гц. сигнал будет браться оттуда.
Ну так для тахометра действительно точности это решения достаточно. Плавание частоты усредняется показометром. Если бы в первом посте была упомянута цель, то многие вопросы даже не возникли.