Как Arduino может выдавать определенную (т.е. 56 кГц) несущую частоту?

Я работаю над проектом свободной оптики, чтобы передавать данные по беспроводной сети между двумя точками. Для этого я использую ИК-светодиод, подключенный к Arduino Uno, который подает импульсы с несущей частотой 56 кГц для передатчика и второй Arduino с ИК-детектором 56 кГц для приемника.

Я попытался использовать delayMicroseconds () между выводами pin и low low, чтобы создать несущую частоту. Такие работы, но частота не всегда одинакова, и любые дополнительные задержки для импульсного сигнала (т. Е. Время, требуемое для вызова функции и декрементирования) могут изменить ее.

Считывая данные для ATmega328, кажется, что есть способ установить более точный импульс с использованием таймеров микросхемы. Возможно ли это, и если да, то как вы создаете импульс 56 кГц с использованием таймеров?

8 голосов | спросил jlbnjmn 24 FebruaryEurope/MoscowbMon, 24 Feb 2014 04:55:35 +0400000000amMon, 24 Feb 2014 04:55:35 +040014 2014, 04:55:35

5 ответов


10

Действительно, можно генерировать сигнал 56 кГц с таймером Arduino .

Таймер фактически может рассматриваться как специальный регистр в MCU, который содержит значение (начиная с 0), которое увеличивается с частотой, которая является тактовой частотой MCU (16 МГц на Arduino Uno), возможность, деленная на фактор, называемый prescaler . Когда это значение достигнет предела, называемого Сравнение соответствия , которое вы укажете, произойдет две вещи:

  • Значение регистра таймера сбрасывается до 0.
  • Вызывается одна функция ISR (функция прерывания) callback (вы можете определить ее, чтобы указать на свой собственный код).

Идея состоит в том, чтобы использовать этот ISR для изменения вывода логического вывода каждый раз, когда он вызывается (HIGH, затем LOW), затем HIGH ...).

Теперь, чтобы создать квадратную волну с частотой 56 кГц, вам понадобится ваш ISR, который будет называться 56000 * 2 раз в секунду (* 2), потому что вам нужно для изменения выходного значения дважды за период).

Вы можете выбрать значение предварительного делителя, которое вы хотите для таймера, из следующего списка:

  • 1 (тактовая частота не разделена, следовательно, 16 МГц)
  • 8 (тактовая частота делится на 8, следовательно, на 2 МГц)
  • 64 256 литий>
  • 1024

На Arduino Uno есть два размера таймеров /счетчиков (они называются таймер /счетчик ): 8 бит и 16 бит.

В Arduino Uno (ATmega328P) у вас есть три таймера в целом, но некоторые могут использоваться основной библиотекой Arduino или другими библиотеками, используемыми в ваших эскизах (вам придется проверить это самостоятельно):

  • timer0 (8-бит)
  • timer1 (16-разрядный)
  • timer2 (8-бит): у этого есть более предварительные параметры (1, 8, 32, 64, 128, 256 и 1024).

Теперь вам нужно создать волну с частотой 56 кГц с 16 МГц, следовательно, без предварительного кадрирования вам нужно будет рассчитывать на:

16000000 / (56000 * 2) - 1 = 141.857 (- 1), потому что таймер отсчитывает от 0 до этого значения и сбрасывает только после это было достигнуто)

Из этого расчета можно сделать два наблюдения:

  1. 141.857 не является целым числом и, следовательно, вы не сможете генерировать волну ровно 56 кГц.
  2. Без предварительной калибровки вам нужен 16-разрядный таймер, поскольку 285 не может быть представлен как 8-разрядное целое без знака.

Теперь у вас есть два варианта:

  1. Используйте 16-разрядный таймер ( timer1 ), используйте prescaler = 1 и выберите 142 как Match Match; что даст вам следующую частоту: 16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Используйте 8-разрядный таймер ( timer0 ), используйте prescaler = 8 и выберите 17 в качестве Match Match; что будет меньше точности со следующей частотой: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hz, который все еще находится в пределах требуемого диапазона.

Теперь, о том, как написать свой эскиз для этого, я советую вам проверить этот инструктируемый , который является очень полным и очень интересным для чтения.

Конечно, Полное описание ATmega328P также важно, если вы хотите в малейших подробностях понять, что вы делаете.

Некоторые важные примечания:

  • ISR выполняется с отключенными прерываниями и поэтому должен быть как можно короче. В частности, из библиотеки Arduino существует несколько функций, которые не должны вызываться из ISR.
  • Часы Arduino Uno не очень точны (он использует керамический резонатор вместо кварца, который был бы намного более точным), так что это означает, что выходная частота еще больше изменится.
ответил jfpoilpret 25 FebruaryEurope/MoscowbTue, 25 Feb 2014 00:45:44 +0400000000amTue, 25 Feb 2014 00:45:44 +040014 2014, 00:45:44
3

Я нашел tone() полезный для генерации высокочастотных импульсов на любом выводе. Он должен иметь возможность обрабатывать 56 кГц. (Редактирование: как отмечалось jfpoilpret, ближайший, на котором вы могли бы попасть на 16-мегагерцовый Arduino, составляет около 55,944 кГц)

Трудность, очевидно, будет сочетаться с вашим сигналом данных. Я не думаю, что вы могли бы сделать это в программном обеспечении, не прибегая к низкоуровневому коду. Это должно быть довольно легко на аппаратном уровне, поскольку это цифровое.

Все, что вам нужно сделать, это вывести свой сигнал данных на другой вывод, а затем объединить его с несущей с помощью логического элемента И. Комбинированный сигнал может поступать прямо на ваш ИК-передатчик.

Если у вас нет логического элемента AND, довольно просто сделать свой собственный, используя пару транзисторов. Просто выполните поиск в Интернете для «транзисторов и ворот».

