Умножение частоты импульсов в 2.6 раза
- Войдите на сайт для отправки комментариев
Вс, 16/08/2015 - 18:19
Возникла задача, применение автомобильное. Есть датчик скорости, есть блок управления от более свежей акпп, подробнее тут: http://www.drive2.ru/l/7396416/ . Необходимо увеличение частоты входных импульсов в 2.6 раза. Сигнал естественно меандр. Мысль выдала вот такой скетч:
long time=0; void setup() { } void loop() { time=pulseIn(A2, HIGH,35000); if(time==0||time>30000) { noTone(13); } else if(time<20500) { tone(A3,735000/time); } }
Есть определенные недостатки, например функция tone выдает минимум 30Гц, мне необходимо от 16Гц, в выходном сигнале периодически встречаются провалы по частоте. Не часто, и не сильные, но есть. Значение 30000 вместе с цифрой 20500 образует гистерезис (частота датчика имеет некоторую неравномерность в начале. Из-за этого происходит чередование tone и noTone с большой скоростью). Прошу у Вас совета, как можно решить такую задачу? Приоретет отдается выходному сигналу, если несколько периодов входных импульсов будет припущено, это не принципиально.
Загляните в исходники tone(), разберитесь и сделайте на их базе свою функцию.
Загляните в исходники tone(), разберитесь и сделайте на их базе свою функцию.
мне пока соображалка не позволяет)
Просто попробуйте.
Я бы не стал с tone связыватся ни в каком виде. Делал бы дето так:
1. Считаем импульсы с входа по прерываниям. В обработчике прерывания инкрементим счетчик на 2.6. Подробней - ищи подсчет импульсов (фронтов) на входе по прерыванию и операции с фиксированной запятой
2. В лупе определяем полупериод выходных типа так если счетчик больше порога - полупериод сокращаем но не ниже некоторого допустимого минимального порога, если счетчик менше - полупериод увеличиваем, но не более максимального порога. Подробней - изучить основы АСУ.
3 В лупе же проверяем истечение временного интервала полупериода, если он истек - меняем выходной на противоположный. Подробней - блинк без делея.
А вобще задачка интересная очень, комплексная, решите сами - можете считать себя программистом 8)
я бы написал на микрос по прицепу:
время = сигнал(время смены сигнала в микросекундак) * 2.6
а дальше генериш сигнал по времени
Первая версия у меня и была с прерыванием по входу, но при этом была сильная неравномерность выходных импульсов, т.к. выходная частота может достигать нескольких кгц, и прерывания тормозят луп. Пойду посмотрю на tone изнутри. В первом посте есть опечатка в коде, вместо noTone(13), должно быть noTone(A3). Переносил код с uno на micro, не заметил.
прерывания тормозят луп.
8о Это что же в них надо было писать?!
I2C (TWI) 0- 12.5 MHz
Sinus, Triangle, Square...... https://www.youtube.com/watch?v=p88eDImwJZY
http://www.ebay.com/itm/AD9833-Programmable-Microprocessors-Sine-Square-...
steel780, я бы сделал на 2-х таймерах. От расчётов частоты и измерения микросов лучше отказаться, у МК есть гораздо более удобный параметр -количество тактов процессора. Один таймер считает количество тактов между импульсами, и между циклами в своём прерывании программирует второй таймер, который уже выдаёт чистый сигнал. Функция loop() тут даже не потребуется.
steel780, я бы сделал на 2-х таймерах. От расчётов частоты и измерения микросов лучше отказаться, у МК есть гораздо более удобный параметр -количество тактов процессора. Один таймер считает количество тактов между импульсами, и между циклами в своём прерывании программирует второй таймер, который уже выдаёт чистый сигнал. Функция loop() тут даже не потребуется.
Не получится сделать стабильный меандр на выходе. Коэффициент умножения не целый. И на один входной импульс прийдется выдавать 2 или 3 выходных в заданом соотношении, на выходе частота будет плавать.
Logik, почему? по моей задумке должно быть стабильно. Предположим насчитал счётчик 10000 тактов, вывалился в прерывание, сказал второму таймеру что-б тот досчитал до 10000/2.6 А второй таймер настроить на перечитку регистра OCR только в конце цикла (TOP). Таким образом пока не поменяется входная частота выходная будет стабильна, т.к. результат 10000/2.6 будет всё время одинаковым. А как только поменяется частота, то таймер сначала закончит старый период, потом перечитает регистр, и уже создаст новый, т.е. максимально корректно отреагирует с задержкой всего лишь в пол-такта входного сигнала.
Смотрим подробней. Пусть на входе стабильная частота и насчситали за импульс 10000 тактов, сказал формировать импульсы длительностью 10000/2.6 =3846 такта. За время следующего подсчета входного, т.е за 10000 тактов на выходе сформируются 2 выходных длительностью 3846+3846=7692. За оставшиеся 10000-7692=2308 на выходе будет еще 3846/2=1923 один уровень 3-го импульса и 2308-1923=385 второй уровен. Затем закончится 10000 тактов и все повторится. 3-й импульс - явно не меандр.
Гадит дробность коэффициента. Можна попробовать умножать на 26 (или 13), а затем выходной делить уже на 10 (или 5). Тоесть на оди входной генерировать таймером 13 выходных, за ним "ставить" делитель на 5 выдающий на выход результат.
Logik, вы наверное не так меня поняли.. Или я что-то не понимаю, что то упускаю? Первый таймер в режиме счётчика только программирует длительность работы второго таймера-генератора, кроме как передать число 3846 он больше ничего не может. Второй таймер отсчитает 3846 тиков , инвертирует выход, и опять начнёт считать 3846 тиков. Сбить равномерность работы 2 таймера никак не возможно, он в независимости от чего бы то нибыло отсчитает положенное количество тактов. Я бы мог даже набрасать скетч, но вряд ли набор регистров таймера будет о чём-то наглядно свидетельствовать..
Сбивать работу второго таймера будет первый. Сбивать каждые 10000 тактов, устанавливая новую длительность. Возможно вы предполагаете не обнулять текущее состояние таймера при установку новой длительности?
Logik, зачем обнулять? Второй таймер не будет сбиваться. Он отсчитает положенное, потом перечитает регистр OCR, и в следущий раз досчитает до нового значения, если оно изменилось.
Тогда при постоянной частоте на входе все ОК. Вмешательства в работу второго таймера нет, OCR можна даже и не переписывать. Все проблемы перенесены в режим разгон-торможение, что на самом деле, чисто с стороны разработки, тестирования и появления плавающих глюков намного неприятней.
Смотрим поведение при изменении длительности на входе. Там вообще печалька. Допусти первый импульс 10000 тиков, второй в десять раз больше- 100000, потом импульсов нет. Типа машина тормозила и стала. Во время измерения первого импульса ничего не выводится (наверно. или выводится?). за время измерения второго импульса выводится 26 импульсов по 3846 тиков, затем выводится некоторое количество импульсов, пока мы каким то образом не поймем что стоим. Т.е. мы стоим а на акпп идет сигнал что мы едем. За время двух импульсов на входе, т.е. 110000 тиков, на выходе было не менее 26 импульсов. Это явно не увеличение частотыв 2,6 раза.
Ещё думаю не лишнее.
steel780!!!! Вмешательство в конструкцию и работу основных узлов автомобиля не допустимо! Это угрожает жизни Вам, родным, близким и далеким людям. Факт того, что я обсуждаю техническую сторону вопроса не означает что я поддерживаю саму идею доработки авто. Любительская разработка не обеспечит эксплуатационную надежность во всем диапазоне условий. Подумайте что будет если отказ произойдет при выходе на обгон.
steel780!!!! Вмешательство в конструкцию и работу основных узлов автомобиля не допустимо! Это угрожает жизни Вам, родным, близким и далеким людям. Факт того, что я обсуждаю техническую сторону вопроса не означает что я поддерживаю саму идею доработки авто. Любительская разработка не обеспечит эксплуатационную надежность во всем диапазоне условий. Подумайте что будет если отказ произойдет при выходе на обгон.
Да вроде в курсе) Ничего страшного не делаю) Если будет отказ, произойдет толчек в коробке и отключиться управление 4вд.
Меня в целом устраивает как работает скетч, за исключением вот этого:
синий, это выход с ардуины, не могу понять почему так. Возможно это происходит в момент переключения, но отследить это не получиться т.к. отображение передачи происходит сильно раньше физического переключения.
Сделал набросок -работает. Но это упрощённая версия, для низких частот нужно дорабатывать. В этом виде считает временной отрезок не более 4мс, т.е. примерно от 125Герц и выше. И ещё не делал отслеживание наличия сигнала, т.е. если его не будет то второй таймер всё равно будет генерить сигнал по последним данным. Выходной сигнал отличный, посмотрел на осцилле. Код для леонардо/micro. Меня просто чисто из спортивного интереса заинтересовала задачка. )
Думаю есть смысл брать минимальную либо среднюю длительность импульса за например 10 периодов.
upd: Открыл другой лог, действительно это моменты переключения, либо значительного изменения положения дросселя. Видимо из-за люфтов в шестернях импульс в этот мемент резко меняет ширину.
Причин такого может быть много. От аппаратных до програмных. Для начала попробуйте в самом конце loop поставить goto на его начало. Мелоч, но может поможет.
steel780, мне кажется с вашим скетчем невозможно добиться качественного синтеза частот, даже с идеальным генератором на входе.
steel780, мне кажется с вашим скетчем невозможно добиться качественного синтеза частот, даже с идеальным генератором на входе.
будем пробовать Ваш, но мне кажеться что tone это тот же самый таймер
steel780, мой нужно дорабатывать. В принципе сделать, что б счётчик понимал сигнал от 0 Герц относительно легко, но остальное уже муторно.
Я в своё время изучил алгоритм tone(), таймер конечно обычный, но у него код довольно примитивный, очень плохо подходит для линейной генерации частоты. Собссно это и понятно, сделан то он просто как пищалка на спикер. Кстати перекинуть его на 16-битный таймер, что-б он пищал на частотах менее 30герц очень легко, я уже как то писал
steel780, дописал скетч, теперь работает от 0 герц до нескольких килогерц, потом начинает дрожать фаза. Осталось как я понимаю только включить отслеживание наличия сигнала ) Нумерация пинов для леонардо/микро
Огромное спасибо, но мне нужно немного времени, чтобы работаться в этом коде.
steel780, наверно сложно в чужом коде разбираться) Переменная tic содержит число тактов процессора за один период входящего сигнала. В переменной icr_tic лежит то-же самое, но при условии что тактов было не более, чем 65535. Если их было больше, то переменная int_tic записывает сколько раз счётчик переходил через максимум. Довольно трудные строки 24-26. 16-битный таймер умеет считать только до 65535, поэтому если тактов было больше, то входя в прерывание эти строчки заставлят досчитать таймер до максимума , вычесть то, что уже оттикало, и когда пройдёт последний такт нога PC6 инвертируется. Фактически в коде два независимых устройства- частотомер и генератор, только им указывается частота не в герцах, а в тактах процессора. Если 16000000 /tic , то будет частота входного сигнала в герцах.
Я имел ввиду скорее строки с 9й по 14ю :-)
Докладываю о полевых испытаниях:) Ваш скетч работает сильно лучше моего, срывов выходных импульсов практически нет (вечером выложу картинку), и нет нужды проверки остановки авто, оно само видит что частота импульсов слишком низкая и пишет скорость 0. Но есть трабл, при включении питания ардуина начинает генерировать импульсы большой частоты, но как только трогаешься с места, все приходит в норму. То есть нужно изначально установить количество тиков побольше.
steel780, самое простое -попробовать присвоить в третьей строке скеча переменной tic какое-то стартовое значение, должно помочь. Только не больше, чем 65535*5.2 , иначе не попадёт под условие 25 строки, и сперва отстрочит какое-то количество импульсов на высокой частоте.
Ближайшие у нулевой скорости оказалось значение 2200000:(
steel780, попробуйте, возможно прокатит, кажется я ошибся, не должно на выходе ничего быть пока не сработает условие в 25 строке. Есть вариант ещё не запускать генератор пока tic не будет иметь нужно знаечние. Но это несколько сложнее.
Срабатывает думаю из-за того, что вход подтянут к +5, а с датчика идет минус.
2200000 хорошо помогло
steel780, вам удалось разобраться как всё это работает? В принципе скетч можно ещё совершенствовать. Например изначально я думал, что б выходной сигнал полность формировался после пол-такта входного. Но сделал после целого такта входного, так было проще. Но качественно новый уровень возможен только на ардуино DUE , там 32-битные таймеры, отпадёт надобность вываливаться в прерывание по переполнению каждые 65535 тактов, и делать пересчёты, а значит резко вырастет качество сигнала.
Меня смущают периодически вот такие моменты:
Может прерывания как-то тормозят друг друга?
steel780, прерывания конечно тормозят, но на выбросы они не способны. Они очень мелко гадят, в виде дрожания фазы. Возможно где-то ошибка, вопрос как вычислить откуда растут ноги. Если это глюк счётчика, значит иногда проскакивает tic размером сильно отличающийся от остальных. Нужно как-то логгировать все значения tic, что б потом проанализировать.. А возможно и генератор, в 25 строке не очень корректно всё сделано..
upd: генератор проверил, выдаёт точно рассчётную частоту без каких-либо выбросов. Стало быть остаётся либо счётчик дурит, либо помехи пролезают на вход.
Здравствуйте. Стоит таже задача что у ТС) Но в пограммировании полный ноль, если в адуиновском С еще как то то в оригинале или С++ не силен. Пишет ошибку на "TCCR3A=0; " я так понял что у меня UNO а код рассчитан под Леонардо. Это можно исправить?
Uno не имеет 4го таймера
Задействовано 2 таймера, если я правильно понял. Адреса нужно изменить, а еще в уно только 1 16 бит, остальные 2 по 8 бит.
wss66, набираете в гугле AVR таймеры и читаете статьи по аппаратным таймерам. А также даташит на конкретный микроконтроллер (ATmega328P у UNO), в котором расписана вся переферия и настройки через регистры.
Здравствуйте, не могу понять откуда в первом посте взялась строчка
tone(A3,735000/time);
Tone-понятно, A3 - выход, а вот как получили 735000?
Если частота равна 1/T, то так как у нас меандр, то T=2*time ( time длина импульса, как я понял) А так как нам нужно умножить частоту на 2,6 то получаем:
2,6/(2*time)=1,3*time
Если перевести в микросекунды:
1300000*time
Как топикстартер получил 735000? Мне нужен умножитель на 1,5 не могу разобраться в его коде.
wunderley, т.е. вариант , что т.с. накосячил с рассчётом вы даже не рассматривали? :)
Хотел убедиться, что я правильно рассуждаю;)
Сможете мне помочь? У меня та же цель, только в наличии ардуино надо и умножитель нужен на 3. Четвертый день уже плохо сплю
Положы " ардуино надо" в памойку и спи спокойно.
Смогу. htpicc@gmail.com. Уже который день кушать не могу.
Доброй ночи.
dimax
Помогите переделать ваш код под NANO. Голову сломал с регистрами и таймерами, но очень интересно разобраться.
спасибо.
amgame, мк atmega32u4 (т.е. леонардо/микро/промикро) был специально выбран для этой программы, т.к. обладает необходимыми ресурсами. Переделывать имеет смысл только на stm32, у которого ещё больше аппаратных возможностей для этой задачи.
amgame, мк atmega32u4 (т.е. леонардо/микро/промикро) был специально выбран для этой программы, т.к. обладает необходимыми ресурсами. Переделывать имеет смысл только на stm32, у которого ещё больше аппаратных возможностей для этой задачи.
Понял. Тогда вопрос в следующем нужен только делитель импульсов с коэффициентом 3.5. Диапазон частот 56-230Hz. Вот их же как то делают на Attiny. Поможите с кодом.?
amgame, делить частоту проще чем умножать. К сожалению нет, мне не интересно тратить на это своё время.