SportIduino и активный чип. Часть 3. Мы в город Изумрудный идем дорогой трудной…

В первых двух частях (часть 1 и часть 2) я рассказывал про идею создания активного чипа и выбор платформы. Здесь продолжу свой рассказ по работе над прототипом активного чипа.

После того, как я решил использовать для активного чипа микроконтроллер ATTINY1614, я начал искать способы, как облегчить себе написание прошивки. Сначала собирался использовать среду разработки Arduino, но наткнулся в интернете на ресурс ATMEL START, где можно было интерактивно создать свой проект (выбрать микроконтроллер AVR) и затем для выбранного проекта выбрать необходимые компоненты, как аппаратные, так и программные (см.рис.1).

Рис.1
Выбор компонентов в ATMEL START

Этот подход очень напоминает приложение STM32 CubeMX для микроконтроллеров STM32 (об этом я рассказывал во 2-й части). И здесь также есть отдельная вкладка для настройки тактирования выбранной периферии (см.рис.2):

Рис.2
Настройка системы тактирования в ATMEL START

Она, конечно, выглядит попроще, чем для STM32, но для микроконтроллеров с ограниченным объемом памяти это скорее плюс, чем минус, так как программный код инициализации выбранной периферии и системы тактирования получается гораздо компактнее.

Также на отдельной вкладке можно сконфигурировать пины микроконтроллера (см.рис.3):

Рис.3
Конфигурация пинов в ATMEL START

Поскольку в выбранном микроконтроллере 14 выводов (пинов), из которых 11 можно смело использовать в своем проекте, то я решил использовать не обычный одноцветный светодиод, а 3-х цветный RGB-светодиод. На рис.3 он подключен к пинам с обозначениями LED_R_PIN, LED_G_PIN и LED_B_PIN.

Затем с ATMEL START свой проект можно выгрузить (экспортировать) как в ATMEL STUDIO, так и в MPLAB X IDE. Это бесплатные среды разработки. Я с ними никогда раньше не работал, но установил себе обе и затем остановился на MPLAB X IDE. Как-то больше она мне пришлась по душе. На моем (далеко не новом) домашнем компе ATMEL STUDIO 7 прилично тормозила, к тому же фирма Microchip, которая продвигает свою среду разработки MPLAB, несколько лет назад купила ATMEL и теперь и в ее среде MPLAB X IDE можно писать программный код на C как для PIC-контроллеров (которые производит сама Microchip), так и для AVR (права на которые перешли к ней после покупки Atmel).

Когда я загрузил в MPLAB X IDE проект, созданный на ресурсе ATMEL START, то я увидел кучу файлов (см.рис.4), а не один файл со скетчем, как в Arduino:

Рис.4
Скомпилированный проект, загруженный с ресурса ATMEL START

Первым делом я его откомпилировал, чтобы оценить размер программного кода инициализации выбранных компонентов. Результат меня приятно удивил: 5% программной памяти! Сравните это с 53% для STM32 (и это для низкоуровневых LL-библиотек)!

Ну и еще приятный бонус – хотя в проекте изначально включено много файлов, они все располагаются в папке проекта (на диске), а не разбросаны по разным папкам (как в Arduino с библиотеками, где часть библиотек подключается из своих папок, а часть берется из папок с платформой AVR). Можно просто сохранить папку проекта и не беспокоиться, что через несколько лет, когда выйдет несколько новых версий среды разработки, этот проект не будет компилироваться без ошибок.

Ну и много других приятных фишек в этой среде разработке. Например, быстрый переход к определению функции или переменной. Есть и минусы – проект был импортирован как чистый C (без классов), а не C++ (с классами, как в Arduino). Возможно, в настройках проекта или самой среды можно было перевести проект и на C++, но меня это не сильно напрягало, и я решил свое время потратить на создание прошивки активного чипа.

