Як Arduino може вивести конкретну (тобто 56 кГц) несучу частоту?


9

Я працюю над проектом вільної космічної оптики для бездротового надсилання даних між двома точками. Для цього я використовую ІЧ-світлодіод, підключений до Arduino Uno, який імпульсує з несучою частотою 56 кГц для передавача, і другий Arduino з модулем ІЧ-детектора 56 кГц для приймача.

Я спробував використати delayMicroseconds () між командами високих і низьких контактів, щоб створити частоту несучої. Цей вид працює, але частота не завжди однакова, і будь-які додаткові затримки для імпульсу сигналу (тобто час, необхідний для виклику функції та зменшення вмісту) можуть змінити її.

Читаючи таблицю даних для ATmega328, виявляється, що існує спосіб встановити більш точний імпульс за допомогою таймерів чіпа. Це можливо, і якщо так, то як створити імпульс 56 кГц за допомогою таймерів?


Яка точність вам потрібна для вашої частоти 56 кГц? Тобто, який діапазон частот прийнятний у вашому проекті? Я запитую, оскільки використовуючи таймери Arduino поодинці, точність має обмеження.
jfpoilpret

55,5 Гц до 56,5 Гц було б ідеально для того, щоб підтримувати високий рівень чуйності в детекторі.
jlbnjmn

Відповіді:


10

Дійсно генерувати сигнал 56 кГц за допомогою таймера Arduino .

Таймер насправді може розглядатися як спеціальний реєстр в MCU, який містить значення (починаючи з 0), що збільшується на частоті, яка є тактовою частотою MCU (16 МГц на Arduino Uno), можливість поділена на коефіцієнт, який називається дошкільник . Коли це значення досягає ліміту, званого Порівняти відповідність , яке ви вказуєте, то відбуваються дві речі:

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

Ідея полягає у використанні цього 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як Порівняти відповідність; це дасть вам таку частоту:16000000 / (2 * (142 + 1)) = 55944 Hz
  2. Використовуйте 8-бітний таймер ( timer0 ), використовуйте prescaler = 8 і виберіть 17як Порівняти відповідність; що дасть меншу точність із такою частотою: 16000000 / (8 * 2 * (17 + 1)) = 55555 Hzяка все ще знаходиться в межах необхідного діапазону.

Тепер, що стосується того, як написати свій ескіз для цього, я раджу ознайомитись із цією інструкцією, яка є дуже повною і дуже цікавою для читання.

Звичайно, повна таблиця даних ATmega328P також важлива, якщо ви хочете зрозуміти, якнайшвидше, що ви робите.

Деякі важливі зауваження:

  • ISR виконується з відключеними перериваннями і, таким чином, повинен бути якомога коротшим. Зокрема, існує кілька функцій з бібліотеки Arduino, які не повинні викликатися з ISR.
  • Годинник Arduino Uno не дуже точний (він використовує керамічний резонатор замість кварцу, який був би набагато точнішим), тому це означає, що вихідна частота зміститься далі.

2
Крім того, коли визначений ліміт буде досягнуто, апаратне забезпечення може переключити шпильку. Таким чином, взагалі не потрібно використовувати ISR. Завжди буде тремтіння з ISR, оскільки інструкція не може бути перервана після її запуску. Однак обладнання завжди перемикає штифт із потрібною швидкістю.
Нік Гаммон

Дещо дивно, що Arduino Uno використовує керамічний резонатор, але джерелом для нього є Arduino UNO FAQ (поблизу "Чи Uno використовує резонатор або кристал для процесорних годин?" ).
Пітер Мортенсен

3

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

Складність, очевидно, буде поєднувати його з вашим сигналом даних. Я не думаю, що ви могли це зробити в програмному забезпеченні, не вдаючись до коду низького рівня. Однак апаратне забезпечення має бути досить простим, оскільки воно є цифровим.

Все, що вам потрібно зробити, - це вивести свій сигнал даних на інший контактний контакт, а потім поєднати його з носієм за допомогою воріт AND. Комбінований сигнал може переходити прямо до ІЧ-передавача.

Якщо у вас немає ворота AND, то зробити його самостійно можна за допомогою пари транзисторів. Просто шукайте в Інтернеті "транзистор і ворота".


Отримувачі часто мають активні низькі показники. Якщо ви підключите верхню частину світлодіода до 56 кГц, а нижню - ваш контактний дані, коли штифт даних знизиться, ви отримаєте ІЧ-вихід, який повинен змусити ресивер знизитись. Ні і ворота не потрібні, просто світлодіодний резистор. Тільки проблема обмежується тим, що можуть керувати поточними іонами.
EternityForest

2

Прийнята відповідь jfpoilpret дуже добре написана, цілком справедлива, і в 99% випадків я зроблю саме те, що він пояснює. Його рішення знаходяться в межах заданих параметрів, тому вони повинні працювати дуже добре. Але що краще, ніж « дуже добре »? Вдосконалення! Зрештою, питання полягає у формуванні точного значення. Як сказано, достатньо близько в більшості випадків (можливо, у всіх), і навіть якщо мати справу з чимось як годинником, коли 1 секунда потребує 1 секунди, вам все одно доведеться страждати від успадкованих недоліків деталей.

Те, що я підкажу, не завжди можливо. У деяких випадках це можливо, але з набагато більшими клопотами та зусиллями, ніж у цьому випадку. Чи варто це залежно від конкретного випадку. Моя мета, головним чином, показати альтернативу для майбутніх посилань, що краще в деяких випадках. Це написано для початківців користувачів Arduino, які не мають великого досвіду в галузі електроніки.

