Содержание
Урок 1. Первый проект
Урок 2. Управление кнопками
Урок 3. Подключение LCD
Урок 4. Использование ШИМ
Урок 5. Таймеры
Урок 6.1. Статическая индикация
Урок 6.2. Динамическая индикация
Урок 7.1. Генерация звука
Урок 7.2. Генерация звука. Продолжение
Урок 8.1. Передача данных через UART
Урок 8.2. Передача данных через UART. Продолжение»
Урок 9. Передача данных через SPI
Урок 10. Изучение АЦП. Простой вольтметр
Урок 11. Получение синуса при помощи ШИМ
Урок 12. Измерение температуры
Урок 13. Внешние прерывания.
Урок 14. Использование отладчика
Урок 15.1. Управление инкрементальным энкодером
Урок 15.2. Управление громкостью, при помощи энкодера
Урок 16. Управление RGB светодиодом
Урок 17. Использование ИК
Урок 18.1. Знакомство с графическим дисплеем
Урок 18.2 Вывод изображения на графический дисплей
Урок 18.3 Вывод русскоязычного текста
Урок 19. Формирование сигнала, при помощи ЦАП (R2R)
Урок 20. Опрос матричной клавиатуры
Урок 21. Сторожевой таймер
Урок 22.1 Воспроизведение wav. Введение.
Урок 22.2 Воспроизведение wav. Продолжение.
Урок 23.1 Работа с внешней памятью
Урок 23.2 Работа с файловой системой Fat

Мы довольно часто в повседневной жизни сталкиваемся, с использованием беспроводных передающих устройств. Эту тему нельзя было обойти стороной, поэтому в этом уроке речь пойдет об использовании инфракрасного (ик) передатчика и приемника, управляемых AVR микроконтроллером. Тема интересная и новая для меня, кроме того, хотелось чтобы она была понятна любому начинающему. Поэтому все варианты, использующие протоколы RC5 и т.п. не рассматривались, желающие могут самостоятельно их освоить, моя цель была понять принцип работы и, как результат, помигать светодиодом на расстоянии.

Решением стала статья с хабры (habrahabr.ru/post/82383), в которой для управления роботом использовался ик. Основная идея весьма проста — информация передается и принимается, как при обычной работе с UART, ик передатчик и приемник выполняют роль проводов. Единственная особенность, то что сигнал с UART должен быть промодулирован на определенной частоте.

Теперь обо всем подробнее, начнем с приемника.В качестве приемника использован TSOP4836. Как уже было сказано, приемник работает на определенной частоте, данный приемник работает на частоте 36кГц. Если принимаемый сигнал отклоняется от заданной частоты, то соответственно снижается чувствительность.

Схема приемника достаточна проста, как впрочем и просто использовать ее программно — достаточно просто ловить данные по UART никаких дополнительных действий. Также возможно подсоединить к FT232 и смотреть терминалкой приходящие данные, мне это очень помогло во время отладки.

lesson17-2

lesson17-3

Для управления светодиодом использована Atmega8, думаю пояснений по коду не требуется, единственное, на что стоит обратить внимание, это скорость UART-2400, она напрямую связана с частотой, на которой работает приемник «10/fo is recommended for optimal function»

#include <mega8.h>
#include <stdio.h>
 
void main(void)
{
char i;
// Input/Output Ports initialization
// Port B initialization
// Func7=Out Func6=Out Func5=Out Func4=Out Func3=Out Func2=Out Func1=Out Func0=Out 
// State7=0 State6=0 State5=0 State4=0 State3=0 State2=0 State1=0 State0=0 
PORTB=0x00;
DDRB=0xFF;
 
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=In Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=T State0=T 
PORTD=0x00;
DDRD=0x00;
 
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: On
// USART Transmitter: Off
// USART Mode: Asynchronous
// USART Baud Rate: 2400
UCSRA=0x00;
UCSRB=0x10;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0xCF;
 
while (1)
      {
          i=getchar();
          if(i=='0')
          {
          PORTB.0=0;
          }
          if(i=='1')
          {
          PORTB.0=1;
          }
      };
}

Теперь перейдем разберемся с передатчиком, в качестве которого использован инфракрасный диод TSAL6200. В целом ничего сложного, задействована ножка Tx, для передачи данных из UART, ножка PB1 нужна для формирования несущей частоты, т.е. она дрыгается с частотой 36кГц.

lesson17-1

17-2

Основной проблемой, в данной схеме, является то, что ик диод потребляет порядка 100мА, поэтому, если дать полный ток, то ножка мк может сгореть. Поэтому ток ограничен, соответственно в ущерб излучаемой мощности. Можно схему переделать и придумать как от этого избавиться, однако для учебных целей схема вполне годна и наглядна.

