Привет хабр. Я уже давно вынашивал сделать UART Аналогового-Цифрового Преобразователя на ATtiny13, зачем делать именно на ATtiny13 ведь есть, к примеру, ATmega8 имеет аж 6 (для DIP корпуса) портов на которых, при помощи мультиплексора, можно проводить измерение АЦП?
Причин несколько:
— ATtiny13 стоит дешевле;
— В ATtiny13 более оптимально используются ресурсы микроконтроллера;
— Размеры;
— Энергопотребление;
— Просто мне так захотелось.
Конечно на мои аргументы можно найти множество контраргументов, например ATmega8 при использовании V-USB может превратится в плату ввода/вывода которой не нужен переходник с UART на USB, правда кроме последнего, и с этим пожалуй не поспоришь.
Поставил себе за цель получить опыт работы с программный UART'ом именно на ATtiny13, а опыт как говорится, бесценный. По-любому пригодится для будущих проектов.
Ну ладно, не буду тянуть и покажу, как работает в железе:
Пару слов по схеме, кстати, вот она:
Схема в Proteus
Скажу сразу, что не плохо бы уделить внимание фильтру питания, у меня это два конденсатора C1 — желательно «керамика» и как можно ближе к ножкам МК, ну и C2 — электролитический, второй можно поставить на 100 мкФ но у меня такого не оказалось под рукой, нашёл на 470 мкФ 10 В. Так же было бы не плохо по конденсатору на каждый порт АЦП, и как можно ближе к МК. R1 не принципиален, но по правилах «хорошего тона» — должен присутствовать.
Данные, как Вы могли видеть, приходят в формате 1023,666,10, ну хоть бери и сохраняй в формате CSV на компе или же другом устройстве, которое будет принимать эти данные.
Кстати принимает данные в моём случае недорогой преобразователь USB — UART основан на микросхеме PL2303HX. Пробовал питать ATtiny13 от бортовых 3.3 В что на преобразователе, по мультиметру к стати 3.4 В, работает, я поначалу думал что изменение питания на такое высокое значение как-то скажется на отправке данных, я где-то читал страшилку мол, нагрей на пару градусов, охлади и всё, прощай адекватные данные… Ничего подобного, охлаждал льдом, слегка грел зажигалкой(без фанатизма) — всё работает нормально, потерь не наблюдал.
Пару слов про код — код написан в среде BASCOM-AVR на Basic'е, вот предлагаю Вашему вниманию мой код на написание я потратил около чем 4-5 часов, так как я раньше не встречался с Basic'ом, но это время было потрачено не только на написание кода но и на то, чтобы разобраться с особенностями BASCOM-AVR, отладка и всякое такое.
Код
Samples Alias 64 ' Аналог директивы #define на Си
' Количество выборок АЦП
$regfile = "attiny13.dat" ' Конфигурации по умолчанию
$crystal = 1200000
$hwstack = 16
$swstack = 16
$framesize = 16
'$noramclear
Open "comb.0:9600,8,n,1" For Output As #1 ' Настройка программного UART, скорость 9600 бод
' Ножка PB0 будет как TXD, подключаем к RXD преобразователя
Config Adc = Single , Prescaler = Auto , Reference = Avcc 'Конфигурирование АЦП, измерение относительно Vcc
Start Adc ' Запускаем преобразование
' Здесь Adc - режим считывания значения: Single - единичное считывание,
' также может быть Free (режим постоянной работы преобразователя)
' Prescaler = 128 - выбираем частоту дискретизации путем деления
' частоты кварца на определенное число (также может быть 2,4,8,16,32,64 или Auto).
' Если выбрать Auto, то компилятор сам выберет подходящую частоту работы АЦП
' Reference – выбор источника опорного напряжения. Aref – внешний источник,
' Avcc – напряжение питания схемы, Internal – внутренний ИОН на 1,1 в.
Declare Function Adc_get(byval Adc_port As Byte) As Word ' Объявим переменную которая принимает номер нужного порта АЦП
' И возвращает усреднённое от "Samples" количество выборок АЦП
Do ' Тут начинается вечный цикл
Print #1 , Adc_get(1) ; "," ; Adc_get(2) ; "," ; Adc_get(3) ' Выводим данные в формате *,*,*
Loop ' Тут кончается
Function Adc_get(byval Adc_port As Byte ) As Word ' Переменная типа Word может принимать знач. до 65535
Dim Temp_result As Word ' Создадим переменную для буфера
Dim Adc_cycles As Byte ' И счётчик выборок АЦП
Temp_result = 0
For Adc_cycles = 1 To Samples
Temp_result = Temp_result + Getadc(adc_port)
Next
Temp_result = Temp_result / Samples
Adc_get = Temp_result ' Эта функция возвращает Temp_result
End Function
Что делает данные код — по началу создаётся программный UART, тут это делается очень просто, задаём нужные параметры, порт, скорость и прочее, потом осуществляется конфигурация АЦП, объявление функции, ну это понятно, потом формируется строчка и результатами усреднённого числа от Samples выборок АЦП. Почему я выбрал именно 64 а не к примеру 42 или 108? Ну потому что 1023 * 64 это равно 65 472, а для типа Word, который я использовал для буфера максимальное значение которое переменная может принять — 65 535, это число является наибольшим числом, представимом в виде двухбайтного слова без знака, если добавить ещё одну выборку переменная попросту обнулится если АЦП возвратит 1023. С типом Long почему-то возникали проблемы, да лично мне и 64 выборки хватает, ниже я покажу как это работает на графике. Ну и потом в UART выводятся результаты.
Как Вы можете видеть шум конечно присутствует, даже не смотря на то что выводится усреднённое значение из 64 выборок, судя по даташиту шум в ± 2 LSB — норма, у меня же шум 1 LSB.
Скрин софта
Как Вы можете видеть, ATtiny13 отправляет значения 15-16 раз за секунду, что я считаю не плохо учитывая что это программный UART да и тиня делает по 64 измерения на порт, а их причём три.
МК потребляет следующий ток:
Питание 5 В — 2.71 мА
Питание 3.3 В 1.75 мА
Пару слов о программированию — как я сказал на видео, частота МК 1.2 МГц, все фьюзы по умолчанию, как в моём предыдущем топике Музыкальный дверной звонок в стиле Star Wars.
Вот фьюзы из калькулятора фьюзов:
Фьюзы
Ну и под конец пару фоток из разных ракурсов:
Небольшая фотосессия
Ссылки:
Альтернатива Wiring для Arduino — BASCOM-AVR
Софт которым делал графики — Serial oscilloscope
Архив с исходником, хекс-файлом и схемой в Proteus 7 Professional
Все мои публикации.