Когда я в написании прошивки дошел до стадии, когда уже надо было тестировать RFID-часть (подносить микросхему NFC к RFID-считывателю), то начались первые проблемы. Я долго не мог добиться, чтобы мой RFID-считыватель увидел микросхему NFC. Я использовал свой смартфон с включенным на нем NFC-модулем и приложением NFC Tools. Не хотел никак мой смартфон видеть NFC микросхему NT3H2311 с подключенной к ней антенной, и все!

Для расчета параметров антенны я использовал приложение Coil64. Поскольку у меня нет прибора, умеющего измерять индуктивность, то параметры колебательного контура (индуктивность и емкость) для резонансной частоты 13.56 МГц я брал из этого приложения. Емкость 50 пф известна из даташита – эта входная емкость на выводах микросхемы NFC, к которым подключается антенна. И для этой емкости следует подобрать индуктивность. Я же рассчитывал индуктивность для емкости 85 пф – чтобы можно было параллельно подключать конденсатор(ы) для более точного подбора резонансной частоты. Приложение мне рассчитало (по известной резонансной частоте и емкости) индуктивность 1.59 микроГенри. Нашел у себя в гараже катушку эмалированного медного провода диаметром примерно 0.46мм, для каркаса антенны взял пробку с пэт-бутылки, и вот такие данные для индуктивности (антенны) в 1.59 мкГн выдала программа Coil64 (см.рис.5):

Рис.5
Параметры индуктивности (антенны) 1.59мкГн, рассчитанные в Coil64

Намотал 5 витков провода на пробку от пэт-бутылки, припаял параллельно конденсаторы на 35 пф – не видит мой смартфон эту микросхему! Я менял параллельные емкости в диапазоне от 0 до 120 пф – эффект нулевой!

Начал уже сомневаться в этом приложении. В даташите на микросхему NFC в разделе 17 «Ссылки» нашел ссылку на чудесный документ «AN11276 NTAG Antenna Design Guide». В нем вначале подробно излагается теория расчета антенн (с многоэтажными формулами), а затем идут примеры плат для разных микросхем. И там я нашел для своей микросхемы NT3H2311 схему и рисунок антенны на печатной плате (см.рис.6):

Рис.6
Пример схемы и печатной платы для NT3H2311 из AN11276

Печатную плату я делать не собирался, но взял лист пластмассы и по размерам антенны,  как на рисунке, разложил 3 витка медной проволоки (найденной у себя в гараже) и горячим паяльником вплавил эту проволоку в пластмассу. Для фиксации обмотал все это еще скотчем. То, что размеры антенны там указаны далеко не миниатюрные, волновало меня меньше всего. В тот момент я хотел только одного – чтобы мой смартфон увидел микросхему NT3H2311.

Но чуда не произошло. Мой смартфон и с этой антенной отказывался видеть NFC микросхему. Я был уже на грани психа. Но успокоился и зашел с другой стороны. Так как я заказывал не одну микросхему NFC, а сразу 4, то решил заменить микросхему NFC в прототипе активного чипа. Когда я ее заменил, то мой смартфон сразу же определил NFC микросхему! С первого раза! Прибора для измерения индуктивности у меня нет, но есть тестер, способный измерять емкость. Я измерил емкость между выводами, к которым подключалась антенна, у выпаянной микросхемы NFC. Прибор показывал 0. А на других микросхемах показывал емкость  около 120 пф. Это не 50 пф как по даташиту (но тут уже может врать мой китайский тестер), но и не 0!

Теперь можно было работать над прошивкой дальше. Я начал обрабатывать прерывания, возникающие при изменении уровня на пине FD микросхемы NFC. Решил алгоритм сделать таким:

    • Первоначально (после сброса) микроконтроллер ATTINY1614 по шине I2C считывает все содержимое EEPROM микросхемы NFC, пытаясь определить текущее состояние EEPROM (из следующих возможных состояний):
      1. NFC_EEPROM_DEFAULT — дефолтное состояние EEPROM, страницы заполнены байтами 0x00;
      2. NFC_EEPROM_SPORTIDUINO — EEPROM отформатирована под SportIduino. Это значит, что заполнены как надо  как минимум страницы 4 и 5, а страницы для отметки (не считая отметки стартовой станции), если заполнены, то должны быть заполнены строго последовательно, начиная со страницы 9;
      3. NFC_EEPROM_UNFORMAT — EEPROM непустая, но ее формат не соответствует формату SportIduino (см.выше).

