Category Archives: AVR. Учебный курс

Управление большим количеством светодиодов через Binary Angle Modulation

Вот приспичило вам сделать себе могучую светодиодную хреновину, чтобы моргала и переливалась. Да еще в RGB и плавненько так. Собрали вы это дело, поглядели на количество каналов которыми нужно рулить и призадумались…
 

▌А что не так с ШИМ?
Да все с ним хорошо, только аппаратных каналов обычно всего несколько штук. А программный ШИМ имеет ряд недостатков. Да, можно взять и на базе алгоритма управления кучей сервомашинок, используя всего один таймер собрать многоканальный ШИМ, но сколько у нас будет вызовов прерываний?
 


 

Каждый отдельный фронт потребует своего прерывания на смену уровня. А представьте, что у нас этих каналов будет не 4, а 40? Или 400? Да контроллер из прерываний вылезать не будет. Прерывания будут налезать друг на друга, порождая джиттер. Не говоря уже о том, что все эти каналы надо будет при любом изменении скважности заново сортировать по длительности. В общем, тупилово будет еще то.
 

▌Нас спасет BAM
Но решение есть. Зовется этот метод BAM. Суть его в том, что мы включаем нагрузку импульсами, поразрядно, с длительностью равной весу разряда.

 

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

 

Интегрируется все аналогично обычному ШИМу. Но есть ряд нюансов:

  1. Частота плавает и на малых разрядах она повышается. Для светодиода или грелки это наплевать. А вот двигатель или еще какую нагрузку с реактивными элементами вроде обмоток или емкостей я бы таким сигналом питать не стал.
  2. При переходе с малых весов к одному большому наблюдается мерцание. Но с этим можно бороться, подробности ниже.
  3. Выдавать вес лучше с большего к меньшему, так меньше заметно влияние второго пункта.

 
(далее…)

Read More »

Интерфейс — одна кнопка

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

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

Итак, что у умеет наша кнопка?
 

  • Ее можно нажимать кратко
  • Можно жать длинно
  • Можно делать разные комбинации нажатий
  • Ее можно отпускать в нужный момент

 
(далее…)

Read More »

FT2232D и AVR. Прошивка и отладка по JTAG

AVRdude Bitbang
Поскольку я привык к связке avrdude+sinaprog то менять ее на что либо совершенно не хотелось. Поэтому в первую очередь я решил проверить, а можно ли юзать FT2232 в том же режиме, что и FT232RL. И пнул дудку в адрес включенной FTDI. Она мне отозвалась, что мол устройство ft0 найдено и работает, но вот контроллер не подключен. Ожидаемо. Осталось только выяснить соответствие выводов у FT2232 и написать конфиг для avrdude.

Все оказалось проще чем я думал. С точки зрения avrdude микруха FT2232 представляет собой всего лишь две FT232R которые она видит как ft0 и ft1 (ну либо другие ft в зависимости от числа FTDI микросхем воткнутых в систему). А дальше все оказалось совсем элементарно — выводы шины ADBUS принадлежали интерфейсу ft0, а BDBUS устройству ft1. Логично, чо.
(далее…)

Read More »

AVR Studio 4.19 и AVR Toolchain

Обновился я тут недавно до AVR Studio 4.19 и спустя некоторое время обнаружил, что все проекты, что были на Си, отказываются компилироваться. Либо компилятся, но не отлаживаются. После недолгого выяснения и теребления народа из сообщества выяснилось, что WinAVR как самостоятельный проект ныне не существует, а полностью перешел под крыло Atmel и ныне зовется AVR Toolchain. Ставить его нужно отдельно с сайта Atmel, предварительно снеся старый WinAVR, поверх студии 4.19. Ставится он теперь в дебри папки студии. В целом ничего не изменилось, по крайней мере все старые проекты скомпилились без проблем.

Чтобы вам не париться с регистрацией на сайте Atmel я бросил пару файликов:

Read More »

Работа с графическим дисплеем WG12864 на базе контроллера KS0107

Обычно для вывода информации сигнального дисплея на HD44780 более чем достаточно. Но иногда нужно нарисовать картинку, график или хочется сделать красиво, с модными менюшками. Тут на помощь приходят графические дисплеи. Одним из самых простых и доступных является дисплей на контроллере KS0107 или аналоге. Например, WG12864A от Winstar. Сам дисплей вполне свободно достается, имеет довольно большой размер (диагональ около 80мм) и разрешение 128х64 пикселя. Монохромный. Цена вопроса 400-500р.
 

