В прошлых статьях я описывал переход с ардуино на STM32, STMCube/HAL, немного рассуждал про билд систему, бутлоадер, строил композитное USB устройство и прокачивал его скорость. Все это делалось на макетке на основе платы Blue Pill STM32F103CB и ежика из проводов. Пора устройству обрести форму, как электронную (схему), так и физическую (корпус).
Вопросы, которые мне предстояло решить на этом этапе очень сильно взаимосвязаны. Выбирая компоненты для проекта нужно примерно представлять в какой корпус их можно затолкать. И наоборот корпус нужно делать под компоненты, которые есть в наличии и платы, которые, опять же, нужно делать с прицелом на корпус. В общем клубок взаимосвязанных вопросов. Можно, конечно, взять коробку побольше и натолкать туда все что угодно, но ведь хотелось что нибудь компактное и легкое.
Прежде чем начать сразу хочу отметить, что это не финальный вариант устройства. Скорее всего в схеме найдутся ошибки, что-нибудь будет работать не так как задумано, в комментариях укажут на более правильные решения, какие-то подходы будут переосмыслены. Я думаю что второй или даже третьей версии устройства не избежать. Поэтому буду рад Вашим конструктивным комментариям.
Под катом многабукав, но будет инженерненько.
Компоненты
Начнем, пожалуй, с компонентов и периферии. По пути заодно прикинем количество ног микроконтроллера, которые потребуются для подключения этого зоопарка, а также параметры питания.
- Основным компонентом GPS логгера, разумеется, будет GPS приемник. В моем случае это довольно навороченный Beitian BN-880 на базе микросхемы UBlox M8N. В модуле встроен также компас на микросхеме HMC5883L.
Подключение: 2 контакта UART для GPS и 2 контакта I2C для компаса
Питание: от 2.7В
Потребление: 50мА- Также заказал модуль Beitial BN-220. В нем нет компаса, но зато антенна более компактная (20х20мм против 30х30). Правда пока неясно как это скажется на качестве приема. Нужно тестировать. Зато, судя по даташиту, этот модуль может работать от 1.4В, что должно позитивно сказаться на времени работы устройства.
- Тут на самом деле все как-то мутно. Вроде бы BN-880 построен на базе UBlox M8N, тогда как BN-220 на базе U-blox M8030-KT. Но в некоторых источниках проскакивает что это, вроде бы, одно и тоже. Точнее M8N это модуль, а M8030-KT это чипсет внутри. Меня же в этой неразберихе волнует вопрос питания — M8N заявлен от 2.7В, тогда как M8030-KT от 1.4В.
- В качестве альтернативы у меня также валяется модуль SIM868. в котором на борту помимо GPS есть ещё GSM/GPRS модуль и Bluetooth. Пока пугает своей навороченностью и сложностью подключения. Нужно будет сначала с отладочной платой поиграться.
- Основным отличием устройства от “просто черного ящика” является наличие дисплея. В первых прототипах я подключал дисплей по I2C, но загрузка шины получалась около 25%. Но дело даже не в процентном соотношении, а в том, что пересылка экранного буфера занимает около 25мс, во время которых нельзя общаться с другими устройствами на шине. Это может быть проблемой, поэтому нужно либо выносить дисплей на отдельную шину I2C, или рассмотреть вариант подключения по SPI
Подключение: 2 провода I2C или 3 провода SPI (дисплей write-only, поэтому линия MISO не используется, зато используется отдельный сигнал Data/Command)
Питание: от 3В
Потребление: 25мА - Для управления устройством у меня будут использоваться 2 кнопки, которые занимают 2 ноги процессора, соответственно
- В оригинальном устройстве (Holux M241, с которого я изначально копировал функционал) нельзя было посмотреть трек в произвольный момент времени. Нужно было обязательно подключать устройство к компьютеру и сливать данные специальной программой. Как мне кажется, возможность посмотреть трек на мобильном телефоне или планшете в любой момент будет весьма востребована. Для этого я приобрел Bluetooth модуль HM-13. Этот модуль выбран потому, что он умеет SPP в добавок к BLE.
Подключение: 2 провода UART, 1 провод статуса (подключено/не подключено)
Питание: 2.5V — 3.9V
Потребление: 50мА (хотя тут же рядом в даташите приводится цифра 13мА. Возможно это пиковое и среднее значение) - Как мне подсказали, нет смысла держать приемник включенным, если ты просто присел отдохнуть или зашел пообедать в кафе. Поэтому я решил добавить акселерометр MMA8452 и по нему определять находится ли устройство в состоянии покоя или мы куда-то движемся.
Подключение: 2 провода I2C, 1 провод на прерывание
Питание от 2В до 3.6В с каким-то микроскопическим потреблением - GPS трек будет записываться на SD карту. Я уже пробовал использовать карту в режиме SPI и это, мягко говоря, медленно. Особенно на запись. Правильный режим для SD карты — SDIO
Подключение: 6 проводов
Питание: от 1.8В
Потребление неизвестно, но думаю не больше 20мА - Для экономии электроэнергии есть смысл отключать питание тех устройств, которые в данный момент не используются. Так возле каждого потребителя я поставлю по транзистору, которым буду управлять отдельным сигналом микроконтроллера
Подключение: 5 сигналов, по одной ноге на потребителя (GPS, Bluetooth, акселерометр, SD карта, дисплей)
- Двухцветный светодиод для отображения статуса (как же без моргающего светодиода?). Можно было бы и трехцветный поставить, но пока не вижу необходимости.
Подключение: 2 контакта
Потребление: 10мА - Помимо Блютуса будет реализован более классический механизм сливания треков — через USB. Для этого будет задействовано 4 линии — дифференциальная пара для данных, 1 пин для детектирования, что устройство воткнули в USB, и еще один пин для логического подключения (зачем нужны эти 2 пина я расскажу ниже)
- Аппетит приходит во время еды. Раз уж я начал в свое устройство мечты пихать все подряд, то почему бы не добавить пищалку? Ну или вибромотор. Пока не придумал юзкейс.
Подключение: 1 провод
- Устройство еще нужно будет запитать. Пока на меня смотрит микросхема PT1502 в качестве зарядника литиевой батареи и контроллера питания. Для связи с микросхемой нужно будет задействовать 2 провода: один для управления питанием, другой для сигнала о севшей батарее. Еще ради интереса можно будет измерять напряжение батареи с помощью еще одной линии.
- Разумеется, заряд литиевого аккумулятора неправильно измерять исходя из напряжения. Поэтому я добавил специальную микросхему-счетчик INA219
Напряжение питания: 3-5В, рекомендуют 3.3В
Подключение: 2 провода I2CКак будет видно ниже напряжение питания в 3В создает некоторый дискомфорт в подключении. Я бы предпочел, чтобы микросхема-счетчик питалась от 2.7В или ниже. Но перебрав несколько вариантов исходя из цены/корпуса/доступности я так и не нашел ничего на 2.7В. Буду благодарен за подсказку.
- Осталось только предусмотреть отладочный интерфейс SWD (3 провода) и отладочный UART (еще 2 провода)
Меня всегда интересовал вопрос а зачем нужны контроллеры с большим количеством портов, а сам с легкостью насчитал 39 лап, нужных для моего функционала. И это не считая кварцев, ресета, и питания. Причем есть идеи чем занять еще с десяток (например, дисплей можно было бы подключать через параллельный интерфейс Intel 8080 или Motorola 6800).
Можно, конечно, I2C port externder’ы прикрутить, чтобы уменьшить количество используемых ног. Но во-первых это дополнительные компоненты на плате, во-вторых сильно усложняется программная часть, а в-третьих все равно в маленьких микроконтроллерах мало памяти, а там где памяти достаточно, там и портов тоже хватает. Так что не вижу смысла все усложнять — пусть будет 39 линий.
Питание
С напряжением питания пока не все так ясно. Можно, наверное, все устройства запитать от 3.3В и на этом успокоиться. Но мы же, все таки, мобильное устройство собрались делать, а значит нужно подумать об экономии электроэнергии. А значит нужно постараться выбрать напряжение питания поменьше. Чуть ниже я прикину какой именно экономии можно попробовать добиться.
Вот данные по всем устройствам в табличке — в таком виде удобнее выбирать домен питания к которому подключать то или иное устройство.
Из таблички легко видеть, что часть устройств могут работать от достаточно низких напряжений (от 1.8В). Другие могут комфортно работать от 2.7В. Наконец, оставшиеся устройства ниже 3В работать не могут. Пищалке, по хорошему, вообще 5В нужно, но у меня она будет питаться от самого большого напряжения — от батарейки, сколько бы на ней ни было.
С питанием дисплея пока не до конца понятно. В описании дисплейных модулей с али указан диапазон 3 — 5В, тогда как в даташите на контроллер матрицы SSD1309 указан диапазон 1.65 — 3.3В. Я предполагаю, что 3В нужно чтобы раскачать повышающий преобразователь на плате дисплейного модуля, тогда как логике достаточно 1.65В. Как будет видно из рассуждений про компоновку есть смысл отказаться от дисплейного модуля и подключить дисплей напрямую, что позволит запитать дисплей от домена 2В.
Примерно такие же рассуждения у меня и про GPS — в разных источниках указано разное напряжение питания. Пока у меня нет понимания какой модуль я буду использовать в итоге, потому пускай приемник поболтается в домене 2.7В.
С SD картой вообще не ясно. Спецификация мутно говорит о том, что вообще-то карта должна питаться от 3.3В, но современные карты достаточно умны и могут понять, что их воткнули в низковольтное устройство и могут переключиться на питание от 1.8В. Но механизм выбора питания до конца не очень понятный. Запитаю я карту от 2В и посмотрим что выйдет. Не получится — будет работать от 3В.
Итак, вырисовывается 4 шины питания — 2В, 2.7В, 3В и батарейка. Хотелось бы всех жрущих и постоянно работающих потребителей (а это контроллер и GPS) посадить на самую низковольтовую шину, но на данный момент я пока не определился с модулем GPS (а значит и с его питанием — 2 или 2.7В), а значит нужно будет некое универсальное решение. Попробую развести плату так, чтобы можно было легко либо одно, либо другое напряжение подать.
Откуда же взять столько разных напряжений? Еще на ранних этапах проекта я присмотрел микросхемку PT1502 даже уже успел попробовать в другом проекте. Помимо заряднинка для литиевой батареи в этой микросхеме есть аж 3 источника питания — один импульсный и 2 линейных понижатора. Вот, правда, на одном из них не регулируется напряжение и составляет 3В — попробую от него запитать INA219. Оставшиеся 2 источника питания проблемы не составляет, т.к. там напряжение можно выбирать.
Прикинуть потребление пока не очень получается. В даташитах указано пиковое потребление — этого достаточно, чтобы рассчитать мощность ключевых транзисторов, но недостаточно, чтобы прикинуть необходимую емкость батареи. Так что пока батарею буду подбирать исходя из доступного места в корпусе, а там уже измерю реальное потребление.
Может возникнуть вопрос, а как согласовывать устройства с разным рабочим напряжением? Давайте разбираться.
- Все коммуникационные ноги микроконтроллеры отмечены как Five Volt Tolerant (кроме UART2 на ножках PA2/PA3), а значит если там появится 3.3В от самого высоковольтного устройства ничего плохого не произойдет
- Акселерометр хотя и запитывается от 2В, может быть потенциально подключен параллельно с высоковольтными устройствами на шине. Эта проблема легко решается — у микросхемы MMA8452Q можно отдельно запитать коммуникационные выводы от другого питания (по самому “высоковольтному” устройству на шине)
- SD карту попробую запитать от того же напряжения, что и микроконтроллер, а значит ничего согласовывать не нужно.
- GPS и Bluetooth должны без проблем скушать “низкое” напряжение от микроконтроллера. Тоже самое касается и других “высоковольтных” устройств
Наконец, пару слов о том, зачем же я так борюсь за понижение напряжения питания. Фишка в импульсном DC-DC преобразователе, который может обменять вольты на амперы (если не брать во внимание потери самого преобразователя, разумеется). Если быть точнее, то обменять более высокое напряжение с низким током на низкое напряжение и более высоким током. Нас в данном случае больше интересует обратные рассуждения — если запитать низковольтную нагрузку через DC-DC, то потребляемый ток этой всей конструкции вместе с преобразователем будет ниже, чем потребляемый ток самой нагрузки. Ну а поскольку емкость батареи измеряется в мАч, то уменьшение потребляемого тока приведет увеличению времени автономной работы.
Вот табличка с расчетами. Пускай батарейка 900мАч линейно разряжается с 4.1 до 3.5В (что в общем случае не соответствует истине). КПД DC-DC преобразователя я поставил 90% (среднее значение из даташита). Разряжать будем током 100мА. Я хотел сравнить время работы устройства от линейного источника питания с импульсным.
Очевидно, что линейный источник разрядит батарею 900мАч током 100мА за 9 часов. А вот с импульсным источником устройство протянет гораздо дольше — 9.3 часа при целевом напряжении 3.3В, 11.4 часа при 2.7В, и целых 15 часов при напряжении 2В. Разумеется, расчеты ну оооочень грубые, но даже так видно, что с импульсным источником долгоживучесть аккумулятора существенно возрастает.
Микроконтроллер
К вопросу выбора микроконтроллера я подошел вдумчиво — долго игрался с конфигуратором, взвешивая все за и против каждого из вариантов. Мне очень понравились микроконтроллеры STM32, поэтому смотреть в сторону других контроллеров без особой необходимости не вижу смысла. Тем более что в линейке STM32 есть контроллеры на любой вкус и под любую периферию. Опыт полученный на предыдущих этапах моего проекта позволяет сузить выбор контроллера исходя из списка периферии, уже написанной программной обвязки, а также возможностей, которые я бы хотел реализовать в будущем.
Так, совершенно очевидно, что 20кб памяти моего STM32F103CB однозначно мало — очень не хватает буферов приличного размера для общения SD картой и USB. Многое из задуманного функционала я еще даже не начинал реализовывать, а занято уже больше 19кб. А вот с мощи для обработки, как оказалось, особо то и не нужно. Если все общение с периферией затолкать в DMA, то на долю центрального процессора остается всего пару процентов.
Прикинув список того, что мне нужно от контроллера я насчитал следующее:
- >= 128кб флеша (сейчас занято около 50к)
- >= 40 кб памяти (сейчас занято 19к)
- >= 40 ног GPIO (см. рассуждения выше)
- >= 40МГц (особо много не нужно, главное чтобы потребление было поменьше)
- DMA (уж больно понравилось)
- >= 2x I2C, >= 3x UART, >= 1 SPI
- SDIO (флешка через SPI работает очень медленно)
- Честный USB Full Speed, лучше High Speed
- Доступность (возможность купить пару штук за адекватную цену)
- Из пожеланий еще нативная поддержка параллельных LCD интерфейсов (обычно реализуется в виде модуля доступа к внешней памяти FSMC)
Микроконтроллеров у STMicroelectornics просто пруд пруди — на любой вкус, цвет и кошелек. Сначала я пробовал при выборе контроллера исходить из серии. Линейки L0 и F0 слишком слабые и мало памяти, S7 и H7 наоборот слишком навороченные, в L4 нет SDIO (UPD: SDIO есть, просто они его не упомянули на титульной странице серии). Среди остальных серий можно подобрать что нибудь исходя из моих нужд, благо у меня нет особо специфичных требований.
Серия STM32WB подкупает наличием Bluetooth, но корпус VFQFPN68 несколько охлаждает желание использовать его в хобби проектах. Да и в розничной продаже таких контроллеров не нашел.
Я целился на корпус LQFP64 — достаточный по количеству ног, но при этом не очень большой и можно запаять в домашних условиях. Хорошо, что есть конфигуратор CubeMX в котором можно фильтрами выбрать то, что нужно.
Остановил свой выбор на контроллере STM32F103RB по трем причинам. Во-первых я уже хорошо изучил серию F103 на примере платы Blue Pill. В целом контроллер STM32F103CB меня полностью устраивал, только памяти было маловато. Во-вторых у меня уже есть бутлоадер и низкоуровневый код по этот контроллер, тогда как под другие придется переделывать. Ну и в-третьих, примерно год назад я на радостях уже купил 3шт STM32F103RB. Тогда я не делал детальное исследование доступных контроллеров, а просто подобрал контроллер потолще из линейки F103. Не выкидывать же его теперь :)
Как я уже отметил, у меня нет особо специфичных требований по периферии или производительности. Но если упрусь во что нибудь, то на примете у меня уже есть контроллеры из линейки F4 (если понадобится что нибудь помощнее), или L152RD, если нужно будет что нибудь с потреблением решать (UPD: еще L433RC присмотрел). Что радует, у STM32 почти все контроллеры pin-to-pin совместимы, и F4 и L1/L4 можно будет впаять практически без переделки платы. Можно даже несколько плат с разными МК собрать и сравнивать потребление.
Пару слов про корпус и компоновку
С деталюшками определились. Пора рисовать схему, потом трассировать плату, а потом пытаться уместить ее в корпус. Или нет? Признаться я сначала как раз и пошел этим путем, но потом пришел к выводу, что все нужно делать в обратном порядке. Ну или как минимум одновременно.
Я бы хотел получить компактное устройство. А для этого нужно точно понимать размер доступного пространства, чтобы в свою очередь понимать где расположить плату и ее размер, батарею какого размера можно будет уместить, где расставлять кнопки, экран, разъем USB и другие внешние компоненты, а также прикинуть как крепить компоненты и можно ли удобно проложить провода между ними. Начинать разводить плату без понимания всех этих штук попросту бессмысленно. Вот и получается, что нужно сначала заняться корпусом и компоновкой, а потом уже переходить к схеме.
Также в процессе рисования корпуса мне несколько раз пришлось пересматривать выбор компонентов. Так изначально я думал использовать дешевый дисплей 128х64 размером 0.96” (размер рабочей области 21.7 х 11.2мм), но этот дисплей выглядел совершенно микроскопическим на фоне корпуса гораздо большего размера. Далее был заказан дисплей 1.3” (рабочая область 29.4 х 14.7 мм), но существенно лучше не стало. Далее я обзавелся дисплеем 1.54” (35 х 17.5 мм) — с ним выглядит более-менее нормально. На данный момент это основной рабочий вариант.
По прикидкам лучше смотрелся бы дисплей 1.8”-2”, но эти уже идут цветные и бОльшего разрешения, а соответственно экранный буфер будет достаточно большим для моего контроллера (35кб вместо 1кб). Ну и с впихиванием больших дисплеев в корпус также могут быть проблемы, т.к. посадочные крепления у таких модулей существенно больше чем активная область дисплея.
Пока я писал эту статью на али появились монохромные дисплеи 2.42” с тем же разрешением (128х64) и точно такой же обвязкой как у 1.54”. Заказал себе на пробу такой — есть шанс воткнуть его в мой корпус без существенного увеличения устройства.
Еще одним существенным моментом на этапе работы над корпусом стало понимание, что покупной дисплейный модуль занимает слишком много места и существенно уменьшает пространство для основной платы. Поэтому я решил отказаться от готового дисплейного модуля, а вместо этого поместить дисплей и его обвязку к себе на плату. Количество деталей в схеме несколько увеличилось, но зато конструкция в целом заметно упростилась и стала более компактной.
Аналогичные размышления у меня и на тему GPS модуля. Он не то, чтобы большой, но как его ни поставь он или мешает, или антенна закрывается какой-нибудь батарейкой. Возможно будет хорошей идеей поместить начинку модуля к себе на плату, а антенну разместить где нибудь в другом месте.
Работа над корпусом также позволила определиться с размером и емкостью батареи. В доступный объем как раз нашлась батарея на 900мАч — на нее и будем ориентироваться. Хотелось бы, чтобы мое устройство работало от батарейки часов 15-20, а значит потребление должно быть на уровне 45-60мА.
На данный момент я не могу назвать работу над корпусом законченной. Во-первых по прежнему открыт вопрос выбора для некоторых компонентов (дисплей, GPS). Во-вторых не ясно заведется ли моя схема в принципе или нужно будет что нибудь кардинально менять. Ну и в-третьих, плата получается ну уж слишком компактной — я не уверен, что в силах такое развести, спаять и отладить. Потому в этой статье я все же сфокусируюсь на вопросах схемотехники, буду двигаться более простыми и понятными шагами, а про корпус расскажу в следующий раз. Вот вам для затравки парочка рендеров и фотографий.
Схема
Вот теперь уже можно заняться электроникой. Я буду достаточно детально описывать схемотехнические решения. В первую очередь для таких же новичков в электронике как и я, а также в качестве конспекта самому себе. Опытные электронщики могут бегло просмотреть схемы и перемотать к следующему разделу.
Начнем с питания.
Аппарат будет запитан от литиевой батареи, а значит нужен контроллер заряда. Также некоторые компоненты имеют верхний предел по напряжению порядка 3.6В, тогда как на батарее может запросто оказаться больше 4В. Значит нужен понижающий источник питания. Как мы уже выяснили нам понадобится несколько разных напряжений.
Я уже упоминал что я буду использовать микросхему PT1502. Она удачно подходит, т.к. реализует контроллер заряда, 3 источника питания, а также схему включения устройства кнопкой. В микросхеме несколько функциональных блоков, которые на схеме для понятности я разделил. Сама схема представляет собой немного переработанную схему из даташита. Вот контроллер заряда литиевой батареи
Резистор R3 задает ток заряда. По умолчанию это соответствует 470мА. Возможно по результатам тестов я уменьшу номинал этого резистора до 510 Ом, что будет давать ток заряда около 900мА (1C).
О текущем режиме заряда контроллер может сообщать ногой CHG_STAT. Причем сигналов он умеет давать аж 3 — заряжается, не заряжается, и уже зарядилось, но еще подключено к розетке. В первом варианте внутренний транзистор прижимает ногу к земле и это легко можно опознать контроллером. Во втором варианте транзистор полностью закрывается и нога переходит в высокоимпедансное состояние. С помощью подтяжки к питанию такой сигнал также легко считать контроллером.
А вот с третьим состоянием не все так просто. Там транзистор приоткрыт и через него течет ток 20мкА. Для того, чтобы считать такое состояние мне подсказали подобрать подтяжку таким образом, чтобы на ноге оказалось примерно половина питания. Тогда можно будет с помощью АЦП легко детектировать такое состояние. Пользуясь законом Ома получаем R5 = 1В/20мкА = 50к.
Как я уже сказал микросхема PT1502 это не просто зарядник, но еще и хитрый контроллер всего питания. Микросхема следит за напряжениями на схеме и с помощью сигнала RESET может управлять главным процессором (мол, рано тебе еще запускаться, питание еще не стабилизировалось).
Также микросхема может запустить прибор по нажатию кнопки (BTN1), а также по сигналу от микроконтроллера (PWR_HOLD) завершить работу и отключить питание. Ну а чтобы сигнализировать процессору о том, что батарея на исходе предусмотрен сигнал BAT_LOW.
А это основной источник питания.
Выходное напряжение задается напряжением на выводе BUCKFB и при батарейном питании настроено на 2В. Но с двухвольтовым питанием обнаружилась одна проблема — USB работать не будет. Т.е. батарейка заряжаться будет, а данные передавать не получится — микроконтроллер просто не сможет выдавать сигналы на шину USB достаточной амплитуды. Даташит рекомендует напряжение как минимум 2.7В, лучше 3.3В.
Чтобы не городить еще один источник питания и думать как переключаться между ними, я решил просто корректировать соотношение делителя R1/R4+R7. При таком включении импульсник работает постоянно. Как только устройство втыкают в USB, транзистор открывается и шунтирует R7. Соотношение задающих резисторов меняется и на выходе получаем 3.16В (можно будет еще поиграться с номиналами и дотянуть до 3.3В).
В микросхеме PT1502 имеются также 2 линейных регулятора.
К этим регуляторам у меня будут подключены либо мало потребляющие компоненты (INA219), либо короткоживущие (bluetooth), так что КПД этих источников не будет проблемой. Напряжение питания LDO2 можно настроить с помощью сигналов LDO2_SETx.
Поскольку по напряжениям питания у меня все еще есть открытые вопросы, я решил развести перемычки для выбора режима LDO2_SETx. Также чтобы иметь возможность измерять реальное потребление по соответствующей шине я также разведу перемычки JP1/JP2/JP3 на гребенку.
Заканчивая тему источников питания нужно упомянуть о питании дисплея. Чуть выше я писал, что во имя компактности мне пришлось отказаться от покупного дисплейного модуля и забрать дисплей с обвязкой к себе на плату. Этот дисплей требует специального повышающего преобразователя на 7-16В. Удобно что этот источник можно включать и выключать с помощью сигнала EN. Сама схема скопирована с даташита повышатора, точно такая же используется и в дисплейных модулях с али.
Кстати, буду благодарен если Вы знаете аналогичные контроллеры питания от других производителей.
Теперь немного о питании микроконтроллера. Микросхема большая и имеет 6 линий питания — 4 на цифровую часть, 1 аналоговое питания и одно для часов. Согласно даташиту на STM32F103 на всех линиях питания (может быть, кроме часовой) должно стоять по конденсатору 100нФ, и еще один общий на 4.7мкФ.
А вот в даташите на STM32F4 сказано, что хотя микроконтроллеры практически совместимы по выводам, все же схемы питания у них несколько различаются. Так на двух выводах должны стоять конденсаторы по 2.2мкФ между выводом и землей (а не между землей и питанием, как у F1). Поэтому пришлось учесть оба варианта и для конкретного микроконтроллера запаивать только часть конденсаторов.
Продолжая тему питания, нужно придумать как его измерять. Можно полагаться на сигнал BAT_LOW и попросить пользователя быстренько закруглиться если батарейка разряжена. Но это именно то, что мне не нравилось в оригинальном Holux M-241, т.к. этот сигнал появлялся слишком поздно и его легко было проворонить. Мне нужен какой нибудь более информативный показатель заряда батареи.
На всякий случай я поставил самый обыкновенный делитель для измерения напряжения батареи. Но в случае литиевых аккумуляторов это только информативный показатель и полагаться на него не стОит. Для более честных показаний по батарее в интернете предлагают использовать “кулон”.
Эта маленькая микросхемка считает количество энергии, которое через нее прошло в или из батареи. Измерения производятся на шунте R10. Показания микросхемы можно считать через I2C. Микросхема умеет измерять напряжение на батарее, ток проходящий через резистор, а также перемножать одно на другое. К сожалению накапливать значение пробежавших мимо Ватт*Часов она не умеет, потому придется делать постоянный опрос.
Перейдем к цифровой части. Сердце всей системы — микроконтроллер STM32F103RB.
Обвязка в виде двух кварцев взята с других схем, найденных в интернете (перепроверено в даташите). Мне не потребуется загрузка из оперативной памяти, а потому сигнал BOOT1 подтянут к земле. BOOT0 можно выбирать перемычкой для загрузки из основной флеш памяти или встроенного UART загрузчика (например для первичной прошивки устройства)
Дальше светодиод.
Поскольку основное напряжение питания будет меняться от 2 до 3.3В то светодиоды к нему подключать не стОит — будет сильно меняться яркость и потребляемый ток. Поэтому светодиоды у меня будут подключены к шине 2.7В, токоограничивающие резисторы рассчитаны соответственно. Поскольку микроконтроллер не сможет выдавать на своей ноге больше 2В при питании от батареи, то push-pull режим GPIO использовать нельзя. Только open-drain.
Про кнопку ресета рассказывать особо нечего.
Поскольку на шине I2C будет сидеть трехвольтовое устройство (INA219), то и подтяжки также нужно делать к трем вольтам
Разъем SWD также стандартен. Диод нужен, чтобы переключать питание между батарейкой и внешним питанием от программатора.
Предвосхищая возгласы что так не делают и что такое подключение на самом деле не отключит батарейку. Да не отключит, но диод тут не для этого. Эта штука нужна чтобы иметь возможность запитать устройство от программатора, если батарея не подключена. А если подключена, то пусть от нее и работает. Ну и если батарея подключена, то нужно защитить сам программатор от 4.2В на батарее.
А вот на кнопках стОит остановиться подробнее.
Дело в том, что первая кнопка будет не только кнопкой, но будет работать также и как включатель устройства — сигнал BTN1 подключен к микросхеме контроллера питания PT1502. Когда устройство выключено питание на микроконтроллер и другие потребители не подается. Именно по этому кнопка подключена не к питанию (VCC) а к батарее (BAT). По нажатии на эту кнопку PT1502 включит все источники питания и запустит микроконтроллер. После этого кнопка может работать как обычная кнопка. Для того, чтобы микроконтроллер не спалить высоким напряжением батареи я соорудил небольшой делитель напряжения, который загонит сигнал BTN1 в необходимые рамки (впрочем, можно и без этого — у микроконтроллера есть входы, толерантные к 5В)
Вторая кнопка ничем не примечательна. Внутри процессора будет включена подтяжка к земле, а кнопка будет подавать на линию единицу…
Плавно переходим к тяжелой периферии. USB
Разъем USB будет торчать наружу устройства, а там может гулять статическое электричество. Оказывается есть специальные микросхемы (такие как STF202-22), которые охраняют микроконтроллеры от внешнего воздействия.
Но интересно тут другое. Внутри микросхемы STF202 спрятан резистор на 1.5к, который подключен между ногой VBUS и линией D+. Этот резистор нужен по спецификации USB — по нему хост узнает, что в него что-то воткнули. Во многих схемах этот резистор включен между питанием и линией D+ всегда. Как только хост видит такой резистор на линии D+ он сразу начинает общение с устройством. Это не всегда уместно, т.к. некоторые устройства могут быть сразу не готовы к коммуникации.
Это как раз мой случай. Для этого есть простая хитрость (подсмотренная тут). Можно включать и выключать этот резистор с помощью транзистора: хотим коммуникации — включаем резистор, хотим просто запитаться от USB — выключаем. Когда Вы втыкаете Ваш мобильник в USB он как правило спрашивает “что делать будем? Данные сливать или только заряжаться?” — в терминах электроники это как раз и идет речь о подключении подтягивающего резистора.
Но как узнать, что устройство воткнули в USB? Для этого я предусмотрел сигнал USB_PLUGGED, который снимается с простейшего делителя.
5В от USB можно было бы и напрямую на ногу микроконтроллера подавать — они же все таки толерантны к 5В. Но пусть уже будет через делитель.
Теперь акселерометр
Схема взята из даташита. Модуль подключен по I2C, но чтобы сигнализировать микроконтроллеру о том, что есть новости используется еще линия прерывания. Также, поскольку на той же шине I2C еще висит трехвольтовая INA219 то для согласования уровней коммуникационные ноги акселерометра также запитаны от шины 3В.
Я уже упоминал, что я бы хотел экономить электроэнергию и отключать неиспользуемые приборы. Так питание акселерометра включается транзистором.
Кстати, мне очень понравились т.н. цифровые транзисторы — транзистор в комплекте с двумя резисторами. Это позволяет сэкономить немного места на плате. Жаль только, что при двухвольтовом питании у меня не получилось подобрать цифровой транзистор с хоть сколько либо приличным током — 20-30 мА максимум. Так что более прожорливых потребителей пришлось подключать MOSFET’ами.
Идем дальше, GPS
GPS находится на отдельной плате и подключается через шлейфик. Поскольку я еще не определился с модулем GPS то предусмотрел 2 различных питания. Кроме транзистора питания на стороне процессорной платы больше ничего интересного нет.
Скажу лишь пару слов про UART’ы. Изначально я планировал использовать все 3 — один для заливки прошивки и дебага, второй для GPS и третий для Bluetooth. Но оказалось UART3 находится на тех же пинах, что и I2C №2, который я изначально планировал использовать для дисплея. Пришлось выбирать. В итоге я пришел к мысли, что заливать прошивку и дебажиться я могу через тот же самый UART, что отведен для GPS (разумеется GPS придется отключить). Ну а если нужно будет дебажить сам GPS, то есть еще USB CDC (в который можно наливать логи) и SWD. Чуть позже я отказался от идеи использования I2C №2, так что UART3 высвободился, но во имя экономии батареи я решил остановится на двух UART’ах.
Bluetooth
Bluetooth подключается по схеме из даташита. Вывод PIO1 может работать в двух режимах. В первом к нему подключается светодиод и модуль этим светодиодом моргает. Разные перемигивания означают разный статус. В другом режиме этот вывод работает как цифровой — единица когда связь установлена, и 0 если нет. Режимы переключаются AT командами при инициализации модуля.
SD карта
Схема подключения SD карты хоть и стандартна, но почему-то далась мне очень нелегко. В интернете слишком много разных вариантов подключений и понять какое правильное оказалось не так просто.
По большей части у меня были вопросы в проходных резисторах. Изредка встречаются схемы где ставят резисторы по 1к. Часть схем ставят резисторы по 22 Ома, видимо в качестве защиты от статики. Тем не менее бОльшая часть схем проходные резисторы не предлагают, и я, пожалуй, пойду тем же путем. Статики у меня также не будет т.к. флешка будет жить внутри корпуса.
Транзистор по питанию, как мне кажется, тоже не будет востребован, я думаю карта будет работать всегда — это же логгер. Но раз это плата тестовая, то пускай будет. Тоже самое и про катушку — видимо это включение в оригинале делал параноик, или карта использовалась в среде с плохим питанием или помехами. Думаю запаять туда нулевой резистор и попробовать без катушки.
Дисплей
У меня была возможность подключить один из дисплейных модулей с али через SPI и сравнить с подключением через I2C. Особых сложностей не возникло и код потребовалось лишь слегка расточить. При этом скорость у SPI на порядок выше чем у I2C. Добавив к этому данные из даташита по потреблению (4 мА у SPI против 10мА у I2C), необходимость в подтягивающих резисторах для I2C, я решил подключать дисплей через SPI.
К сожалению сигнал BS0 не выведен на шлейф дисплея, а потому нельзя выбрать режим 3-Wire SPI, можно только 4-Wire SPI. Разница в дополнительной линии D/C (данные/команда), которые в случае 3-Wire режима передаются девятым битом данных SPI. Впрочем, может 4-Wire режим это и к лучшему, т.к. SPI в STM32 может передавать только по 8 бит.
В остальном схема соответствует даташиту.
Ну и напоследок пищалка. Ничего особенного — просто включается через транзистор.
На случай если вместо пищалки будет вибромотор, я предусмотрел защитный диод. Впрочем, слышал мнение, что пищалке защитный диод также не помешает.
В железе
Выше я описывал свои размышления на тему корпуса. На самом деле я даже пытался развести плату под этот корпус. К сожалению плата оказалась слишком тесной. Пришлось использовать двусторонний монтаж, перейти от компонентов 1206 на 0805, но все равно компоненты на плате были расположены очень плотно. Более того, каждое изменение в схеме было болью, т.к. приходилось переразводить чуть ли не полплаты.
Так я с ней возился несколько недель, но плата меня победила и проект я забросил почти на год. Пинком стала вот эта статья. А ведь действительно, это же только прототип, причем первый из нескольких. Зачем мучиться со сверх компактной платой, куда не подлезть ни паяльником, ни осциллографом, если можно все отладить на большой плате?
Ну такую огромную плату как у айфона делать не обязательно, а вот в акционные 100х100мм 2 слоя у JLCPCB влезть вполне реально. Можно себя практически не ограничивать. Так на плате разместился огромный дисплей 2.42”, джамперы измерения потребления по всем линиям питания, конденсаторы по питанию где нужно и не нужно, и вообще куча деталей, которые можно было бы и не устанавливать. Еще и место осталось.
По разводке особо рассказывать нечего. БОльшую часть сигнальных и силовых линий я разводил по верхнему слою, тогда как нижний практически полностью отдал под землю. К сожалению компоновка все равно получилась достаточно плотной и некоторые сигнальные линии пришлось тащить по нижнему слою через полплаты. Из-за этого земля местами “разрывается” на несколько слабо связанных островов. Надеюсь это не составит проблем.
Под антенной bluetooth землю не делал, но все равно пришлось протащить одну из сигнальных линий через эту зону. Впрочем, это линия BT_ON, по которой сигналы часто не бегают (там либо включено, либо выключено), а значит особо сильно на сигнал влиять не должно.
Близилось лето и я планировал взять плату с собой в отпуск. Чтобы горничные в отелях не пугались голой отладочной платы с веером проводов было бы неплохо спрятать это в корпус. Я не мог отказать себе в удовольствии и разрабатывал корпус и плату одновременно. Так появились крепления платы в корпус, крепления держателя дисплея.
Модуль GPS это бутерброд из нескольких плат и антенны толщиной 12мм. Я решил его не цеплять сверху на плату, а расположить на одном уровне. Это уменьшило толщину корпуса, но откусило у платы один угол.
Пару фотографий платы и финального (на этом этапе проекта) устройства.
Батарея удачно размещается под дисплеем, но пришлось сделать небольшую коробочку для того, чтобы приподнять дисплей ближе к верхней крышке.
Пару слов по сборке платы. Спаял я все примерно за 3 вечера, и еще примерно неделю по вечерам ушло на неспешную отладку и проверку со стороны программной части. К моему удивлению фундаментальных сложностей с наладкой платы не возникло и практически все завелось как надо.
Рассыпуху 0805 оказалось паять не намного сложнее чем 1206, вполне съедобно в домашних условиях при наличии увеличительного стекла. Можно даже на 0603 замахнуться. А вот с пайкой микроконтроллера и разъема дисплея (у них шаг выводов 0.5мм) пришлось повозиться. На ютубе у людей это как-то просто выглядит — провел раз паяльником и все, а у меня все выводы послипались мгновенно.
Не обошлось и без мелких проблем. Кое-где был непропай, где-то была “сопля”. Футпринт под USB разъем оказался неправильным — у него шаг выводов был меньше чем нужно (вот и верь после этого футпринтам из интернета!). Пришлось немного подогнуть выводы, чтобы они стали на дорожки. FPC разъем дисплея купленный на али оказался с контактами снизу, тогда как мне нужен был с контактами сверху (я до этого и не подозревал о таком различии). Пришлось “сдуть” разъем со штатной платы дисплея.
После запихивания платы в корпус оказалось, что отключать батарейку просто выдергиванием разъема не получится, а оставлять неотлаженную плату под напряжением не хотелось. Пришлось приколхозить выключатель.
При настройке платы оказалось, что нигде нет земляного контакта, куда можно было бы прицепить щуп осциллографа. Пришлось цепляться крокодилом за USB разъем. Нужно будет предусмотреть тестовые площадки в следующей версии платы.
По схемотехнике также обнаружились проблемы. Так совершенно неожиданным фактом оказалось, что микросхема PT1502 на выводе RESET генерирует напряжение в 3В (я был в полной уверенности что там что нибудь вроде открытого коллектора). В итоге эти 3В утекали на линию питания, даже при том, что я планировал там иметь всего 2В.
Вот упрощенная схема того, что получилось
Спасибо великому разуму и ребятам с easyelectronics.ru, этот косяк решился добавлением одного диода. После небольшого хирургического вмешательства эта часть заработала как надо.
Далее, блютус модуль (питается от 2.5В) я нечаянно подключил к основному питанию (2В), вместо фиксированных 3В. Теперь блютус у меня может работать только при подключенном USB, когда напряжение основного питания поднимается до 3.3В.
В принципе можно было бы взмахнуть скальпелем и припаять блютус к правильному питанию, но UART2 к которому подключен блютус не толерантен к 5В (сам же вычитал это в даташите на стадии анализа, сам же отметил это в тексте выше, и в итоге забыл при разводке платы). Потому подключение блютуса к питанию выше чем питание микроконтроллера чревато… В следующей версии платы просто подключу блютус к какому нибудь другому UART’у.
DC-DC преобразователь с изменяемым напряжением также заработал как и планировалось — при питании от батареи исправно выдает 2В, а когда подключаешь USB поднимается до 3.16В (нужно бы поиграться с номиналами и дотянуть до 3.3В). Но тут вылезла еще одна недоработка схемы: нужно также уметь поднимать напряжение и при питании от программатора. Думаю это лечится добавлением еще одного диода. Попробую поиграться чуть позже.
Наконец, за время работы над платой мне так и не стало понятнее как же правильно запитывать SD карту от пониженного напряжения. Непродолжительное гугление ни к чему не привело. По всей видимости нужно погружаться в чтение тесычестраничных спецификаций (которые, к тому же частично закрыты). Ну а пока я закоротил R7 и плата теперь питается от фиксированных 3.16В (3.3В). Оставлю пока так на ближайшие пару месяцев, пока я буду заниматься программной часть.
Кстати о софте. Удивительно (хотя и вполне ожидаемо), но в целом все завелось без проблем. Поскольку я переходил между микроконтроллерами одной серии (с F103CB на F103RC), то переделки программной части не потребовалось. Только номера пинов поправил, да добавил включение транзисторов. Тем не менее было 2 нетривиальных момента с которыми пришлось повозиться.
Первый — это питание от батарейки. Отладку платы я проводил при питании от USB и все в целом работало хорошо. Но вот от батареи плата включаться упорно не хотела. Т.е. работать может (если ее включить при подключенном USB, а потом выдернуть шнурок), но запуститься на холодную не получается.
По дизайну микросхемы PT1502 стартовать плата должна примерно так. Пользователь нажимает кнопку BTN1 и через треть секунды микросхема включает все источники питания. Когда с питанием все хорошо PT1502 “отпускает” сигнал RESET, тем самым запуская микроконтроллер. Процессор в свою очередь выставляет сигнал PWR_HOLD в единицу, сигнализируя о том, что он запустился. После чего PT1502 исправно поставляет электричество в схему, пока микроконтроллер не опустит сигнал PWR_HOLD в ноль.
Но это в теории. На деле же как только процессор выставлял сигнал PWR_HOLD плата мгновенно выключалась. Я перелопатил всю схему питания, смотрел осциллограммы основных сигналов, тасовал туда-сюда код в бутлоадере, но проблему осознать не получалось. Я также грешил на отсутствие pull-down резистора на линии PWR_HOLD, который я забыл установить, но он рекомендуется даташитом (и он скорее всего таки нужен). Но добавление его навесом проблему не решало. И только когда я одолжил четырехканальный осциллограф все стало ясно.
Когда пользователь нажимает кнопку (оранжевая линия) микросхема PT1502 включает питание (фиолетовая линия). Все это происходит задолго (300мс) до событий на этой осциллограмме. А дальше происходит нечто интересное. PT1502 отпускает RESET (голубая линия), процессор запускается и зачем-то опускает линию кнопки в ноль. Даже несмотря на то, что микроконтроллер еще пытается поднять линию POWER_HOLD (зеленая линия) — уже поздно, PT1502 уже выключил все источники питания. Дальше происходит еще несколько конвульсий, но схема все равно тихо умирает.
Вопрос в том откуда взялся ноль на кнопке? Все дело в неприметной ошибке в бутлоадаре, из-за которой на ноге BTN1 выставлялся режим вывода (возможно на других ногах также происходили чудеса в этот момент) и там появлялся низкий сигнал.
С чем еще пришлось пободаться, так это с SD картой. В старом микроконтроллере модуля SDIO попросту не было, так что этот кусок пришлось изучать с нуля. Я провозился почти целый день в попытках завести карту, копируя куски кода из примеров в интернете, и того, что сгенерировал CubeMX. Хотя карта отлично читалась в компьютере, в моей схеме заводиться упорно не хотела. Я грешил на плохую пайку, неверно выбранные подтягивающие резисторы, корявую схему и неверно трактованный даташит. Но к моему удивлению другая карта с тем же кодом и на той же плате завелась без проблем. Нужно будет этот вопрос изучить более детально.
С картой была связана еще одна проблема. Потыкав в разные линии осциллографом я увидел активность только на линии D0, тогда как на D1-D3 была тишина — карта работала в однобитном режиме. В HAL даже обнаружилась функция HAL_SD_ConfigWideBusOperation() которая может включить 4-битный режим передачи. К сожалению когда карта переводилась в 4 битный режим, то SDIO периферия уходила в глубокий RX FIFO Overrun и переставала работать.
Проблема оказалось весьма интересной. Оказалось что внутри функции HAL_SD_ReadBlocks() есть некий цикл, который опрашивает флаги SDIO. По мере поступления новых данных от карты этот код перекладывает байтики из внутреннего FIFO буфера в пользовательскую память. Так вот карта передавала байты настолько быстро, что код в HAL_SD_ReadBlocks() попросту не успевал перекладывать данные. Пришлось временно понизить частоту тактирования карты. Ну а в будущем я буду использовать DMA и такой проблемы не должно возникать в принципе.
Заключение и дальнейшие шаги
Тех кто в этом месте ожидал увидеть законченное устройство мне придется огорчить — закончена только тестовая плата, да и то, только железячная часть. Теперь в нее нужно вдохнуть жизнь, заняться программной обвязкой, тонкой настройкой режимов и потребления. Ну и собственно написать код логгирования — то ради чего и затевался весь проект.
Тем не менее, лично для меня этот этап это очень больше и важное достижение. Электроника это не моя специализация и я очень рад, что устройство вообще запустилось. Мне удалось достаточно сильно прокачаться в проектировании схем, согласовании нескольких устройств, разводке платы, выборе компонентов и много еще в чем другом.
Про программную часть я расскажу в другой раз. Как и про нюансы настройки. Дело в том, что эту всю начинку нужно сначала оживить и протестировать. На данный момент удалось запустить все устройства на плате (ну кроме пищалки), но только в объеме “запустилось и как-то отвечает”. Никакой логики обработки еще не написано.
Планы на ближайшее будущее:
- Поганять электронику в разных режимах, проверить что схема таки работает. Исправить косяки во второй версии платы
- Измерить потребление всей периферии и найти пути оптимизации потребления.
- Собрать несколько вариантов платы на разных микроконтроллерах (например на L152 или L433)
- Вдумчиво прочитать спецификацию SD и разобраться как правильно подключать карту в режиме Low Voltage Signaling (1.8В)
- Попробовать разные GPS модули и, наконец, определиться с каким я пойду дальше
- Заказать отдельную микросхему компаса (например HMC5883L или HSCDTD008A) и попробовать их как-то использовать
- Сделать внутренний рефакторинг кода, проапгрейдить все основные библиотеки, начиная с HAL
- Начать, наконец, писать фичи. Собственно реализовать то, ради чего задумывалось устройство
На этом разрешите откланяться. Буду благодарен за конструктивные замечания, идеи и советы по схемотехнике и разводке платы.
Исходники:
Код: github.com/grafalex82/GPSLogger
Код бутлоадера: github.com/grafalex82/STM32duino-bootloader/tree/gpslogger_bootloader
Плата: easyeda.com/editor#id=cb23183151c2464380107f0eeacf7e00|216b592b6e5d4f37bc20d5f519963c22
Корпус: cad.onshape.com/documents/8092a5e633174f005b156d23/w/b48f920e9dbda410343914c6/e/c9718a9053bda2a2bb7ed4da