и затем по текущему состоянию EEPROM  пытается определить текущий режим активного чипа (из следующих возможных режимов):

      1. MODE_WAIT_FORMAT_FOR_SPORTIDUINO — режим ожидания, пока EEPROM чипа NFC не будет отформатирована как NFC_EEPROM_SPORTIDUINO. Применяется для состояний EEPROM «NFC_EEPROM_DEFAULT» или «NFC_EEPROM_UNFORMAT»;
      2. MODE_EMULATION_AC — режим эмуляции активного чипа, когда состояние EEPROM равно «NFC_EEPROM_SPORTIDUINO» и тип чипа (значение байта 3 страницы 4 EEPROM) равен NTAG216 (значение 0x06). Станции SportIduino определяют это значение как пассивную метку NTAG216 и пишут в этот чип как в метку NTAG216. При этом не надо ничего менять в прошивке станций SportIduino, но никакого выигрыша во времени отметки это не дает;
      3. MODE_NATIVE_AC_START и MODE_NATIVE_AC_STOP – режим «истинного» активного чипа, когда состояние EEPROM равно «NFC_EEPROM_SPORTIDUINO» и тип чипа (значение байта 3 страницы 4 EEPROM) равен новому значению (например, 0x16). При этом надо менять алгоритм в прошивке станций SportIduino (чтобы они умели работать с новым значением типа чипа), например, как это я описал в части 1, и это должно дать выигрыш во времени отметки/очистки.
    • после того, как уровень на пине FD меняется с 0 на 1 (по умолчанию это происходит, когда NFC микросхема выходит из зоны действия поля RFID-считывателя), микроконтроллер ATTINY1614, если он находится в режиме «MODE_WAIT_FORMAT_FOR_SPORTIDUINO» или «MODE_EMULATION_AC», опять считывает по шине I2C все содержимое EEPROM микросхемы NFC и сравнивает текущее состояние/режим с предыдущим. И по результатам сравнения пытается определить, что же изменилось в чипе. Например, добавилась новая отметка (на стартовой, базовой или финишной станции) или чип был очищен на станции очистки или чипу был присвоен новый номер (в программе SportOrg). И в зависимости от обнаруженных изменений микроконтроллер включает индикацию на RGB-светодиоде. Зеленым светом – для подтверждения отметки, синим цветом – для сервисных режимов (очистка/смена чипа), красным цветом – индикатор низкого напряжения батарейки активного чипа.

При этом я пока не собирался детально прорабатывать режимы «MODE_NATIVE_AC_START» и «MODE_NATIVE_AC_STOP», я их просто обозначил. Потому, что для этого надо еще менять прошивку станций SportIduino, которых у меня нет. Я целиком сосредоточился на реализации режима «MODE_EMULATION_AC».

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

Все шло неплохо, постепенно я доделывал анализ содержимого EEPROM после каждого прерывания уровня пина FD, как вдруг в один прекрасный момент мой прототип активного чипа перестал работать. Микроконтроллер ATTINY1614 работал как часы, но только при считывании данных по шине I2C из микросхемы NFC моя программа стала работать совсем не так, как раньше. Некорректность была в том, что теперь, анализируя содержимое EEPROM микросхемы NFC после каждого прерывания, моя программа всегда определяла состояние как «NFC_EEPROM_UNFORMAT». При этом я никак не изменял содержимое EEPROM микросхемы NFC, что подтверждалось чтением EEPROM моим смартфоном.