Вот такой вот:

(далее…)

Read More »

Работа с резистивным сенсорным экраном

Хоть резистивный touchscreen и является устаревшим и активно вытесняется емкостными сенсорами, но тем не менее он еще не скоро канет в Лету. Во первых из-за простоты и дешевизны, а во вторых из-за элементарной работы с ним.

Конструктив
Итак, как он устроен. Там все очень и очень просто. Есть две пленки, сделанные из проводящего материала, а между ними гранулы диэлектрика. Когда касаемся пальцем, то продавливаем зазор между пленками и контачим верхнюю на нижнюю. Ну, а определить координаты касания уже дело несложное.

Для этого на каждую пленку нанесено по два электрода. Слева-справа на одной и сверху-снизу на другой. Крест на крест, в общем. Поскольку сопротивление пленки довольно большое, под сотни ом, то образуются как бы два перпендикулярных резистора, висящие друг над другом.
(далее…)

Read More »

AVR. Учебный Курс. Асинхронный режим таймера

Иногда полезно иметь в системе часы отсчитывающие время в секундах, да еще с высокой точностью. Часто для этих целей применяют специальные микросехмы RTC (Real Time Clock) вроде PCF8583. Вот только это дополнительный корпус, да и стоит она порой как сам МК, хотя можно обойтись и без нее. Тем более, что многие МК имеют встроенный блок RTC. В AVR его правда нет, но там есть асинхронный таймер, служащий полуфабрикатом для изготовления часиков.

Первым делом нам нужен часовой кварц на 32768Герц.

Почему кварц именно 32768Гц и почему его зовут часовым? Да все очень просто — 32768 является степенью двойки. Два в пятнадцатой степени. Поэтому пятнадцати разрядный счетчик, тикающий с частотой 32768 Гц, будет переполняться раз в секунду. Это дает возможность строить часы на обычной логической рассыпухе без каких либо заморочек. А в микроконтроллере AVR организовать часы с секундами можно почти без использования мозга, на рефлексах периферии.

Асинхронный режим таймера
Помните как работают таймеры? Тактовая частота с основного тактового генератора (RC внешняя или внутренняя, внешний кварц или внешний генератор) поступает на предделители, а с выхода предделителей уже щелкает значениями регистра TCNT. Либо сигнал на вход идет с счетного входа Тn и также щелкает регистром TCNT

Структура же Timer/Counter2 немного отличается от остальных — у него нет счетного входа, зато есть возможность задействовать собственный тактовый генератор.

Для этого на выводы TOSC2 и TOSC1 вешается кварцевый резонатор. Низкочастотный, обычно это часовой кварц на 32768Гц. На Pinboard он смонтирован справа от контроллера и подключается перемычками. Причем тактовая частота процессора должна быть выше как минимум в четыре раза. У нас тактовая от внутреннего генератора 8Мгц, так что нас это условие вообще не парит :)

Часовой кварц вешается просто на выводы. Без конденсаторов и каких либо заморочек.
(далее…)

Read More »

Подключение клавиатуры к МК по трем проводам на сдвиговых регистрах. Часть 2. Буквенный ввод как на телефоне

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

Аппаратная часть
Как вы уже догадались, чтобы подключить дополнительные кнопки к блоку клавиатуры, нужно добавить дополнительный сдвиговый регистр, который будет захватывать нажатия других восьми кнопок. Ниже приведена блок схема этой конструкции:

Рассмотрим режим работы, когда при каждом клике ногой CLK происходит сдвиг битов влево по направлению к старшему (S0 поднята, S1 опущена). Взглянем на сдвиговый регистр U1. При каждом дрыге ногой CLK, бит, который находится на выводе Qn, перемещается на вывод Qn+1, тоесть сдвигается в сторону старшего бита (влево). Но так как биту, который находится на ноге Q7 уже некуда сдвигаться, то он по идее должен бы был пропасть. Чтобы этого не произошло, мы посылаем его на следующий сдвиговй регистр U2, подключив Q7 регистра U1 к ноге SR SER регистра U2. Объясню, что же это за нога. В рассматриваемом нами режиме работы сдвигового регистра (S0 поднята, S1 опущена) биты смещаются в cторону старшего, а на место младшего становится бит, который в данный момент находится на ноге SR SER. Так как два наших сдвиговых регистра тактируются от одного источка (микроконтроллера), то бит на ноге Q7 сдвигового регистра U1, при сдвиге не теряется, а перескакивает на сдвиговый регистр U2, где продолжает свой путь в микроконтроллер. (далее…)

