Управление длительностью импульсов
- Войдите на сайт для отправки комментариев
Пт, 12/02/2016 - 12:33
Добрый день. Встала задача сгенерировать простейший импульсный сигнал. Под рукой имеется arduino 2560. Начал разбираться как и что, и вот сразу столкнулся с проблемой. Набросав незамысловатый код, оказался неприятно удивлен.
analogWrite(pin,HIGH);
analogWrite(pin,LOW);
Осцилограф говорит, что длительность не 1 мкс, как этого бы хотелось, а целых 8,7+. С утра пытаюсь найти решение проблемы, но в итоге пишу сюда, господа знатоки. Очень прошу подсказать нубу его ошибку.
П.С.: опыта программирования железок не имею, я всего лишь десктопный разработчик, не ругайтесь
Благодарю за внимание.
https://www.arduino.cc/en/Reference/Micros
Благодарю за ответ. Однако micros(), как я понял, измеряет время. Мне же необходимо его назначить. Я хочу получить импульсную модуляцию со скважностью 50% и длительностью импульса 1мкс.
уберите delay и получите 4 мкс :) c кварцем 16мГц, читайте работу таймеров
Его я тоже убирал и получал эти 4мкс. Выходит, что уменьшить это время до 1 мкс технической возможности у этой платы нет? Или я опять что-то не так понял?
Только таймеры помогут Вам. Вот по теме, там и пример есть. Есть еще такая функция, но частоты естественно ограничены.
Пытался использовать и tone(). Логика моих рассуждений такова: длительность 1мкс = 1МГц частоты. Осцилограф показывает 30мкс. Я и игрался с частотами, но меньше 12 никак не получалось. Сейчас буду изучать таймеры, надеюсь смогу решить свою проблему.
piggy197, если вам нужны микросекундные точности то забудьте про ардуиновские функции. Насовсем :)
Кстати, а зачем вам такая точность?
Чуял, что просто не будет :) Может подскажете, что надо вспомнить? Мозгом понимаю, что задача совсем не сложная, однако пятая точка испытывает противоположные ощущения.
Сказали копать - я копаю. Скажут не копать - не буду :)
Я хочу получить импульсную модуляцию со скважностью 50% и длительностью импульса 1мкс.
Скважность в % не измеряется. Предполагаю, что Вам нужен прямоугольный сигнал со сважностью 2 (меандр) и частотой 500кГц. Правильно?
Тогда держите:
1
void
setup
() {
2
pinMode(9, OUTPUT);
3
TCCR1A = 0x40;
// Переключение пина 9 по сравнению
4
TCCR1B = 0x09;
// Установить СТС режим и делитель частоты 1
5
OCR1A = 15;
// установить TOP равным 15
6
}
7
8
void
loop
() {}
Нужный Вам сигнал на цифровом пине 9.
А вот здесь есть много букв на эту тему.
Знаете, все ваши примеры, почему-то не дают никаких результатов. Сигналы отсутствуют.
piggy197, разумеется примеры то для УНО :)
Знаете, все ваши примеры, почему-то не дают никаких результатов. Сигналы отсутствуют.
Это Вы мне. Мой пример не даёт результата?
Ну, а на чём Вы его запускаете? А-а-а- у Вас же Мега!!!!
Виноват - эти примеры для UNO-подобных ардуин.
Значит, так. Для меги это БЕЗУСЛОВНО возможно и так же просто и коротко, как и здесь.
Лично я переделывать не буду - меги нет. Почитайте про таймеры и переделайте - это несложно. Или попросите кого-нибудь, у кого Мега есть.
И последнее. В примере (из этой темы), время будет точнее если 15 заменить на 16 - будет точно 1 мкс. Я тут чуть-чуть ошибся.
Когда будете переделывать на мегу - не забудьте, 15 замените на 16.
Почитайте про таймеры и переделайте - это несложно.
Буду пытаться, только я, как абсолютный новичок, не очень понимаю магии заклинаний, типа TCCR1A, OCR1A и тд. Пока что :)
Информация 1. Информация 2. Информация 3. Её много есть, лучше конечно читать даташит на конроллер, но по ссылкам более подробно расписано. Да и ЕвгенийП Вам привел примеры, осталось только сменить регистры и их значения.
Буду пытаться, только я, как абсолютный новичок, не очень понимаю магии заклинаний, типа TCCR1A, OCR1A и тд. Пока что :)
Заодно и научитесь - будете понимать. Главное, теперь Вы уверены, что результат достижим и достижим совсем несложно, так что Вам нужно просто "дожать" и любая неудача - лишь повод искать ошибку, а не сомневаться в самом подходе. Всё, что Вам нужно сделать: установить CTC режим, установить сброс таймера по сравнению на нужном пине, поставить делитель частоты 1 и вставить в качестве предельного значения счётчика 16. И всё заработает.
Не забудьте про мою ремарку насчёт "заменить 15 на 16" - не знаю как я так лопухнулся. Там ведь всё просто - это число есть ни что иное, как количество тактов. Если тактовая частота 16МГц, то конечно же в 1 мкс должно быть 16 тактов, а не 15.
Удачи!
Удачи!
Спасибо за столь мотивационный пост :) Если вас не затруднит, объясните, пожалуйста, почему в регистры TCCR1A и TCCR1B вы заносите 64 и 9 соответственно?
И последнее. В примере (из этой темы), время будет точнее если 15 заменить на 16 - будет точно 1 мкс. Я тут чуть-чуть ошибся. Когда будете переделывать на мегу - не забудьте, 15 замените на 16.
Вы не ошибались Евгений :) Всё точно. Счёт регистра OCR идёт с ноля. При OCR=0 таймер будет дёргать свою ногу каждый такт мк, т.е. получим частоту 16/2= 8МГц. При OCR=15 таймер дёргает свою ногу на каждый 16-й такт, т.е. получим частоту 500кГц или ширину одного импульса 1us. Ровно что и хотел Т.С.
Два самых старших бита регистра TCCR1A отвечают за то, что будет делать таймер в тот момент, когда значение его счётчика совпадёт со значением для сравнения, которое хранится в регистре OCR1A (в общем случае не обязательно в нём, но мы ниже ещё укажем, что у нас оно хранится именно в нём).
00 - ничего
01 - инвертировать соответсвующий (для счётчика 2 - девятый) пин
10 - установить пин в LOW
11 - установить пин а HIGH
Нам с Вами надо инвертировать, вот и пишем туда 01. Ну, а поскольку это самые старшие биты, а другие биты у нас должны быть нулями, получается. что мы туда пишем B01000000 или, что тоже самое 0x40
(кстати, два следующих бита точно такие же, но отвечают за пин 10. Поэтому, если мы вместо 0x40 загоним туда 0x10, то всё будет работать точно также, но с пином 10, а не 9).
В ТССR1B мы пишем 9 (это B00001001). Три самых правых бита выбирают делитель частоты для таймера. У нас написано 001 - делитель 1, т.е. таймер тикает на каждый такт процессора. Два следующих (влево) бита (у нас 01) устанавливают СТС режим со значением для сравнения, хранящимся в регистре OCR1A.
Ну, и последнее, что есть в том примере - в этот самый OCR1A заносится нужное значение.
Дальше всё работает так:
1. таймер стартует с 0 и на каждом такте процессора прибавляет единичку к своему счётчику.
2. как только значение счётчика становится равным числу, хранящемуся OCR1A, таймер инвертирует пин, сбрасывает счётчик в 0 и ... см. п.1
И последнее. В примере (из этой темы), время будет точнее если 15 заменить на 16 - будет точно 1 мкс. Я тут чуть-чуть ошибся. Когда будете переделывать на мегу - не забудьте, 15 замените на 16.
Вы не ошибались Евгений :) Всё точно. Счёт регистра OCR идёт с ноля. При OCR=0 таймер будет дёргать свою ногу каждый такт мк, т.е. получим частоту 16/2= 8МГц. При OCR=15 таймер дёргает свою ногу на каждый 16-й такт, т.е. получим частоту 500кГц или ширину одного импульса 1us. Ровно что и хотел Т.С.
Точно? Меня смутило следющее. Вот смотрите:
1. В начальный момент, в счётчике 0, а когда там стало 1, то 1/16 мкс уже прошла, когда там стало 2, то уже 2/16 мкс прошли.
2. Когда в счётчике стало 16 - прошло ровно 16/16 мкс.
3. Как раз в этот момент он и сбрасывается в 0 и инвертирует пин.
Разве нет? Получается, чтобы он ждал 16 периодов, в регистре должно быть именно 16. Разве нет?
Впрочем, в любом случае. ТС возьмёт осциллограф, посмотрит и оставит как ему лучше. Я бы так и сделал на его месте :)
ЕвгенийП, какие-то сложные конструкции вы в голове выстраиваете :) Счёт времени ведь идёт с конца предыдущего такта, а не ноля ocr. ИМХО удобнее считать как делитель. 0 - F_CPU /1 ; 1 - F_CPU /2; 2 - F_CPU /3 , итд..
Ну и слава Богу. Значит моё первое интуитивное решение было правильным, пока не начал лукаво мудрствовать. "Сороконожка не ведала горя, пока не задумалась в какой последовательности она переставляет ноги" :)
Большое спасибо за доступные для новичка объяснения! Задачу выполнил, настроил 2 выхода диференцированно, все как и хотел. Евгений, действительно, в 1 случае вы были абсолютно правы - максимальным значением надо делать 15 (проверенно осцилографом :)).
Задачу выполнил, настроил 2 выхода диференцированно, все как и хотел.
С Победой Вас!
Как видите, не боги горшки обжигают
Теперь, когда Вы всё сделали сами, Вы вполне сможете довести немного до ума. Я про это не писал Вам раньше, чтобы мозги не пудрить лишними заботами.
Вот смотрите. мои примеры расчитаны на то, чтобы показать как это делается, а не на то, чтобы испольщовать их в серьёзных проектах. Поэтому они упрощены. В частности, я тупо выставляю нужные биты и присваиваю значение всему регистру целиком. При этом я "попутно" устанавливаю в ноль те биты, которые мне не вовсе не нужны. Если кроме моего примера никто не работает, то это приемлемо. А вот если там ещё работают какие-то библиотеки и т.п., то луше делать не так, а аккуратно выставлять в 0 или 1 те биты, которые для нас важны и НЕ ТРОГАТЬ те биты, которые нам фиолетово. Оставлять в покое их прежние значения. То, что сейчас мы все эти фиолетовые биты забиваем нулями, какой-то библиотеке может серьёзно помешать. Для того, чтобы так делать, нужно использовать не присваивание, а аккуратные побитовые операции. Это понятно?
Задачу выполнил, настроил 2 выхода диференцированно, все как и хотел.
Для того, чтобы так делать, нужно использовать не присваивание, а аккуратные побитовые операции. Это понятно?
Спасибо за дельное замечание, в будующем обязательно это буду учитывать. Моя задача была - сгенерировать 2 меандра, 1 со сдвигом на пол периода. Я это сделал, однако меня смущает задержка между ними в 70 нс. Я так понимаю, эта задержка обусловолена временем исполнения одного такта. Хотелось бы одновременного выхода двух сигналов. Наверное, буду искать другое решение своей задачи. Или найду ардуинку с большей частотой. Еще раз большое спасибо за помощь!
меня смущает задержка между ними в 70 нс. Я так понимаю, эта задержка обусловолена временем исполнения одного такта.
Не знаю, выручит ли это Вас, но там можно получать на одной ноге сигнал, а на другой ноге иметь такой же сигнал, но в противофазе (инвертированный) зато безо всяких задержек. Если будете копать в даташите, это инверированные ноги с чертой над буквами пишутся.