Добавляя вывод отладочных сообщений в разные участки программного кода, я определил причину. Оказалось, что теперь по шине I2C считывались некорректные данные! Напомню, что микросхема NFC содержимое своей EEPROM по шине I2C передает блоками по 16 байт (сразу 4 страницы по 4 байта, тогда как микросхема NFC по RFID всегда обменивается страницами по 4 байта). И теперь при чтении блока по шине I2C неожиданно произошли изменения! Первым байтом микросхема NFC теперь почему-то стала возвращать номер считываемого блока, 2-й байт теперь всегда читался как 0x00, а затем, начиная с 3-го байта, шли первые 14 байт содержимого блока EEPROM. Последние 2 байта блока при этом терялись… Я сначала стал грешить на ATTINY1614 и поменял в прототипе активного чипа эту микросхему. Однако это ничего не дало и тогда я заменил уже 2-ю микросхему NFC (впаяв уже 3-ю из 4-х микросхему NFC).

После этого прототип активного чипа заработал как мне надо (по моей программе). Но не долго… Он проработал буквально пару часов, после чего стал виснуть при любом обращении микроконтроллера к микросхеме NFC по шине I2C. Только сброс по вотчдогу выводил его из этого зависания, на затем после сброса, когда моя программа пыталась прочитать содержимое EEPROM микросхемы NFC, жестоко зависал по-новой. Пришлось опять доставать паяльник и снова менять микросхему NFC (4-ю из 4-х).

Однако с этой (последней) микросхемой NFC прототип активного чипа отказался работать сразу. Я смартфоном читаю EEPROM этой микросхемы без проблем, а вот моя программа, работающая по прерываниям уровня сигнала на пине FD микросхемы NFC, никак не реагировала, когда я считывал смартфоном (который генерировал RFID-поле). Как оказалось, у этого экземпляра микросхемы NFC пин FD никогда не подтягивался к 0.

Какие-то очень капризные оказались микросхемы NFC. Я не претендую на роль безупречного монтажника, но микросхем за свою жизнь я запаял достаточно. И такой процент брака встречал только в конце 80-х годов прошлого века, когда работал на заводе «Счётмаш» и сталкивался там с армянскими и грузинскими микросхемами. Для регулировщиков эмблемы на этих микросхемах были как красная тряпка для быка, когда они пытались заставить работать плату с такими микросхемами. Они их сразу все маркировали крестами и отдавали монтажницам на замену. На заводе даже вынуждены были сделать цех входного контроля, чтобы выявлять брак еще на приемке. Но это мало помогало. Но это так, лирическое отступление, как говорится, накатили воспоминания моей молодости. Я тем же паяльником запаял в прототип активного чипа еще и 2 микросхемы ATTINY1614 (одну я поменял, думая, что это она искажает данные при чтении по шине I2C, хотя это предположение потом не подтвердилось) и они работают как часы. А вот про NT3H2311 такого не скажешь…

В общем, легкой жизни никто и не обещал. Заказал я еще партию этих капризных микросхем. Срок доставки 3-6 недель. Пока они едут, я решил использовать на последней микросхеме NFC пин PwrOut вместо неработающего пина FD, чтобы можно было продолжать разрабатывать программу.

Для этого слегка модифицировал программу. На пине PwrOut микросхемой NFC формируется выходной сигнал во время нахождения антенны в электромагнитном поле RFID-считывателя и предназначен он для подачи питания на внешние микромощные устройства (потребляемый ток которых должен составлять доли миллиампера). Это аналоговый сигнал, у которого нет выраженного четкого фронта, как на пине FD. Поэтому я не стал его обрабатывать в обработчике изменения уровня пина FD, а добавил анализ уровня пина PwrOut в обработчике прерывания таймера D, которое в неспящем режим происходит каждую миллисекунду. Добавил программный счетчик для определения устойчивого уровня этого пина (считаю уровень устойчивым, если он остается неизменным 10 раз подряд, то есть 10 миллисекунд). И при обнаружении нового устойчивого уровня помещаю событие в очередь событий, как в обработчике прерывания уровня пина FD. Пришлось отключить перевод микроконтроллера в спящий режим (таймер D в спящем режиме я отключаю).