Read More »

Подключение клавиатуры к МК по трем проводам на сдвиговых регистрах

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

Суть
Подключение клавиатуры осуществляется по трем сигнальным проводам. Дополнительные элементы: сдвиговые регистры sn74198n и несколько резисторов. Максимальное количество кнопок ограничивается лишь максимально допустимым временем на сканирование клавиатуры. Я использовал в своем проекте 16 кнопок, но путем добавления новых сдвиговых регистров, можно увеличить данное число до необходимого вам значения. Вас будет ограничивать лишь пропорционально возрастающее время сканирования клавиатуры.

Аппаратная часть
Сдвиговые регистры – вещь довольно удобная за счет своей дешевизны и универсальности. Их часто используют для подключения светодиодов, семисегментных индикаторов и т.п. по небольшому количеству выводов микроконтроллера. В нашем случае, будем проделывать почти все тоже самое, но в обратную сторону:будем передавать данные не «из микроконтроллера», а «в него». Для наглядности привожу блок схему работы данного устройства:

  • 1.Блок Клавиатуры
  • 2.Сдвиговый регистр
  • 3.МК

Блок клавиатуры представляет собой набор кнопок, которые одним выводом подключены к земле, а другим подключаются к соответствующему входу сдвигового регистра.
(далее…)

Read More »

Управление множеством сервомашинок

При построении разных роботов порой приходится использовать несколько сервоприводов. А если это какой-нибудь шестиногий паук, то приводов там этих просто тьма. Как ими управлять? На форуме кое кто даже сокрушался, что ему бы для этих целей плисину применить. Хотя на кой черт там ПЛИСка, когда с рулением даже трех десятков сервоприводов справится самый рядовой микроконтроллер, затребовав под это дело всего один таймер.

Итак, кто не помнит как управляются сервы может прогуляться в старую статью и освежить знания.

Возьмем, для начала, 8 сервомашинок. На каждую серву идет вот такой сигнал:

На каждую серву со своей ноги контроллера должна идти такая вот последовательность. Итого подобие ШИМ’a на 8 каналов. Как сгенерировать эту бодягу? Да проще простого. Принцип тут простой. Импульсы медленные — всего то 50Гц, меняются тоже нечасто — серва штука инерционная, поэтому даже сто раз в секунду ей не подергаешь. Так что времени на обработку у нас вагон и маленькая тележка.

Сами импульсы будут генерироваться одним таймером, в фоновом режиме. Принцип генерации прост: Все импульсы стартуют одновременно, выставляя свои уровни в 1.
Затем в таймер, в регистр сравнения, заносится время длительности первого импульса. По прерыванию сравнения происходит:

  • Сброс бита на порту первого канала
  • Загрузка в регистр сравнения таймера значения длительности второго импульса

(далее…)

Read More »

Работа с портами ввода-вывода микроконтроллеров на Си++

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

Тут возникают два, на первый взгляд, противоречивых требования:

  • 1)Драйвера внешней периферии хочется писать максимально абстрагировавшись от конкретного способа подключения к микроконтроллеру, а ещё лучше независимо от типа микроконтроллера. Переписывать «библиотечный» код для каждого проекта не очень хорошо.
  • 2)Скорость и размер кода в большинстве случаев имеют большое значение.

(далее…)

Read More »

Организация древовидного меню

Почти для всех проектов на микроконтроллере с экранчиком требуется система меню. Для каких-то проектов одноуровневое, для других — многоуровневое древовидное. Памяти, как обычно, мало, поэтому хочется запихнуть все во флэш.

Попутно, из проекта в проект, развивалась своя псевдоОС — таймеры, события, диспетчеры.
Я ее полностью писал на си, оптимизацией и вылизыванием еще не занимался.

Перебирая разные системы, наткнулся на MicroMenu:

Попробуем разобрать ее на части и прикрутить к системе.
(далее…)

Read More »

Обработка множества инкрементальных энкодеров одновременно

Про инкрементальный энкодер и про обработку его сигналов с помощью МК уже была статья. Вроде-бы ничего сложного — два бита текущего состояния, два бита предыдущего — автомат с 16 состояниями. Рассмотрим эту задачу ещё раз с позиции максимально эффективной (по скорости и размеру кода) обработки сигналов множества энкодеров одновременно.

