Обычно, для перехода от идеи к реализации, необходим прототип устройства, удобный для проверки и отладки на месте, что особенно важно для мобильного устройства. Далее постараюсь максимально подробно разобрать процесс создания прототипа беспроводного сенсора на базе ATtiny85. Цель — создать сенсор работающий, условно говоря, в коробке с искусственным освещением и передающий температуру и статус освещения с немедленной реакцией на изменение освещения: включилось, отключилось, мигнуло. Сенсор решено было сделать мобильным и питать от элемента CR2032, иначе говоря, при разряде до 2.7V (предел для датчика TMP36), можно рассчитывать на 200mAh. Микроконтроллер ATtiny85 имеет всего 5 портов ввода/вывода и возможность отключить RESET в пользу дополнительного порта. Данный бюджет был распределён следующим образом: Элементная база определена, можно приступать к проектированию. Ситуация требует использовать RESET в качестве порта ввода/вывода. Однако RESET необходим для программирования микроконтроллера, в том числе и для прошивки настроек (Fuses). Соответственно, после отключения RESET программировать устройство будет не возможно. Таким образом, чтобы не получить «кирпич» первым делом необходимо раздобыть высоковольтный (12V) программатор, для сброса Fuse-ов. Подходящую схему и скетч для Arduino можно найти по ссылке ATTiny Fuse Reset with 12 Volt Charge Pump. Данная схема не требует дополнительного питания, и для получения 12V используется умножитель (Charge Pump). Схема находится на сайте по ссылке, расположенной выше. На вывод (4) подается питание 5V, при этом на выводе (2) устанавливается низкий уровень (земля), конденсатор C1 заряжается до 5V. Затем на (2) подается 5V и на обкладках С1 образуются 10V, они через диод D2, при низком уровне на (3), попадают на C2. Затем уровни на (3) и (2) меняются местами и уже 15V поступают на C3, следующая итерация сливает 20V (на самом деле ~17V) на C4. Затем напряжение через делитель R2/R3 попадает на аналоговый вход A0, где сравнивается с опорным значением, и если напряжение выше 12V, то раскачка (смена уровней на (2) и (3)) выключается. Транзистор Q1 нужен для быстрой разрядки конденсаторов и формирования необходимого импульса для программатора. Резисторы на выводах ATtiny85 необходимы для защиты микроконтроллера при неправильном подключении. У меня получился следующий дизайн:    Неудобно, что USB разъём накрывает контактные пины, но дизайн платы таков, что здесь к микроконтроллеру сложно даже штатное питание подвести. Проще говоря, было место на плате, появилась идея добавить пины для подключения обычного программатора в следующей конфигурации:  Позже стало очевидно, что использовать схему в таком виде целесообразно только в самом крайнем случае. Разработка схемы вместе с макетной платой будет производится в KiCad EDA, это свободный пакет для автоматизации разработки электронных схем. Исходные файлы KiCad проекта размещены на GitHub, в папке attwlight_sensor.pcb. Существует множество хороших инструкций по работе с данным редактором, например стоит посмотреть ролик на YouTube KiCAD Quick-Start Tutorial. Если совсем кратко, то для начала работы над схемой в KiCad достаточно запустить редактор схемы  и справа пройтись по иконкам, чтобы добавить: элементы , питание , провода  и метки . Метки нужны, чтобы не загромождать схему проводами. При разводке печатной платы все одинаковые метки необходимо будет соединить дорожками. Если в доступных библиотеках нет необходимого элемента его можно создать с нуля либо изменить один из существующих. В последнем случае достаточно поставить курсор на нужный элемент и нажать Ctrl+E (редактировать элемент в редакторе) и в новом окне: создать элемент из текущего , отредактировать его внешний вид и свойства , затем сохранить в новую библиотеку . Чтобы созданную библиотеку можно было использовать, её необходимо подключить в Preferences → Component Libraries, воспользовавшись кнопкой Add в верхней части. Для добавления в библиотеку других элементов, её нужно выбрать  и после добавления сохранить . Итоговая схема:  По сути, устройство состоит из трех независимых частей. Проверив их по отдельности вполне можно ожидать, что в сборе всё заработает как было задумано. Прототип как раз и нужен, чтобы проверить насколько данное ожидание соответствует действительности. Ниже, в комментариях к схеме, я остановлюсь на том, что пошло не так. В рабочем режиме питание на датчик подается с порта PB5 микроконтроллера. В отладочной конфигурации подать питание на датчик можно установив перемычку между выводами VCC и D10 контактной площадки P2. Сигнал RESET активен при низком уровне и высокий уровень не мешает работе микроконтроллера и даже увеличивает стабильность по сравнению с висящим в воздухе RESET. Для съема данных с датчика используется аналоговый порт ADC2. Засада ждала в виде ёмкости C1, которая была подключена непосредственно к RESET микроконтроллера. Понятно, что емкость на RESET снижает время активности сигнала или даже блокирует его, мешая программированию устройства, поэтому до сборки был проведен эксперимент, но как оказалось не достаточно чистый. Дело в том, что если на работающую схему добавить данный конденсатор, то процесс проходит успешно ровно один раз, если включить схему с ним — то не разу. Пока дело дошло до конденсатора, была впаяна перемычка между D1 и SCK, очевидно, что эта часть схемы не мешает установке на SCK низкого уровня, но подозреваемых больше не было. После установки перемычки между C1 и землей, программировать устройство стало можно, но только с питанием 5V. Однако в инструкции указано 1.8-5.5V и эксперименты с этим микроконтроллером и питанием 3V были успешными. Оказалось что на питании TMP36 есть встроенная ёмкость 10nF и этого достаточно, чтобы блокировать процесс при низком напряжении. В результате перемычка встала на своё место. Нумерация выводов у штыревых разъёмов в KiCad не соответствует принятой для данного модуля, поэтому нумерация здесь зеркальная относительно указанной в инструкции для NRF24L01+. Для работы радиомодуля в 3х пиновой конфигурации необходимо поменять местами выводы MISO и MOSI, и добавить часть схемы справа, состоящую из элементов: R3, D1 и C2. Схема данной конфигураци взята отсюда nRF24L01+ with ATtiny85 3 Pins. Работа данной схема возможна по тому, что на CE (chip enable) можно сразу установить высокий уровень, а CSN (chip select) нужен только для передачи модулю сигнала о начале новой команды, что достигается сбросом высокого уровня в низкий. Соответственно, CSN можно объединить с одним из оставшихся выводов, в данном случае SCK (clock). Штатные импульсы SCK не успевают зарядить конденсатор C2 и на CSN остается низкий уровень, перед началом передачи команды нужно установить на SCK высокий уровень на более длительное время, чтобы получить высокий уровень на CSN. С чем связанна необходимость поменять местами MISO и MOSI я не понял, видимо так было удобно. Для стабильной работы модуля желательно наличие ёмкости 1-10μF на выводах питания модуля, для этих целей на схеме предусмотрен конденсатор C4. После устранения проблем с датчиком температуры, первым делом была проверена возможность прошить ATtiny85 с установленным радиомодулем. Процесс не пошёл, avrdude ругнулся на не верную сигнатуру, но я проявил упорство и запустил прошивку… и в итоге тоже ошибка. В результате эксперимента радиомодуль не пострадал, правда и шансов что-то в него прошить не было из-за модификаций приведенных выше. А вот микроконтроллер пришлось реанимировать с помощью высоковольтного программатора. Идея оказалась неудачной, но попробовать стоило. В процессе тестирования микроконтроллер успешно работал от внутреннего осциллятора без делителя на частоте 8MHz, однако с непосредственно подключенным радиомодулем его работа стала не стабильной. В том смысле, что если соединить радиомодуль с разъёмом проводами длиной 30cm, всё работает нормально, а с модулем, установленным в разъем, что-либо отправить невозможно. Все попытки стабилизировать систему дополнительными конденсаторами, ровно как и сделать её нестабильной, разместив вынесенный радиомодуль вплотную к микроконтроллеру, ни к чему не привели. В результате пришлось включить делитель, что вернуло микроконтроллер к заводским настройкам. Работа ATtiny85 на частоте 1MHz каких либо сложностей не вызвала, но заметно сократила ожидаемое время работы от батареи. Подробнее об этом в конце статьи. С этим датчиком всё относительно просто, на него попадает только искусственное освещение, а регистрировать он должен только моменты его включения и отключения. Для максимально быстрой реакции на событие датчик генерирует прерывание на порту PCINT3 (Pin Change Interrupt). Элементы R1 и C3 подстроечные, для них предусмотрено место на плате, но они не распаяны. С3 параллельно с фототранзистором Q1 может понадобиться, чтобы исключить дребезг сигнала. Проблема в том, что стандартный для таких случаев конденсатор 0.1μF, разряжается через резистор 10MΩ около секунды, что не приемлемо для регистрации события — свет мигнул. Соответственно, можно установить конденсатор меньшей ёмкости и/или уменьшить сопротивление резистора R2, но сначала нужно проверить, есть ли в этом смысл. Поскольку здесь используется прерывание может показаться, что в схеме нужен компаратор, но эти мысли сразу отпадают, как только становится понятно сколько эта штука потребляет. Правда и потребление микроконтроллера, при уровне сигнала вблизи центра рабочего диапазона, подскакивает с 7μA примерно до 260μA в режиме сна. Однако данную проблему проще решить программно, а именно, после срабатывания прерывания (PCINT3 или WDT), можно проверить напряжение на аналоговом входе ADC3, если оно неприемлемо, сообщить о проблеме и пропустить активацию PCINT3. В любом случае это нештатная ситуация, которая требует внимания. Готовую схему необходимо развести на плате. Это также можно сделать в KiCad. Для этого сначала требуется завершить работу со схемой: Редактор схемы можно закрыть и перейти к редактору печатной платы . Здесь нажать , затем загрузить ранее созданный netlist (Read Current Netlist), убедиться, что не было ошибок и закрыть окно. Если схема была изменена или элементам были назначены другие посадочные места, необходимо обновить netlist и загрузить его здесь снова. При первой загрузке netlist все посадочные места окажутся стопкой в одной куче. Сначала необходимо переключить сетку на 1/10" (2.54mm), растащить элементы (используя кнопку m), убрать лишние надписи Visibles → Render → Values и, пользуясь подсказками редактора, соединить элементы дорожками. Результат будет выглядеть примерно так:  Оставшиеся белые линии, указывают какие посадочные места необходимо соединить проводами. К сожалению в KiCad нет способа вывести результат, так чтобы его было удобно воспроизвести на макетной плате. Но в данном случае макетная плата получилась не большой, и с ней можно поступить просто: отключить лишние надписи Visibles → Render → Footprints Front, снять скриншот и зеркально отразить его по вертикали.  Готовый макет:  Тут два несоответствия со схемой выше: не распаяны подстроечные элементы R1,C3 и диод короче на одно отверстие.  Плата немного побита жёсткой отладкой, но на то она и макетная. Большинство других вариантов, после всех модификаций, выглядело бы хуже. Arduino IDE наиболее доступное кроссплатформенное программное обеспечение для программирования AVR микроконтроллеров и вполне удобное для небольших проектов. Не смотря на то, что Arduino IDE официально не поддерживает ATtiny85, существует штатный способ добавить данный микроконтроллер в список поддерживаемых. Как это сделать, подробно описано по ссылке Programming an ATtiny w/ Arduino 1.6. Однако данный способ годится только для непосредственного программирования ATtiny85 и не позволяет использовать Arduino код. С одной стороны это хорошо, код чище будет, но задача в данном случае — разработать скетч демонстрирующий способность устройства функционировать как было задумано, и такая оптимизация здесь преждевременна. Значит нужно Arduino ядро для ATtiny85, его можно взять здесь arduino-tiny, версия для Arduino 1.5 подойдет. Доступны будут не все функции, но базовый набор, включая программный последовательный порт, для отладки, можно будет использовать. К сожалению в актуальной, на данный момент, Arduino IDE v1.6.6 что-то сломали, и c этим ядром необходимо использовать версию 1.6.5. Осталось приготовить программатор. Для этого совсем не обязательно использовать специальное устройство, можно в ближайшую Arduino прошить скетч из File → Examples → ArduinoISP, затем соединить с сенсором, как указанно на принципиальной схеме, и не забыть про конденсатор 10μF, который необходимо установить между RST и GND выводами Arduino.  Программировать устройство нужно без установленных радиомодуля и перемычек. В меню Tools → Board нужно выбрать конфигурацию микроконтроллера, в данном случае: ATtiny85 @ 1 MHz (internal oscillator; BOD disabled), в меню Tools → Port выбрать USB порт программатора и в меню Tools → Programmer указать тип программатора, в данном случае: Arduino as ISP, затем воспользоваться кнопкой Upload. Тестовый скетч для работы с сенсором получился довольно интересным, в нем можно найти широкий набор примеров, а именно:
 Чтобы скомпилировать скетч необходимы сторонние библиотеки: Это оптимизированные версии библиотек для работы с радиомодулем NRF24L01+, которые подходят для микроконтроллера ATtiny85. Их необходимо скачать и распаковать в папку libraries в директории со скетчами Arduino. Ниже будут приведены наиболее интересные куски кода с подробными комментариями. Полностью скетч можно найти на GitHub в папке attwlight_sensor, также в папке attwlight_rx находится скетч для приёмника. Функция void sleep() вызывается в главном цикле void loop() и останавливает его до тех пор пока не сработает одно из прерываний PCINIT3 либо WDT. Затем выполняется полезная работа и снова вызывается данная функция. Функция содержит обращения к регистрам микроконтроллера, и что при этом происходит не всегда очевидно. Чтобы с этим разобраться нужно заглянуть в документацию на микроконтроллер ATtiny85 datasheet раздел «23. Register Summary», в нем приведен полный список регистров с прямой ссылкой на страницу с подробным описанием для чего предназначен тот или иной бит. Особенности работы с данным датчиком уже были разобраны в разделе «Принципиальная схема». Отмечу только, что параметры здесь выбраны так, чтобы потребление микроконтроллера в режиме сна не превышало 20μA. Если не использовать вывод AREF микроконтроллера, который предназначен для задания опорного напряжения, все измерения на аналоговом порту будут привязаны к напряжению питания. Батарея не стабилизированный источник, следовательно для корректного считывания показаний датчика температуры, необходим способ измерять напряжение питания в процессе работы. Напряжение питания также является хорошим индикатором состояния батареи. Ниже приведен код, который позволяет произвести требуемые измерения полагаясь на стабильность внутреннего опорного напряжения Vbg (Bandgap reference voltage) равного 1.1V. Согласно спецификации Vbg может находится в пределах 1.0-1.2V, поэтому необходимо убедиться в точности измерений и при необходимости скорректировать константу 1125300. Получив напряжение питания, легко вычислить точное напряжение на аналоговом входе микроконтроллера и перевести его в температуру. Остальная часть скетча нужна, чтобы собрать данные вместе и отправить их наиболее оптимальным образом, с точки зрения энергопотребления. Ничего интересного там нет, обычная логика, надеюсь, комментариев в коде достаточно, чтобы разобраться как всё работает. Если скомпилировать данный код, можно увидеть, что он свободно умещается в 8KiB и даже есть куда развернуться: Осталось проверить, что всё работает как было задумано, и можно прошивать Fuses переключающие RESET в порт ввода/вывода. Готовой конфигурации в Arduino IDE для этого нет, поэтому нужно воспользоваться командной строкой: Что из себя представляют данные Fuses, можно посмотреть в калькуляторе Engbedded Atmel AVR® Fuse Calculator. Если кратко, то эти настройки предписывают: использовать встроенный осциллятор с делителем частоты на 8 (итоговая частота 1MHz); использовать стандартные задержки при старте, необходимые для стабилизации осциллятора; отключить BOD (Brown-out Detector) — перезагрузка при низком напряжении питания для защиты памяти от записи мусора; включить возможность считывать прошивку; и собственно отключить RESET.  Пришло время измерить энергопотребление получившегося устройства. Вводные следующие: данные передается каждые 120sec, если пришло прерывание от датчика освещения, то немедленно; событиями от датчика освещения можно пренебречь; ёмкость батареи 200mAh. Как видно, тут было ради чего бороться. К сожалению, стабильности на 8MHz добиться не удалось. Видимо без внешнего осциллятора, это не реально. Все исходные коды проекта доступны на GitHub Инженер-программист компьютерных систем и сетей