В итоге добился корректной работы программы в режиме «MODE_EMULATION_AC» (эмуляция активного чипа). На анализ содержимого EEPROM микросхемы NFC (после обнаружения нового события в очереди событий) уходит 63 миллисекунды плюс 10 миллисекунд на ожидание стабильного уровня пина PwrOut. Считаю эту задержку вполне приемлемой.  На текущий момент программа занимает 55% flash-памяти микроконтроллера ATTINY1614 (см.рис.7):

Рис.7
Фрагмент основного цикла программы

И это при том, что сейчас в программе значительную часть занимает вывод отладочных сообщений. Если закомментировать макроопределение USE_DBG_MSG и перекомпилировать программу, то она займёт уже 37% flash-памяти. Считаю, что это вполне приемлемо и еще остается достаточно свободного места для реализации полноценных режимов активного чипа «MODE_NATIVE_AC_START» и «MODE_NATIVE_AC_STOP», требующих изменения прошивки станций SportIduino. Но для этого требуется свободное время и наличие хотя бы нескольких базовых и мастер-станций SportIduino для экспериментов. А с этим у меня сейчас напряженка…

Cнял видео, демонстрирующее работу прототипа активного чипа с прототипом станции SportIduino.

ПОСЛЕСЛОВИЕ

В процессе работы с микросхемой NFC мне пришла в голову другая мысль, как еще можно использовать эту микросхему (NT3H2311) в SportIduino. У этой микросхемы есть еще интересный режим «SRAM MIRROR», позволяющий SRAM (64 байта или 16 страниц) «зеркалировать» на любые страницы EEPROM микросхемы. И в этом случае RFID-считыватель, обращаясь к таким страницам EEPROM, на самом деле обменивается данными с SRAM. Считыватель об этом ничего не подозревает (только время записи в такую страницу резко сокращается, ведь не требуется программировать EEPROM), а микросхема NFC в этом случае не сохраняет данные из SRAM в EEPROM (об этом, если надо, должен позаботиться микроконтроллер по шине I2C). Понятно, что этот режим возможен только когда на микросхему NFC подается внешнее питание. На мастер-станции не должно быть проблем с внешним питанием. Если доработать мастер-станцию SportIduino, добавив рядом с ней дополнительную плату с микросхемой NT3H2311 (см рис.6), то можно эту микросхему перевести в режим «SRAM MIRROR», «зеркалируя» на SRAM последовательно 16 страниц, начиная с 4-й. И тогда мастер-станция по I2C может записывать в эти страницы данные, как в мастер-чипы. И не только записывать, но и считывать. Причем делать это достаточно быстро – насколько позволяет RFID-протокол и шина I2C.

И тогда к этой плате можно подносить базовые станции как к мастер-чипу. Ресурс EEPROM этого «мастер-чипа» никогда не выработается – ведь вместо EEPROM используется SRAM. Конечно, надо будет для этого доработать прошивку мастер-станции. Но зато это позволит расширить возможности SportIduino.

Например, можно считывать логи из базовых станций практически неограниченного размера. На печатных платах базовых станций SportIduino версии 3 уже предусмотрено место под микросхему внешней I2C-EEPROM (думаю, что как раз для лога). Обмениваясь пакетами небольших размеров (32-48 байт) через SRAM микросхемы NFC, можно мелкими порциями считать лог из внешней I2C-EEPROM в базовую станцию. Скорость обмена ограничена только RFID-протоколом (чтение страницы 4 байта занимает около 1 мс) и шиной I2C. Около 4000 байт в секунду должно быть.

Или можно сделать обновление прошивки базовых станций «по воздуху», когда через такой «мастер-чип» новая прошивка сначала целиком сохраняется во внешней I2C-EEPROM базовой станции и устанавливается признак наличия новой прошивки (например, в EEPROM микроконтроллера базовой станции), а затем уже загрузчиком базовой станции (который надо будет также доработать) после рестарта определяется наличие новой прошивки и эта прошивка загружается из внешней I2C-EEPROM в flash-память микроконтроллера базовой станции.