Обозначим текущее состояние энкодера как «y1» и «y2», а предыдущее, как «x1» и «x2». Всего 4 бита — 16 состояний. Условимся, что направление «Вперёд» у нас будет от первого датчика энкодера ко второму. Запишем все возможные состояния в таблицу.

Таблица 1.
№	y2	y1	x2	x1	Вперёд	Назад	Состояние
------------------------------------------------------------------
0	0	0	0	0	0	0	Стоп	
1	0	0	0	1	0	1	Назад
2	0	0	1	0	1	0	Вперёд
3	0	0	1	1	0	0	Не определено
4	0	1	0	0	1	0	Вперед
5	0	1	0	1	0	0	Стоп
6	0	1	1	0	0	1/0	Назад*	
7	0	1	1	1	0	1	Назад	
8	1	0	0	0	0	1	Назад	
9	1	0	0	1	1/0	0	Вперёд*	
A	1	0	1	0	0	0	Стоп	
B	1	0	1	1	1	0	Вперёд	
C	1	1	0	0	0	0	Не определено	
D	1	1	0	1	1	0	Вперёд	
E	1	1	1	0	0	1	Назад	
F	1	1	1	1	0	0	Стоп

* — строчки 6 и 9 в таблице в принципе означают перемещение назад и вперёд соответственно, в случае если оба датчика энкодера никогда не срабатывают одновременно. Такая ситуация теоретически может иметь место если энкодер это две оптопары и колесо с отверстиями, причем размер отверстия меньше расстояния между оптопарами. На практике это встречается редко, по этому будем иметь этот случай ввиду, но учитывать не будем.
(далее…)

Read More »

AVR. Учебный Курс. Инкрементальный энкодер.

Энкодер это всего лишь цифровой датчик угла поворота, не более того.

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

Если с абсолютным энкодером все просто, то с инкрементальным бывают сложности. Как его обрабатывать?

С Энкодера выходят два сигнала А и В, сдвинутых на 90 градусов по фазе, выглядит это так:

А дальше пляшем от типа энкодера. А они бывают разные. (далее…)

Read More »

Создание Bootloader’a

Введение
На написание данной статьи меня сподвигло практически полное отсутствие какой либо вменяемой информации по теме бутлоадеров на русском языке, и конкретно для чипов основанных на архитектуре AVR.

В общем то DI как то писал о вкусностях этих тулз для пользователей будь то мобила, либо девайс в труднодоступном месте, но процесс работы самого кода подробно не был рассмотрен.

И в один прекрасный день мне на работе дали партийное задание — разработать систему позволяющую дистанционно обновлять прошивку кое-каких устройств, сами железки стоят под взрывозащитными кожухами в шахтах на значительной глубине. Лазить туда и разбирать каждый девайс чтобы воткнуть шлейф ISP понятное дело не самая лучшая идея, однако устройства соединены интерфейсом RS485 это позволяет использовать бутлоадер в проекте.

Конечно можно взять один из OVER чем 9000 готовых бутлоадеров на Сях и доработать напильником, переделать под задачу, но мне давно было интересно разобраться в теме самопрошивки МК. И, думаю, не только мне, поэтому вооружившись даташитом и найдя скудную документацию на утилиту AVRprog я сел за AVR Studio изобетать велосипед — писать свой загрузчик. Естественно на асме (под 8ми битки только на асме пишу).

Так, для разгрева, разработаем проект бутлоадера с прошивкой по RS232 и поддержкой протокола AVRprog v1.4, а дальше можно его заточить хоть под I2C или SPI, RS485 и т. д.
(далее…)

Read More »

AVR. Учебный Курс. Кусочно-линейная аппроксимация

Часто бывает так, что приходится обрабатывать жутко нелинейные величины, задаваемые каким-нибудь извращенным законом. Простейший пример — датчики расстояния SHARP GP2D12. Только поглядите на его характеристику:

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

Вариантов тут, на самом деле, всего два. Первый очень быстрый, но жадный до памяти ПЗУ — табличный.
То есть мы просто берем и эту кривулину расписываем в памяти. Например, у нас с 8ми разрядного АЦП идет значение напряжения от 0 до 256, а мы на каждое значение создаем в памяти значение расстояния. Тогда с АЦП сразу гоним в индекс массива, где эти значения хранятся и получаем расстояние:

L=Curve[ADCH];

Недостаток один — прожорливость до памяти, растущая в геометрической прогрессии с ростом разрядности АЦП.

Вариант второй — написать функцию, переводящую одну величину в другую. (далее…)

Read More »

AVR. Учебный Курс. Использование AVR TWI для работы с шиной IIC (i2c)