Теперь пару слов о формировании несущей частоты, ножка таймера T1А включена в режим Toggle, это значит что при достижении таймером величины указанной в OCR1A, состояние ножки изменится на противоположное, подобное мы делали в уроке про генерацию звука.

lesson17-6

Частота, которую можно получить на ножке таким способом определяется по формуле из даташита:

lesson17

Focn — частота, с которой должна дрыгаться ножка;

Fclk — частота таймера;

N — частота предделителя таймера;

OCRn — значение регистра  сравнения;

В остальном исходный код для передатчика, ничем не отличается, от ранее изученного нами, в статье про передачу данных по UART. Для удобства повесил 2 кнопки PB2 передает ‘1’ — соответственно зажигает светодиод, PB0 передает ‘0’ — гасит светодиод.

#include <mega8.h>
#include <stdio.h>
 
void main(void)
{
bit ps=0;
// Input/Output Ports initialization
// Port B initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=P State1=0 State0=P 
PORTB=0x05;
DDRB=0x02;
 
// Port D initialization
// Func7=In Func6=In Func5=In Func4=In Func3=In Func2=In Func1=Out Func0=In 
// State7=T State6=T State5=T State4=T State3=T State2=T State1=0 State0=T 
PORTD=0x00;
DDRD=0x02;
 
// Timer/Counter 1 initialization
// Clock source: System Clock
// Clock value: 8000,000 kHz
// Mode: CTC top=OCR1A
// OC1A output: Toggle
// OC1B output: Discon.
// Noise Canceler: Off
// Input Capture on Falling Edge
// Timer 1 Overflow Interrupt: Off
// Input Capture Interrupt: Off
// Compare A Match Interrupt: Off
// Compare B Match Interrupt: Off
TCCR1A=0x40;
TCCR1B=0x09;
TCNT1H=0x00;
TCNT1L=0x00;
ICR1H=0x00;
ICR1L=0x00;
OCR1A=0x6E;
OCR1B=0x00;   
 
// USART initialization
// Communication Parameters: 8 Data, 1 Stop, No Parity
// USART Receiver: Off
// USART Transmitter: On
// USART Mode: Asynchronous
// USART Baud Rate: 2400
UCSRA=0x00;
UCSRB=0x08;
UCSRC=0x86;
UBRRH=0x00;
UBRRL=0xCF;
 
while (1)
      {
         if((PINB.0==0) && (ps==0))
         {
         putchar('0');
         ps=1;
         }
 
         if((PINB.2==0) && (ps==0))
         {
         putchar('1');
         ps=1;
         }
 
 
         if((PINB.0==1)&&(PINB.2==1))
         {
         ps=0;
         }
      };
}

На железке все работало стабильно, глюков замечено не было, в пределах 1,5-2 метров прием устойчивый под разными углами, дальше — нужно целиться. В пределах 3-4 метров все работает нормально, дальше нет возможности проверить.

Исходники доступны здесь

