Я работаю над проектом по космической оптике для беспроводной передачи данных между двумя точками. Для этого я использую ИК-светодиод, подключенный к Arduino Uno, который пульсирует с несущей частотой 56 кГц для передатчика, и второй Arduino с модулем ИК-детектора 56 кГц для приемника.
Я попытался использовать delayMicroseconds () между командами pin high и pin low для создания несущей частоты. Этот вид работает, но частота не всегда одинакова, и любые дополнительные задержки для импульсного сигнала (т. Е. Время, необходимое для вызова функции и уменьшения) могут изменить ее.
Читая таблицу данных для ATmega328, кажется, что есть способ установить более точный импульс, используя таймеры чипа. Возможно ли это, и если да, то как создать импульс 56 кГц, используя таймеры?
источник
Ответы:
Действительно возможно генерировать сигнал 56 кГц с таймером Arduino .
Таймер фактически может рассматриваться как специальный регистр в MCU, который содержит значение (начиная с 0), которое увеличивается с частотой, равной тактовой частоте MCU (16 МГц на Arduino Uno), вероятность делится на коэффициент, называемый предделитель . Когда это значение достигает заданного вами предела, называемого « Сравнение совпадений» , происходят две вещи:
Идея состоит в том, чтобы использовать этот ISR для изменения выхода логического вывода каждый раз, когда он вызывается (
HIGH
тогдаLOW
, потомHIGH
...).Теперь, чтобы сгенерировать прямоугольную волну 56 кГц, вам нужно, чтобы ваш ISR вызывался
56000 * 2
раз в секунду (* 2
потому что вам нужно менять выходное значение дважды за период).Вы можете выбрать желаемое значение прескалера для таймера из следующего списка:
В Arduino Uno есть два размера таймеров / счетчиков (на самом деле они называются таймер / счетчик ): 8 бит и 16 бит.
В Arduino Uno (ATmega328P) у вас всего три таймера, но некоторые из них могут использоваться базовой библиотекой Arduino или другими библиотеками, используемыми в ваших эскизах (вы должны проверить это самостоятельно):
Теперь вам нужно сгенерировать волну 56 кГц из 16 МГц, следовательно, без предварительного масштабирования, вам нужно посчитать:
16000000 / (56000 * 2) - 1 = 141.857
(- 1
потому что таймер считает от 0 до этого значения и сбрасывается только после его достижения)Из этого расчета мы можем сделать два наблюдения:
141.857
не является целым числом, и, следовательно, вы не сможете генерировать волну ровно 56 кГц.Отныне у вас есть два варианта:
142
в качестве сравнения совпадения; это даст вам следующую частоту:16000000 / (2 * (142 + 1)) = 55944 Hz
17
в качестве сравнения совпадения; это даст меньшую точность при следующей частоте:16000000 / (8 * 2 * (17 + 1)) = 55555 Hz
которая все еще находится в требуемом диапазоне.Теперь, что касается того, как написать свой набросок для этого, я советую вам проверить это учебное пособие, которое очень полно и очень интересно читать.
Конечно, полная таблица данных ATmega328P также важна, если вы хотите в мельчайших подробностях понять, что вы делаете.
Некоторые важные замечания:
источник
Я нашел
tone()
полезным для генерации высокочастотных импульсов на любом контакте. Он должен быть в состоянии обрабатывать 56 кГц. (Редактировать: как отмечает jfpoilpret, самое близкое, что вы могли бы получить на Arduino 16 МГц, - около 55,944 КГц)Трудность, очевидно, будет сочетать его с вашим сигналом данных. Я не думаю, что вы могли бы сделать это в программном обеспечении, не прибегая к низкоуровневому коду. Это должно быть довольно легко в аппаратном обеспечении, так как это цифровой.
Все, что вам нужно сделать, это вывести ваш сигнал данных на другой вывод, а затем объединить его с носителем с помощью логического элемента AND. Комбинированный сигнал может идти прямо на ваш ИК-передатчик.
Если у вас нет удобного логического элемента И, тогда довольно просто сделать свой собственный, используя пару транзисторов. Просто найдите в Интернете «транзистор и затвор».
источник
Принятый ответ jfpoilpret очень хорошо написан, совершенно действителен, и в 99% случаев я буду делать именно то, что он объясняет. Его решения находятся в пределах ваших определенных параметров, поэтому они должны работать очень хорошо. Но что лучше, чем « очень хорошо »? Совершенство! В конце концов, вопрос в том, чтобы получить точное значение. Как уже говорилось, достаточно близко в большинстве случаев хорошо (возможно, во всех), и даже при работе с чем-то вроде часов, когда 1 секунда должна быть 1 секунда, вы все равно должны страдать от недостатков унаследованных частей.
То, что я предлагаю, не всегда возможно. В некоторых случаях это возможно, но с большим количеством хлопот и усилий, чем в этом случае. Стоит ли это зависеть от конкретного случая. Моя цель в основном показать альтернативу для будущих ссылок, которая лучше в несколько более отдаленных случаях. Это написано для начинающих пользователей Arduino, которые не имеют большого опыта в электронике.
Для более продвинутых людей это, вероятно, будет выглядеть слишком многословно и глупо. Но я верю, что те же самые люди, вероятно, уже знают это и не нуждаются в этом ответе. Это также применимо к каждому микроконтроллеру и каждому производителю и архитектуре. Но для других микроконтроллеров вам нужно будет обратиться к правильной таблице данных, чтобы выяснить правильные регистры и имена и значения перед масштабированием.
В вашем случае вам нужна конкретная частота, и самое приятное в этом то, что фактически 56 кГц можно достичь очень легко (не считая практических недостатков деталей). Так что это тоже идеальный пример.
Генерация сигнала зависит от таймеров и источника синхронизации микроконтроллера, что хорошо объяснено в jfpoilpret. Его ответ имеет дело только с проблемой одной точки зрения, которая связана с таймерами. Но вы также можете поиграть с источником тактовых импульсов, а еще лучше - и с синергией, и с потрясающими результатами. Изменяя параметры среды, в этом случае взламывая систему и заменяя источник тактовых импульсов, мы можем справиться с конкретной проблемой гораздо, гораздо проще и проще.
Для начала напомним, что из-за переключения состояния вывода необходимо выполнить ISR в два раза больше, чем частота сигнала. Это 112 000 раз в секунду. 56 000 и 16 000 000 не складываются очень хорошо, как уже отмечалось. Нам нужно изменить либо частоту сигнала, либо частоту тактов. Давайте разберемся с неизменной частотой сигнала и найдем лучшую тактовую частоту.
Было бы очень просто выбрать часы с некоторым порядком величины, превышающим 56 кГц (или 112 кГц, но это практически то же самое), так как вы добавляете только нули, и этот тип математики является самым простым для большинства людей. К сожалению, все в этом мире является своего рода компромиссом с чем-то. Не каждое значение будет работать.
Первый пример со слишком низкой скоростью тактового генератора.
Если вы выберете тактовую частоту 56 000 Гц, вы ничего не сможете сделать, так как вам нужно будет звонить в ISR каждый цикл и больше ничего не делать. Это совершенно бесполезно. Если вы выберете в 10 раз более высокую скорость (560 кГц), у вас будет 9 (10 циклов для достижения таймером максимального значения - один цикл для вызова функции ISR), чтобы микроконтроллер выполнял вашу работу, и этого вполне может быть недостаточно. Вам просто часто требуется больше вычислительной мощности.
Если вы выберете слишком большое значение с другой стороны, то при 56 МГц микроконтроллер просто не сможет с ним работать. Это слишком быстро. Таким образом, простой выбор самой большой цены в магазине также не снизит ее.
Оригинальные Arduino Uno R3 имеют штатные часы на 16 МГц, поэтому все, что работает медленнее, гарантированно будет работать. Следующее значение, которое на порядок больше 56 и ниже 16 МГц, составляет 5,6 МГц. Это позволит вызывать ISR каждые 50 циклов и создать идеальную частоту таймера 112000 Гц. И ваш сигнал будет ровно 56 кГц. У вас будет 49 циклов микроконтроллера для выполнения вашей программы между вызовами ISR, но она по-прежнему будет примерно на 1/3 скорости исходных часов. Можно использовать 112 в качестве базы и использовать тактовую частоту 11,2 МГц, и это даст около 2/3 стандартного резонатора 16 МГц. Функция ISR будет вызываться каждые 100 циклов и при этом генерировать идеальный сигнал 56 кГц.
Однако существуют две основные проблемы с этими значениями.
Первая проблема сильно зависит от ваших потребностей: вы жертвуете примерно 1/3 (с 11,2 МГц) своей максимальной вычислительной мощности, чтобы получить точную частоту сигнала, которая использует легко обнаруживаемое значение регистра (OCR iirc ). Вы можете быть в порядке с этим или нет.
Вторая проблема - это жесткая демонстрация : очень легко найти значения, но очень часто они просто не существуют как изготовленный источник часов. Это веб-страница резонатора Фарнелла, которой просто не хватает 5,6 МГц и 11,2 МГц.
Чтобы обойти это, мы можем посмотреть на доступные значения резонатора и найти что-то еще, что можно использовать для генерации точно желаемых значений. Если мы разделим 56 на 4, мы получим 14 и, к счастью, есть резонатор 14 МГц. Это дает нам гораздо более высокую скорость и большую мощность, а также одинаково легко найти значение регистра. Чтобы вызывать ISR 112 000 раз в секунду, нам нужно поместить десятичное значение 124 или шестнадцатеричное 0x7C в регистр OCR, поэтому, посчитав 124 цикла + 1 для вызова ISR, мы получим желаемое идеальное значение.
NB
Когда микроконтроллер запускается с помощью команды программы, счетчик увеличивается. Если генерируется прерывание, вызывается ISR, и это значение сохраняется в специальном регистре. Когда код ISR завершается, значение счетчика программы восстанавливается из этого специального регистра, и программа продолжается с того места, где оно было прервано, как если бы это никогда не происходило.
Я приведу крайне тупой пример. Если вы пурист, я предупреждаю вас: может возникнуть кровотечение из носа и глаз.
Представьте, что вам нужно идти откуда-то куда-то. Пошаговые инструкции по маршруту - ваша основная программа и ее команды. Как быстро вы идете или бежите, зависит от вашей «тактовой частоты», но не от инструкций по маршруту (30 шагов вперед, 1 поворот 90 град. Влево, 10 шагов вперед, 45 град. Вправо и т. Д.) Они всегда одинаковы , Теперь представьте, что маленький ребенок или жадный коррумпированный местный политик время от времени развязывают ваши ботинки. Это событие, которое генерирует прерывание. Затем вы останавливаетесь после последнего шага, становитесь на колени и снова завязываете обувь. Это ваша программа ISR.
Затем вы продолжаете с того места, где остановились; Вы не начинаете с начала. Когда вы идете без заботы в мире и все время, вам все равно, даже если вы должны завязывать обувь каждый второй шаг. Однако, если вы делаете это с временными ограничениями, такими как бег на 100 метров на Олимпиаде (или бег от голодного хищника, питающегося мясом), остановка и завязывание вашей обуви могут иметь ужасные последствия. То же самое с микроконтроллерами. Даже если вы выполните только одну строку кода, ваша программа будет продолжаться, хотя и медленно. Если вам не важна скорость, это не будет проблемой. Если вам нужно выполнить какое-то время, например, используя другие действия, зависящие от таймера, помехи могут быть очень нежелательными и проблемными.
Меньше - больше! Более быстрые часы не всегда лучше. Устройства с меньшей тактовой частотой потребляют значительно меньше энергии. Это может быть решающим моментом в устройстве с батарейным питанием.
Необходимые циклы выводятся из следующих формул:
(тактовая частота / (предскалерное значение * необходимая частота вызовов ISR)) - 1
источник
Вы можете включать и выключать несущую, просто переключая режим вывода несущей между выходом и входом. Я использовал это для управления тепловым насосом через инфракрасный порт (дистанционное управление) 37 кГц.
источник
Нет необходимости использовать ISR для создания носителя. Просто установите таймер для получения 50% ШИМ-выхода на необходимой несущей частоте. ISR тогда просто отвечает за модуляцию несущей - обычно с интервалами 0,5 или 1 мс - гораздо более удобная скорость. По моему опыту, ошибка 5% в несущей частоте допускается большинством ИК-приемников. Я использовал Freetronics EtherMega 2560 (который имеет много таймеров), но я уверен, что другие процессоры будут работать так же хорошо.
источник