Про шину IIC я писал уже неоднократно. Вначале было описание протокола, потом пример работы в лоб, а недавно камрад Ultrin выложил пример работы с i2c на базе блока USI. Да и в интернете полно статей по использованию этой шины в своих целях. Одно плохо — все они какие то однобокие. В подавляющем большинстве случаев используется конфигурация «Контроллер-Master & EEPROM-Slave». Да еще и на программном мастере. И ни разу я не встречал материала, чтобы кто то сделал Контроллер-Slave или описал многомастерную систему, когда несколько контроллеров сидят на шине и решают арбитражем конфликты передачи. Пустоту пора заполнять, решил я и завязал узелок на память… Да только веревочку пролюбил :)

Обещаного три года ждут, вот я таки пересилил лень, выкроил время и сообразил полноценную библиотеку для работы с аппаратным модулем TWI, встроенным во все контроллеры серии MegaAVR. Давно грозился.

Кошмар на крыльях ночи
Во-первых, я сразу же отказался от концепции тупого последовательного кода. Когда у нас есть некоторая функция SendByte(Address,Byte) которая шлет данные по шине, а потом возвращает 1 или 0 в зависимости от успешности или неуспешности операции. Метод прост, дубов, но медленный. Т.е. пока мы байт не пошлем мы не узнаем ушло ли оно, а значит будем вынуждены тупить и ждать. Да, шина i2c может быть очень быстрой. До 100кбит ЕМНИП, но даже это время, а я все же за высокоскоростное выполнение кода, без тормозных выдержек. Наш выбор — диспетчеризация и работа на прерываниях.

Суть в том, что мы подготавливаем данные которые нужно отослать. Дальше запускаем аппаратуру передачи и возвращаемся к своим делам. А зверский конечный автомат, что висит на прерывании TWI передатчика сам передает данные, отвлекая основную программу только тогда, когда нужен какой-либо экшн (например сунуть очередной байт в буфер передачи). Когда же все будет передано, то он генерит событие, которое оповещает головную программу, что мол задание выполнено.
Как? Ну это уже от конкретной реализации событий программы зависит. Может флажок выставить или байт состояния конечного автомата подправить, а может и задачу на конвейер диспетчера набросить или Event в почтовый ящик задачи скинуть. Если юзается RTOS.
(далее…)

Read More »

Использование интерфейса USI в режиме мастера TWI

Возникла необходимость использовать EEPROM совместно с контроллером ATTiny44. Соответственно выбор пал на AT24C64, работающую по интерфейсу I2C (TWI по атмеловской терминологии). Порыл в документации и в инете — с виду вроде все просто, но при реализации алгоритма несколько раз возникали вилы нигде толком не обозначенные, поэтому решил написать статейку.

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

Примечание: для понимания материала статьи желательно представлять работу TWI интерфейса и микросхем serial eeprom. Прочитать об этом можно в статьях DI HALT’a про IIC интерфейс и, например, в статье про часы (где-то еще попадалась статья про работу конкретно с serial eeprom, но не нашел…)
(далее…)

Read More »

Пример виртуальной машины

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

Простой пример для чего это нужно — фрезерный станок с ЧПУ. И надо на нем выточить голову Сократа из цельного куска металла. Задача, на самом деле, не шибко сложная.

Но попробуйте написать прошивку, двигающую резцом, в виде классического конечного автомата — двигающую резцом в зависимости от условий или состояний. Да вы сдохнете раньше чем это сможете сделать.

Другое дело если разбить программу на элементарные операции, вроде «Резец вверх», «резец вниз», «шаг на n мм», а прошивке скормить последовательность этих микроопераций в виде байт-кода или текстового скрипта. Как все серьезно упрощается. Да и попутно можно нашинковать Платона с Гераклом, было бы желание, да образец для копирования.

Т.е. у нас появился свой язык устройства, полностью отвязанный от аппаратной реализации и оперирующий только органами устройства. И вот тут, главное, не впасть в высокоуровневую прелесть и не начать изобретать универсального интерпретируемого языка аля JAVA для микроконтроллеров. В условиях ограниченных ресурсов это полный бред.

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

Ну, хватит воды, приведу пример того, что у меня получилось за вечерок курения в код. Код рабочий, но я там ничего не оптимизировал. Так, накидал чтоб работало, до ума доведете сами. Сделано все на базе ядра диспетчера. Я его уже описывал, поэтому работу его функций пояснять не буду
(далее…)

Read More »