ответил Peter Bloomfield 24 FebruaryEurope/MoscowbMon, 24 Feb 2014 16:02:04 +0400000000pmMon, 24 Feb 2014 16:02:04 +040014 2014, 16:02:04
2

Принятый ответ 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 циклов и создания идеальной частоты таймера 112 000 Гц. И ваш сигнал будет ровно 56 кГц. У вас будет 49 циклов MCU для выполнения вашей программы между вызовами ISR, но она все еще составляет около 1/3скорость оригинальных часов. В качестве базы можно использовать 112 и использовать тактовую частоту 11,2 МГц, и это даст примерно 2/3 от резонатора 16 МГц. Функция ISR будет вызываться каждые 100 циклов и все еще генерирует идеальный сигнал с частотой 56 кГц.

Однако с этими значениями существуют две основные проблемы.

  • Первая проблема сильно зависит от ваших потребностей: вы жертвуете примерно 1/3 (с 11,2 МГц) максимальной вычислительной мощности, чтобы получить точную частоту сигнала, использующую легко регистрируемое значение регистра (OCR IIRC ). Вы можете быть в порядке с ним, или вы не можете.

  • Вторая проблема - это hard showstopper : очень легко найти значения, но очень часто они просто не существуют в качестве созданного источника синхронизации. Это веб-страница резонатора Фарнелла , которой просто не хватает 5,6 МГц и 11,2 Мгц.

Чтобы обойти это, мы можем посмотреть доступные значения резонатора и узнать что-то еще, что можно использовать для создания точно требуемых значений. Если мы разделим 56 на 4, получим 14, и, к счастью, имеется резонатор 14 МГц. Это дает нам гораздо более высокую скорость и большую мощность и с одинаково легко найти значение регистра. Для вызова ISR 112 000 раз в секунду нам нужно поместить значение десятичного числа 124 или шестнадцатеричного 0x7C в регистр OCR, поэтому, подсчитывая 124 цикла + 1 для вызова ISR, мы получаем желаемое идеальное значение.

N.B.

  1. ISR - процедура обслуживания прерываний (это код, который выполняется только на сгенерированных прерываниях)
  2. Насколько велика ваша программа, зависит от размера памяти! Он не имеет ничего общего с тактовой частотой и не имеет никакого отношения к тому, как часто вы вызываете ISR.
  3. Когда микроконтроллер запускается с помощью команды программы, счетчик увеличивается. Если генерируется прерывание, вызывается ISR, и это значение сохраняется в специальном регистре. Когда код ISR завершается, значение счетчика программы восстанавливается из этого специального регистра, и программа продолжается от того места, где она была прервана, как если бы она никогда не происходила.

    Я приведу пример с огромным опустошением. Если вы пурист, я предупреждаю вас: может произойти кровотечение из носа и глаз.

    Представьте, что вам нужно идти куда-то куда-то. Пошаговые инструкции маршрута - ваша основная программа и ее команды. Как быстро вы идете или бегаете, зависит от вашей «тактовой частоты», но не от инструкций маршрута (30 шагов вперед, 1 поворот на 90 градусов слева, 10 шагов вперед, 45 градусов справа и т. Д.). Они всегда одинаковы , Теперь представьте себе, что маленький ребенок или жадный коррумпированный местный политик развязывают вашу обувь время от времени. Это событие генерирует прерывание. Затем вы остановитесь после своего последнего шага, встаньте на колени и снова завяжите ботинок. Это ваша программа ISR.

    Затем вы продолжаете с места, которое вы остановили; вы не начинаете с самого начала. Когда вы идете без посторонней помощи в мире и все время, вам все равно, даже если вам нужно привязать обувь к каждому другому шагу. Если вы, однако, делаете это со сменой времени, например, забегая на 100 метров на Олимпийских играх (или бегая от голодного плотоядного хищника), остановка и привязка ваших ботинок могут иметь ужасные последствия. То же самое с микроконтроллерами. Даже если вы выполняете только одну строку кода, ваша программа будет продолжена, хотя и медленной. Если вам вообще не нужна скорость, это не будет проблемой. Если вам нужно сделать некоторое время, например, используя другие действия, зависящие от таймера, помехи могут быть очень нежелательными и проблематичными.

  4. Меньше! Более быстрые часы не всегда лучше. Более медленные устройства с тактовой частотой потребляют значительно меньше энергии. Это может быть решающим моментом в устройстве с батарейным питанием.

  5. Необходимые циклы производятся из этих формул:
    (тактовая частота /(значение предварительного делителя * необходимая частота вызова ISR)) - 1

ответил zzz 1 AMpTue, 01 Apr 2014 08:10:46 +040010Tuesday 2014, 08:10:46
0

Вы можете превратить носитель и выключается просто включением режима несущей штырьковый между выходом и входом. Я использовал это для управления тепловым насосом через инфракрасный порт (дистанционное управление) на 37 кГц.

ответил kiwiron 31 MarpmMon, 31 Mar 2014 13:51:33 +04002014-03-31T13:51:33+04:0001 2014, 13:51:33
0

Нет необходимости использовать ISR для создания носителя. Просто настройте таймер, чтобы получить 50% -ный выход ШИМ на требуемой несущей частоте. Затем ISR отвечает за модулирование несущей - как правило, с интервалами 0,5 или 1 мс - гораздо более удобная скорость. По моему опыту, большинство ИК-приемников допускают 5% -ную ошибку в несущей частоте. Я использовал Freetronics EtherMega 2560 (у которого много таймеров), но я уверен, что другие процессоры будут делать то же самое.

ответил kiwiron 1 PMpTue, 01 Apr 2014 12:12:01 +040012Tuesday 2014, 12:12:01

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132