46 комментариев: Урок 17. Использование ИК в AVR микроконтроллерах

  • Уважаемый админ вот пробую сделать ик барьер вот код ,скажите где ошибаюсь.
    у меня на порту С стоят ик приомники луч прямо попадает на них когда луч прерывается срабатывает PORTD у меня вроде работает но не стабильно пожалуста потскажите

    #include
    #include
    void main(void)
    {
    PORTB=0x00;
    DDRB=0x00;
    PORTC=0x3F;
    DDRC=0x00;
    PORTD=0x00;
    DDRD=0x80;
    // Timer/Counter 2 initialization
    ASSR=0x00;
    TCCR2=0x68;
    TCNT2=0x00;
    OCR2=0x00;
    while (1)
    {
    if (PINC.0==0||PINC.1==0||PINC.2==0||PINC.3==0)
    {
    PORTD.7=1;
    delay_ms(200);
    PORTD.7=0;
    };

    }
    }

  • Что значит раьотает нестабильно, опишите.

  • PORTD постаянно то включается то отключается
    я пробывал на одном приомнике все нормально но если подключаю 3 или 4 тогда все такое впечатление какбутто дребезги но пробывал потяжку не получяется .

  • Может недостаточно освещено, поэтому один какой то срабатывает

  • нет освешением все нормально ,тут я смотрел осцилографам на фходах амплитуда дрыгает пробывал резистор поттяжки не помагает пожалуста посаветуйте как разобратся

  • Попробуйте убрать подтяжку порта С

  • а можно тут использовать ADC чтоб кантралер определял наличие конкретного сигнала и реагировал только на его отсутствие и присутствие? если можно чуть по подробнее опишите для чайников. заранние спасибо

  • Дело в том, что датчик должен выдавать логические уровни, поэтому АЦП именно тут немного не в тему.

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

  • если можно . мне чуть не совсем понятно откуда берется значение (OCRn — значение регистра сравнения); из формулы указанной выше

  • OCRn это указание сколько тиков нужно сделать таймеру, т.к. нам нужно получить частоту 36кГц для несущей, то эти 36кГц являются Focn, т.е. из формулы мы должны получить OCRn. Здесь мы его не берем, здесь мы его рассчитываем. Если вы светите на ваши фотоприемники с такой частотой, то у вас все и будет дрыгаться

  • Добрый день, не подскажите как реализовать свет в комнате на ик ? Что бы можно было включить\выключить и сделать ярче\темнее ? Спасибо.

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

  • Подскажите, а как быть с напряжением в 220В ?

  • самый простой способ — реле

  • А не найдётся схемки пульта и приёмника на attiny13 на 4 команды? Ищу долго, но толком ничего не нашёл. А сам-то не силён в писанине, но залить HEX смогу. Если знаете схемки и пульта и приёмника, чтобы они были связаны вместе, то дадите ссылочку пожалуйста!. Буду очень благодарен.

  • Александр, подобная статья планируется

  • Ну чтож, буду ждать.

  • Делаю ИК барер только на одной меге8. Всё как бы понятно и работает если данные приходят такие какие послал через UART. или приходят искажонные. Я их сравниваю с тем что выслал и если несовпадают, делаю дело. Но что делать если данные послал, а они недошли совсем? Прерывания на принятия нету, а в массиве старые данные…Пока нет мыслей…. 🙁 Дайте подсказку !!!! ❓ ❓ ❓

  • посмотрите через какую нибудь фотокамеру мигает ли светодиод

  • не втом проблема. Проблема как после того как послал данные и они совсем не дошли до приёмника т. е. закрыт путь чем то между передатчиком и приёмником. Посылаю данные через ИК и если они не дошли или дошли искажонные, что -то делаю, скажим включаю сирену. Проблема заключаеться в том что немогу очистить массив в который принимаю данные. Массив из 16 симболов, а посылаю 8 (*ABCDEF$). Может в том проблема. Делаю так:
    в основном цикле

    очищаю массив в который принимаю данные
    uart_data[0]=0;
    uart_data[1]=0;
    uart_data[2]=0;
    и т. д.
    uart_data[15]=0;

    посылаю 8 байт по очереди
    putchar(0x2A); // начало трансляции
    while(!( UCSRA & (1<<UDRE)))
    {
    } // Ждем опусташения UDR
    putchar(0x41); // A
    while(!( UCSRA & (1<<UDRE)))
    { PORTD.2=0;
    } // Ждем опусташения UDR
    и т.д.
    принимаю данные в прерывании
    проверяю массив и ищю "*"
    x=0;
    while(t_char !='*')
    {
    uart_data[x];
    t_char = uart_data[x];
    x++;
    }
    t_char=0;
    вывожу данные в экран
    lcd_clear();
    delay_ms(500);
    lcd_gotoxy(0,1);
    lcd_putchar(uart_data[x]);
    x++;
    lcd_putchar(uart_data[x]);
    и т. д.
    проверяю строку
    if(uart_data[x]!=0x41 || uart_data[x++]!=0x42 || uart_data[x++]!=0x43 || uart_data[x++]!=0x44 || uart_data[x++]!=0x45 || uart_data[x++]!=0x46)
    {
    lcd_puts("error-3");
    }

    и ошибки нет если приёмник или передатчик закрыты наглухо.
    Может надо принимать данные не в прерывании а просто функцией getchar(); ??? ❓ ❓ ❓

  • может проще сделать таймаут? например, постоянно слать один и тот же байт, каждый прием сбрасывает таймер в ноль, но если байт не придет и таймер перевалит через определенное значение, то запускать сирену.

  • Ну да. Наверное нет смысла слать много байт для такого прибора, достаточно 1. С таймером хорошая идея, но у меня, где я хочу применить этот ИК барьер, уже нет свободных таймеров :sad:. Ещё попробую поиграться только с одним байтом . 🙂

  • Не подскажите, где можно найти пример получение кода с пульта для ИК приемника на Atmega8?

  • Ознакомьтесь с http://avr-start.ru/?p=3516

  • Данный урок повторил на других МК (tiny2313+mega8), на скорости 1200, тактрировал МК от внутренних генераторов — работает уверенно с расстояния 5м. Хороший урок, спасибо!

  • Объясните пожалуйста, зачем в схеме приемника конденсатор и резистор, если он работает и без этого. Каково их предназначение?

  • это фильтр. если для опытов, то можно и не ставить. если в устройство которым будете пользоваться то лучше поставить.

  • Он фильтрует перепады напряжения или что?

  • Можно и так сказать. В общем чтобы убрать помехи по питанию.

  • А если на один контроллер примудрить к тх uarta китайский передатчик, на rx uarta другого контроллера приёмник. Будет работать? Передатчик и приёмник на 433 МГц.

  • будет

  • У меня вопрос я сделал управление лампой с помощью ик пульта , в люстре 2 фазных провода одним питаю модуль для пульта другой идет на лампу от виключателя. Задача нужно независимо включать виключать как пультом так виключателем как проходной виключатель как сделать програмно? Все варианти пробовал виключатель приоритетний над пультом так как пульт включает импульсно подал сигнал лампа горит а виключатель постоянно включен или виключен

  • отлавливайте прерывание по спаду или нарастанию, что последнее пришло то и приоритетное, вроде задача то простая

  • Вопрос про частоту.
    Вы ее замеряли? Или только расчитали?
    В чем фишка… Нужна мне управлялка лампочкой чтоб с дивана не вставать, китайские радиомодули склонны ловить помехи, даже несмотря на применение «родного» протокола для «пультов от сигнализации» срабатывание по радиоканалу оказалось нестабильным. Умучился. Зато обратил внимание что самсунговским пультом от телевизора свети хоть куда- все равно телек стабильно принимает, ни о каком «прицеливании» нет и речи. Озаботился ИК-пультом. Это преамбула…
    И вот с чем столкнулся… По расчету выходят примерно те же значения, что и у вас в статьях (хочу использовать tiny13 со стандартным генератором- там другие цифры получаются, но методика та же). Впрочем, лукавлю… В код-вижн-авровский визард ставлю значение в микросекундах (для удвоенной частоты, разумеется)- он выдает хекс-число для регистра. И прогнал я все это дело через Протеус… а он мне показал вовсе не то что расчитано! Должно быть 36 килогерц, а он выдает что-то около 30. Подобрал пока «вручную», но в железе не испытывал…
    Вы пишете что «надо прицеливаться»- возможно, не в малом токе светодиода причина, а именно в неверно выдаваемой частоте?

  • измерял осциллографом, на приемнике.

  • Благодарю за ответ. 🙂
    «Осциллограф не является средством метрологического контроля».
    Поскольку живым частотомером сам не обладаю- попробую на железе и «по расчету», и «по частотомеру Протеуса», о результатах отпишусь.

  • ЗЫ: Только сейчас сообразил: мерять что-либо на приемнике бессмысленно, поскольку оный выдает уже «готовый» демодулированый код- что свидетельствует лишь о том, что чего-то как-то он принимает, а меня интересовала частота модуляции, напрямую влияющая на «дальнобойность». Если посмотреть даташит на TSOP- там по графику зависимости чувствительности от частоты видно, что отклонение по частоте на 10% (3-4 килогерца) ухудшает чувствительность уже вдвое…
    В любом случае извините что докопался, возможно- зря… Зато отписаться о результатах эксперимента теперь- дело чести.

  • Как обещал- отчитываюсь о результатах эксперимента.
    Элементная база: Attiny13 (работа от встроенного генератора на 9,6 МГц без предделителей), ноунейм ИК-светодиод, включен между ногами OC0A и PORTB.2 через резистор 220 Ом (предельный ток пинов и порта не превышен), прокол NEC- значит работаем с несущей 38 КГц, излучающий диод и приемник жестко закреплены друг напротив друга, питание 5 вольт (от программатора), код передается каждые полсекунды, в качестве приемника- китайская «свечка» (включается/выключается).

    Расчетное значение таймера: 0x82
    Светим без препятствий- приемник реагирует. Светим через бумажку- реакции нет.
    Подобраное в протеусе значение таймера: 0x8C (частотомер кажет 37,798 КГц)
    Светим без препятствий: приемник реагирует. Светим через ту же бумажку: приемник все равно реагирует!!!

    Результат эксперимента: расчетное значение несущей частоты не совпадает с реальным, Протеусу верить можно, точное значение несущей частоты можно подобрать с помощью его «виртуального» частотомера.

    Надеюсь, мой камент был полезен. 🙂

  • Чудес не бывает, либо посчитано не правильно, либо исходные данные не верные. Таймер штука дубовая, работает синхронно основной частоте, с учетом предделителей. Может режим не CTC? Может округлили не правильно? Может предделители поставили? И еще, не забывайте, что у тини13 встроенный генератор — лютое говнище, по даташиту он может плавать на 10%.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *

Последние комментарии
  • Загрузка...
Счетчик
Яндекс.Метрика