Для більш просунутих людей це, мабуть, буде виглядати занадто багатослівним та занедбаним. Але я вважаю, що ті самі люди, напевно, це вже знають і не потребують цієї відповіді. Це також стосується кожного мікроконтролера та кожного виробника та архітектури. Але для інших мікроконтролерів вам знадобиться проконсультуватися у правильному аркуші даних, щоб з’ясувати правильні регістри та прізвища імен та значень.

У вашому випадку вам потрібна конкретна частота, і приємна річ у тому, що саме 56 кГц насправді можна досягти дуже просто (не рахуючи практичних недосконалостей деталей). Тож це також ідеальний приклад.

Генерування сигналу залежить від таймерів та тактового джерела мікроконтролера, як це добре пояснив jfpoilpret. Його відповідь стосується проблеми лише однієї точки зору, яка суперечить таймерам. Але ви також можете поспілкуватися з джерелом годинника, а ще краще - з синергією та приголомшливими результатами. Змінюючи параметри навколишнього середовища, в цьому випадку злом системи та замінюючи джерело тактового сигналу, ми можемо впоратися з конкретною проблемою набагато, набагато більшою легкістю та простотою.

Спершу нагадаю, що через зміну стану штифта потрібно виконати ISR в два рази більше, ніж частота сигналу. Це 112 000 разів за секунду. 56 000 і 16 000 000 не складаються дуже добре, як уже зазначалося. Нам потрібно змінити або частоту сигналу, або тактову частоту. Давайте зараз розберемося з незмінною частотою сигналу і знайдемо кращу тактову частоту.

Найпростіше було б вибрати тактовий годинник на порядок більше 56 кГц (або 112 кГц, але це практично те саме), оскільки ви додаєте лише нулі, і такий вид математики для більшості людей найпростіший. На жаль, все в цьому світі - це якийсь компроміс з чимось. Не кожна цінність спрацює.

Перший приклад - із занадто низькою тактовою швидкістю генератора.

Якщо ви вибрали тактову частоту 56000 Гц, ви нічого не зможете зробити, оскільки вам потрібно буде викликати 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 ). З тобою може бути добре, а може і не.

  • Друга проблема - це жорсткий шоустоппер : Знаходити значення дуже просто, але дуже часто вони просто не існують як виготовлений годинниковий джерело. Це веб-сторінка резонатора Farnell, якій просто не вистачає і 5,6 МГц, і 11,2 МГц.

Щоб обійти це, ми можемо переглянути доступні значення резонатора та дізнатись ще щось, що може бути використане для генерування саме бажаних значень. Якщо ділимо 56 на 4, ми отримуємо 14, і на щастя, є резонатор 14 МГц. Це забезпечує нам набагато більшу швидкість і більшу потужність і однаково легко знайти значення регістра. Для виклику ISR 112 000 разів на секунду нам потрібно поставити значення десяткової 124 або шістнадцяткової 0x7C в регістр OCR, тому, рахуючи 124 циклів + 1 для виклику ISR, ми отримуємо бажане ідеальне значення.

NB

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

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

    Уявіть, що вам доведеться ходити звідкись кудись. Покрокові інструкції щодо маршруту - це ваша основна програма та її команди. Наскільки швидко ви ходите чи бігаєте, залежить від вашої "тактової швидкості", але не від інструкцій маршруту (30 кроків вперед, 1 поворот на 90 градусів вліво, 10 кроків вперед, 45 градусів праворуч тощо). Вони завжди однакові . А тепер уявіть собі маленьку дитину чи жадібного корумпованого місцевого політика, розв'язуючи взуття час від часу. Це подія, яка породжує перерву. Тоді ти зупинишся після свого останнього кроку, знову встаєш на коліна і зав’яжи взуття. Це ваша програма ISR.

    Потім ви продовжуєте з місця, де ви зупинилися; ви не починаєте з початку. Коли ти без піклування ходиш по світу і весь час, то тобі не байдуже, навіть якщо доведеться зав’язувати взуття кожен другий крок. Якщо ви все ж зробите це з обмеженнями у часі, як, наприклад, біг на 100 метрів на Олімпіаду (або біг від голодного хижака, що їсть м'якоть), зупинка та зав'язування взуття може мати серйозні наслідки. Те саме і з мікроконтролерами. Навіть якщо ви виконаєте лише один рядок коду, ваша програма буде продовжуватися, хоч і повільно. Якщо ви зовсім не піклуєтеся про швидкість, це не буде проблемою. Якщо вам доведеться виконати певний час, наприклад використання інших залежних від часу дій, втручання може бути дуже небажаним та проблематичним.

  4. Менше значить більше! Більш швидкий годинник не завжди кращий. Пристрої з повільнішим тактовим режимом споживають значно менше енергії. Це може стати вирішальним моментом у пристрої, що працює на акумуляторі.

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


TLDR: Випаровуйте керамічний осцилятор 16 МГц і замініть його іншим, що дозволяє рівно 56 кГц шляхом цілого поділу (наприклад, 14 МГц і ділити на 250).
Пітер Мортенсен

0

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


0

Для створення носія не потрібно використовувати ISR. Просто встановіть таймер для отримання 50% виходу ШІМ на необхідній несучій частоті. Тоді ISR відповідає лише за модуляцію носія - як правило, з інтервалом 0,5 або 1 мс - набагато комфортнішою швидкістю. На мій досвід, більшість ІЧ-приймачів допускає 5% помилок у несучій частоті. Я використовував Freetronics EtherMega 2560 (який має багато таймерів), але я впевнений, що і інші процесори будуть так само добре.


Як саме реалізується тоді модуляція носія? Зміна режиму штифта захоплення виходу таймера між входом (оператор вимкнено) і виходом (оператор включений)?
Пітер Мортенсен
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.