В прошлом я занимал должность инженера ПО в двух компаниях-производителях нательной электроники — Pebble и Fitbit. За время моей работы клиенты постоянно жаловались на одну и ту же проблему: продолжительность работы батареи. Это была непрекращающаяся «борьба с гидрой», когда каждая новая версия прошивки вела к очередной регрессии жизни батареи.
Длительность работы батарей очень важна для многих продуктов, которые мы используем в повседневной жизни: телефоны, машины, часы, наушники, мышки и другие устройства — все постепенно переходят на автономное питание. И хотя некоторые потребители могут предпочесть продолжать запитывать свои устройства по проводу, подавляющее число клиентов требуют беспроводных устройств, на производство которых и нацелились многие компании.
В идеале для каждого нового девайса, каждой новой прошивки и для 99% клиентов не должно быть сюрпризов, связанных со временем работы батареи.
В этой статье я расскажу, как наладить сбор метрик для оценки продолжительности её функционирования, как анализировать эти данные для отдельных устройств, и как собирать все метрики с парка устройств для точного прогнозирования работы батареи при использовании определённой прошивки. Все эти возможности помогут разработчикам оптимизировать продолжительность работы батареи и исправлять проблемы сразу же при их появлении, независимо от того, сколько у вас в парке устройств: десять или миллион.
Содержание
- Почему важна продолжительность работы батареи
- Работать с батареями трудно
- Измерение потребляемой устройствами мощности
- Небольшое вступление по теме метрик
- Метрики, которые обычно связаны с потреблением энергии
- Метрики батареи для одного устройства
- Метрики батареи для всего парка устройств
- Сравнение длительности работы батареи среди разных версий ПО
- Лучшие практики
- Использование Memfault в качестве стека мониторинга
- Заключение
Почему важна продолжительность работы батареи
Пользователи хотят, чтобы их IoT-устройства можно было один раз настроить и забыть. После установки подключения и загрузки продукта не должно возникать никаких нюансов за исключением периодической смены батареи. При этом заменяться или перезаряжаться батареи должны как можно реже, продолжая работать ожидаемое количество времени. В Pebble на упаковке часов говорилось, что их батареи ёмкостью 130 мАч должно хватать на 7 дней, и это было нашей целью. Если же часы в итоге не могли проработать заявленные 7 дней, приходилось делать возврат.
Также важно, чтобы поведение батареи соответствовало ожиданиям клиента. Одно дело, когда часы линейно разряжались со 100% до 0% в течение 6 дней, и совсем другое, когда они на протяжении 3 дней показывали заряд 90%, который затем резко падал до 10%, и на 4-й день отключались.
Пользователи ожидают правдивых показаний от батарей, но мы, как инженеры, тесно связанные с аппаратным обеспечением, знаем, что это не всегда так. С батареями работать трудно, и это наша обязанность — сделать их надёжными.
Работать с батареями трудно
Это так. Батареи по разным причинам делают нашу жизнь чуть печальнее. Начнём с того, что при измерении оставшейся ёмкости батареи мы обычно наблюдаем только её напряжение, которое является довольно нестабильной величиной.
Вот несколько других причин, по которым батареи являются одной из самых болезненных составляющих разработки электронных продуктов.
▍ Окружающая температура влияет на эффективность батареи
Работая в разных условиях, батареи ведут себя по-разному. Например, при эксплуатации в холоде эффективность Li-Ion батарей сильно снижается, что можно видеть по графику ниже.
Некоторые батареи также могут повреждаться от перегрева, а некоторые при зарядке в холодных условиях. Это температурные существа, и лучше стараться обеспечивать для них стабильную рабочую среду, хотя это, конечно, утопия.
К счастью, те устройства, с которыми мы работали в Pebble, всегда носились на запястье, так что здесь у нас была хорошая температурная стабильность.
▍ Поведение батареи изменяется под нагрузкой
Выдаваемое батареями напряжение может отличаться в зависимости от силы потребляемого тока на момент измерения, что можно видеть по графику ниже.
Лучше всего измерять напряжение во время известного или ожидаемого уровня потребления тока.
В случае наших часов Pebble мы делали две вещи. В первую очередь мы старались во время измерения напряжения батареи выполнять оптимизацию, чтобы в тот момент отсутствовало высокое потребление тока. Наиболее значительное потребление происходило при использовании ЖК-подсветки, вибрации и интенсивных вычислений процессора и графики (как в демо Intrinsic Gravelty Хейко Бехренса).
Во-вторых, при каждом считывании напряжения, которое мы регистрировали и использовали в вычислениях, производилась множественная выборка за короткий период, из которой мы брали средние показания. Это позволило отсеять шумы, обусловленные потреблением большого объёма энергии, и низкие уровни напряжения, которые могли исказить показания. В нашем случае двумя серьёзно влияющими на напряжение элементами были вибромотор и подсветка дисплея.
▍ Не все батареи одинаковы
У одного поставщика могут встречаться как хорошие, так и неудачные партии батарей. Некоторые экземпляры могут оказываться очень качественными, в то время как другие будут упираться в порог минимального рейтинга по ампер-часам. Так уж обстоят дела, особенно когда проекты считают копейки в своих расходах на материалы.
Кроме того, как вы наверняка знаете, со временем батареи стареют и с прохождением всё большего числа циклов заряда утрачивают свою ёмкость. В Pebble мы это учли, постепенно обновляя кривую разряда батарей для разных ревизий устройств, а также делая это год за годом в попытках предпринять всё возможное для компенсации износа.
Измерение потребляемой устройствами мощности
Начнём создавать модель для понимания того, как долго проработают наши устройства на батарее. Первым шагом мы измерим, сколько энергии потребляет устройство на базовом уровне. Под этим подразумевается его работа в трёх основных состояниях: минимальная нагрузка, нормальная и повышенная.
Использование всех этих трёх профилей потребления энергии помогает построить картину того, сколько может потреблять отдельное устройство, а с этим понять, на сколько хватит его батареи.
▍ Профили мощности для каждого компонента
Первым шагом мы создадим основу для понимания того, сколько каждый компонент будет потреблять с течением времени. Несмотря на то, что в спецификациях устройств обычно содержатся данные о потреблении ими энергии, эта информация не всегда точна, и разные компоненты из разных партий будут иметь отличные друг от друга характеристики потребления.
Нам нужно проделать следующие шаги:
- Убедиться, что на ваших макетных платах есть шины питания, чтобы можно было изолировать множество компонентов и легко подключить к ним щупы.
- Взять мультиметр, способный измерять силу тока в мкА и мА.
- Написать прошивку, инструментирующую один компонент в различных режимах, и определить, сколько тока он потребляет в каждом режиме. Это должна быть простейшая прошивка, в идеале содержащая только код драйвера.
- Повторить все эти действия с каждым компонентом, который может значительно влиять на потребление энергии.
К примеру, в одном нательном устройстве акселерометр потреблял много энергии, если его надолго оставляли не в том состоянии. Мы написали прошивку, которая устанавливала для него разную частоту дискретизации и регистрировала потребление тока, после чего определили с её помощью частоту, при которой можно было сохранить акселерометр, достигнув 7-дневного периода работы батареи.
▍ Уровень заряда (SoC) во времени
Определив, может ли наше устройство успешно выполнить все поставленные требования по длительности работы батареи, нам нужно протестировать его с другой стороны. Теперь мы рассмотрим измерение уровня заряда во времени, чтобы подтвердить необходимую длительность автономной работы.
Одним из наиболее типичных и простых способов оценить электроёмкость батареи (SoC устройства) является измерение её напряжения во время постоянного потребления известного объёма энергии. Но этот метод не единственный.
▍ Кулоновский подсчёт с помощью топливных датчиков
У нас в Pebble в одном из видов часов использовался топливный датчик. Топливный датчик — это толковый аппаратный компонент, который может показывать SoC батареи и её состояние. Он понимает её энергоёмкость в двух аспектах: измеряет напряжение и выполняет кулоновский подсчёт, который показывает, сколько тока поступает в батарею и выходит из неё.
Для устройств с ёмкими батареями, таких как телефоны, машины и прочие, топливные датчики являются оптимально подходящим компонентом. Они надёжны, и вы можете доверить им сложную задачу по измерению текущей ёмкости батареи.
Но в свете такой похвалы в адрес топливных датчиков, зачем тратить столько времени на разговоры про её измерение с помощью напряжения? Дело в том, что в Pebble мы не могли использовать топливные датчики, поскольку они потребляют больше энергии, чем было допустимо. Существуют тысячи продуктов, которые могут столкнуться с аналогичной проблемой, особенно ввиду того, что люди хотят создавать сенсоры и IoT-устройства, работающие в течение месяцев и даже лет на небольших батареях.
Если вам повезёт с возможностью применить топливный датчик, и при этом вы будете использовать Zephyr RTOS, обязательно познакомьтесь с их новым Fuel Gauge API, недавно добавленным в Zephyr v3.3.
▍ Определение уровня заряда по напряжению
Обычно компании используют именно этот способ, так как измерить напряжение батареи очень легко, и для этого не требуется много энергии. Проблема лишь в том, что показания отслеживаемого напряжения сложно читать, их повышение/падение происходит нелинейно, и при разных условиях работы они изменяются.
Нам нужен более эффективный способ.
▍ Измерение уровня заряда с помощью напряжения и зарядной кривой
Преобразовать показания напряжения в процент поможет зарядная кривая батареи. По своей сути эта кривая весьма проста: она отражает сопоставление между напряжением батареи и относительным процентом, который, вероятно, соответствует этому напряжению. У продуктов также обычно есть кривая заряда и разряда.
Такую кривую компании получают, когда хорошо понимают свойства своей батареи и имеют достаточно данных для её генерации. Она гораздо понятнее для клиентской поддержки и инженеров, которые не причастны непосредственно к подсистеме батареи.
В этом году, работая в Embedded World, я познакомился с интересным инструментом — Qoitech. Он создаёт продукт, который помогает пользователям строить кривые заряда и разряда в разных условиях. Я считаю, что их продукт стоит своих денег, если он способен помочь компаниям переводить неявные показания напряжения в понятные для всех проценты.
Небольшое вступление по теме метрик
Прежде чем погружаться в дальнейшие разделы, посвящённые сбору и объединению метрик, описывающих состояние батареи, мы вкратце разберём, что вообще такое метрика. Это очень важно, поскольку я встречал firmware-инженеров, которые не уделяли им должного внимания.
Метрика — это измерение, выполненное во время работы устройства. При этом процесс совмещения большого числа метрик и вычисления статистики называется агрегированием.
Вы можете собирать метрики почти обо всём в системе. В прошивках я люблю измерять такие показания, как время выполнения задач, число ошибок и время подключения, потребление энергии периферийными устройствами и другие. Передав все эти метрики с устройства в хранилище данных, вы можете отыскать в них тенденции.
Тем не менее сбор и агрегирование метрик не всегда происходит столь же легко, как может прозвучать. Если вы хотите узнать больше о лучших практиках сбора метрик, то рекомендую изучить следующие ресурсы:
- Interrupt — Firmware Heartbeat Metrics. Эта статья советует агрегировать метрики на устройстве и отправлять их с установленными интервалами.
- Memfault Webinar — The Power of Metrics — Monitoring Battery Life, Connectivity, Power Consumption & More. Здесь рассказывается, какие метрики лучше всего собирать, чтобы оптимизировать сетевое подключение и длительность работы батареи.
- Memfault Docs — Data Serialization Overview. В этом документе освещается, как платформа Memfault построила свой слой сериализации событий, максимально облегчив добавление новых метрик и их сжатие до минимальных размеров.
Одна из важнейших стратегий, вытекающих из приведённых материалов, заключается в отправке этих метрик устройств и их прошивок в хранилища данных с регулярными интервалами, обычно раз в час.
Например, если вы хотите отследить отключения функции BLE (Bluetooth Low Energy), то отправляете число отключений, произошедших в течение этого интервала времени, и только его. То же касается измерения времени работы микросхемы BLE. Отправляйте количество секунд, в течение которого она была активна. Генерация метрик с фиксированным интервалом позволяет упростить их агрегирование, поскольку оно выполняется с помощью простой математики.
Возьмите общее время подключения, поделите его на количество пульсов, и вы получите среднее время подключения на один пульс.
Но нас интересуют не отключения Bluetooth-соединений. Давайте поговорим о питании.
Метрики, которые обычно связаны с потреблением энергии
Ниже приводится частичный список тех процессов, которые я отслеживал в прошлом, и которые помогали мне и моим коллегам понять, что конкретно потребляет энергию батареи.
▍ Сетевое взаимодействие
Сюда относятся все виды беспроводной связи, такие как WiFi, LoRa, Bluetooth, ZigBee, LTE и так далее.
- Отправленные/полученные пакеты.
- Отправленные/полученные байты.
- Число подключений/отключений.
- Время, проведённое в каждом состоянии (оповещение, подключение).
- Настройки питания и сила радиосигнала.
- Пропускная способность.
- Количество повторных попыток.
▍ Использование периферии
Здесь мы стараемся измерить показания всех периферийных устройств, которые могут потреблять значительные объёмы энергии.
- Время включения/отключения датчика (акселерометра, гироскопа, GPS, камер, компаса и так далее).
- Время включения/отключения актюатора.
- Общий диапазон актюатора.
- Время включения/отключения дисплея и подсветки.
- Количество обновлений дисплея.
- Время включения/отключения камеры.
- Чтение/запись/стирание данных из хранилища.
▍ Использование процессора и кода
- Время пробуждения, засыпания и входа в глубокий сон процессора.
- Время, проведённое за выполнением каждого задания в системе.
- Время выполнения требовательных блоков кода.
- Время загрузки.
- Количество записанных логов.
- Время, проведённое в блокировке мьютексами или в очередях.
- Количество переключений контекста для обнаружения переполнения памяти.
Метрики батареи для одного устройства
Самым важным случаем использования метрик является отлаживание проблем отдельных устройств внутренне или через клиентскую поддержку. Я вижу, как большинство компаний начинают диагностику проблем с логов, но именно использование метрик несёт реальную ценность. Это позволяет вам наглядно видеть и собирать намного больше данных, особенно в случае строгих ограничений пропускной способности (спутниковое подключение, LTE и так далее).
Для измерения длительности работы батареи самой важной метрикой, естественно, является SoC устройства. Как уже говорилось, она обычно отправляется сначала в виде показаний напряжения, а в конечном итоге, после применения разрядной кривой, в виде процентов.
Отобразив эти две метрики наряду с другими, вы сможете быстро и легко увидеть, какие из них связаны с потреблением заряда батареи.
В примере выше показатель SoC % для нашей батареи (синяя линия) стремительно падает. Это может быть связано с тем, что процессор намного активнее во время этого окна, чем обычно, что, в свою очередь, может объясняться количеством байтов, записываемых во флеш-память.
Зная это, мы можем вникнуть в другие имеющиеся метрики или добавить новые. Нам следует начать собирать метрики для каждого модуля, записывающего в память, или отслеживать, какие задачи выполняются во время высокой загрузки процессора. Естественно, вы можете отслеживать слишком много метрик для одной прошивки, но по факту это не будет особо накладным. Учитывая, что каждая метрика потребляет от 4 до 8 байтов на измерение в час, я работал с прошивкой, которая собирает от 50 до 200 метрик.
Как уже говорилось в течение статьи, в некоторых проектах будет регистрироваться только напряжение, отправляемое в виде метрики. Это работает относительно хорошо при анализе одного устройства, особенно если период работы батареи составляет всего пару недель, и метрики можно просматривать в течение всего этого времени. Однако если у вас есть возможность, то будет гораздо полезнее регистрировать процентный показатель. Так что стройте разрядную кривую!
Метрики батареи для всего парка устройств
Пытаясь решить все проблемы с батареей для каждого отдельного устройства, далеко не уйдёшь. Ни один инженер не имеет столько времени, чтобы каждый день просматривать метрики всех отдельных устройств, выясняя, ухудшается ли состояние их батарей, и внесла ли новая прошивка улучшение или ухудшение. Именно поэтому нам нужна возможность агрегировать эти метрики по всему парку устройств.
В масштабах парка из миллиона девайсов определить среднее время работы батареи бывает очень трудно. Этот процесс можно упростить, следуя приведённым далее рекомендациям и ориентируясь на описанный мной опыт.
▍ Не регистрируйте уровень заряда напрямую
Показания напряжения или выведенный из них процент, полученные напрямую, не удастся агрегировать по всему парку.
Представьте, что ваша база данных каждый час получает следующие точки данных от 4 устройств. Значения, выделенные жирным, указывают на повышение процента SoC.
Устройство А | Устройство В | Устройство С | Устройство D |
75% | 23% | 92% | 5% |
72% | отсутствует | 89% | отсутствует |
67% | отсутствует | 85% | 10% |
34% | 19% | 100% | 7% |
78% | 21% | 97% | 5% |
Вряд ли мне бы удалось внести всё это в базу данных и написать SQL-код, определяющий среднее падение длительности работы батареи в час для каждого устройства и агрегирующий результаты. Да и сомневаюсь, что база данных смогла бы вычислить такую операцию для миллиона устройств, предоставляющих по нескольку тысяч точек данных каждое.
Есть здесь и другие проблемы:
- Поскольку нам нужно вычислить дельты между каждым показанием SoC, это означает, что мы не можем отбросить данные, и все они должны быть получены и обработаны по порядку. Одного этого факта должно быть достаточно, чтобы напугать любого, работающего в индустрии микропрограмм.
- Что, если устройство отключится от сети на один-два дня и вернётся уже с совершенно другими показаниями SoC? Предположим ли мы, что зарядное устройство за это время не подключалось?
- Как можно достоверно узнать, что зарядное устройство использовалось?
Рассмотрим изображение ниже. Если бы мы просто регистрировали каждую точку данных показаний SoC в процентах, то ничего не знали бы о сбое питания и последующем событии зарядки.
В конечном итоге мы стараемся вычислить первую производную от процента заряда батареи в нашей базе данных. Тем не менее это вычисление может нарушаться отсутствующими точками данных, что делает его практически невозможным. Есть способ получше.
▍ Регистрируйте дельту уровня заряда
Вместо того, чтобы вычислять первую производную в базе данных, вычисляйте её на устройстве! Между двух известных моментов времени вычислите объём заряда батареи, который был исчерпан за этот период. Для этой метрики есть две идеальных единицы измерения: изменение в процентах или амперах, если используется топливный датчик.
Я также настоятельно рекомендую стандартизировать протяжённость интервала, чтобы ещё больше упростить вычисления. Для понимания, насколько простыми они могут получиться, мы ещё раз пройдёмся по нашим четырём устройствам. Заметьте, что жирным выделены повышенные проценты SoC.
Устройство А | Устройство В | Устройство С | Устройство D |
- | - | - | - |
-3% | отсутствует | -3% | отсутствует |
-5% | отсутствует | -4% | 6% |
-33% | -2% | 15% | -3% |
44% | 2% | -3% | -2% |
Если все эти показания снимались в течение интервала длительностью 1 час (например, устройство А исчерпало 3% батареи за первый час), тогда можно просто сложить все те, в которых повышения SoC не наблюдалось. Таким образом, в среднем мы получим потребление примерно 6% заряда в час.
Всё настолько просто. Ту же логику и метод можно применить, если в устройстве используется топливный датчик. Зарегистрируйте количество кулоновских отсчётов в час, вычислите среднее, и вы узнаете, сколько тока потребляется за это время.
Вот простой фрагмент кода, представляющий потенциальную первую версию моей прошивки на Си.
static void prv_device_metrics_flush_callback(bool is_flushing) {
static int32_t s_prev_battery_pct;
if (is_flushing) {
// Конец интервала пульса
const int32_t current_battery_pct = battery_get_pct();
const int32_t battery_delta = current_battery_pct - s_prev_battery_pct;
device_metrics_set(kDeviceMetricId_BatteryLifeDrain, battery_delta);
} else {
// Начало интервала пульса
s_prev_battery_pct = battery_get_pct();
}
}
Эту стратегию, которая прекрасно работала у нас в Pebble, можно применить как к одному устройству, так и к миллионному парку. Мне в этом методе больше всего нравится то, что при наличии дельты и продолжительности во времени, становится легко вычислить ожидаемый срок работы батареи.
В ходе внутреннего тестирования мы могли определить этот срок довольно точно и всего за 1-2 дня, если часы носили все сотрудники компании (24 часа * 100 человек = 2,400 точек данных при измерении показаний батареи каждый час).
Заметьте, что регистрировать нужно SoC и дельту SoC. Первое пригодится для обработки данных отдельных устройств, а второе для агрегирования информации по всему парку.
▍ Не регистрируйте пульс устройства в случае зарядки батареи
Обратите внимание, что в таблице из предыдущего раздела были случаи, когда показания SoC % некоторых устройств возрастали (выделены жирным). Объясняется это тем, что в те интервалы к устройствам была подключена зарядка. Мы также проигнорировали эти показания при вычислении среднего потребления энергии. Это было важно, поскольку мы хотим суммировать только те интервалы, в которые устройство работает нормально и питается от батареи.
Вместо того, чтобы игнорировать эти показания на сервере, я советую отбрасывать метрики и вообще их не отправлять. Либо каким-то образом обозначать метрики дельт SoC, которые были получены при подключённой зарядке. Тогда мастер SQL легко сможет проигнорировать эти события в финальных вычислениях.
Здесь стоит отметить, что отбрасывание нескольких точек данных в конечном итоге не имеет большого значения. Когда тысячи устройств регистрируют данные каждый час, несколько отброшенных часов не повлияют значительно на средние значения.
Более проработанный фрагмент кода, игнорирующий события заряда батареи, можно найти в документации Memfault.
Сравнение длительности работы батареи среди разных версий ПО
Большинство производителей электроники знают количество выпущенных ими устройств. Обычно они разрабатываются внутри компании и имеют всего пару ревизий. Если на устройстве была установлена одна прошивка, которая никогда не обновлялась, то оно наверняка будет в среднем потреблять изо дня в день одинаковое количество энергии на протяжении всего срока службы. Это одно из хороших качеств прошивки.
Но интернет вещей (IoT, Internet of Things) работает иначе. Программное обеспечение IoT-устройств постоянно обновляется. ПО — это то, что делает современные компании уникальными и ценными, поэтому его обновление является жизненно важным. Тем не менее такие обновления зачастую влекут за собой определённую регрессию устройств и могут внести реальные проблемы. Из своего опыта могу сказать, что мы вносили бесчисленное множество ухудшений в выпускаемые нами проекты.
При отправке метрик обязательно сопроводите каждую версией прошивки, для которой она собиралась (как уже говорилось о метриках отслеживания пакетов пульса выше). Версия встроенного ПО должна выступать основным подтекстом для определения того, увеличивается или уменьшается время жизни батареи.
Одним из самых острых моментов для производителя электроники является выпуск очередной прошивки, поскольку она может закирпичить тысячи устройств или значительно сократить длительность работы батареи. Чтобы компенсировать эти риски, нужно собирать данные на всех стадиях релиза и постоянно их анализировать. Имея даже всего пару тысяч выборок, вы сможете принимать основанные на данных решения и минимизировать число изматывающих деплоев.
Лучшие практики
В течение где-то десяти последних лет я занимался разработкой прошивок и общался с очень многими инженерами из той же сферы. На основе этого опыта я приведу несколько лучших практик, которые рекомендую внедрить любой команде разработчиков.
▍ Не предполагайте, что ПО, работавшее для 1-100 устройств, будет также работать для парков из 10К+ устройств
Я и мои коллеги из Memfault общались с огромным числом разработчиков. Все они, как и мы, сходились к одинаковому видению, что, когда количество устройств начинает выходить за тысячи, используемые в них изначально системы данных начинают ломаться или становятся запредельно дорогостоящими.
Вот несколько типичных методик, с которыми я часто сталкивался в прошлом, и которые терпели неудачу.
- Генерация метрик из логов: очень легко попасть в эту ловушку, потому что кажется, что здесь нет ничего сложного. Команды в самом начале проектов внедряют логи, отправляют их в S3, а затем начинают создавать скрипты для их парсинга. Тем не менее при выходе за определённый количественный порог устройств это становится большой проблемой, и хрупкая природа логов сильно усложняет использование и обслуживание таких систем. Генерируйте метрики на устройстве.
- Использование Grafana для агрегирования данных по всему парку: Prometheus, StatsD, Grafana и аналогичные инструменты не предназначены для мониторинга огромных количеств устройств. Напротив, они оптимизированы для обработки нескольких серверов и сервисов, отслеживающих метрики здоровья, отправляемые каждые несколько секунд. Они спроектированы для отслеживания сущностей в реальном времени, а не предоставления обширных исторических запросов по множеству измерений, которые необходимы для полноценного понимания продолжительности жизни батареи. Подумайте дважды, прежде чем решить, что Grafana окажется универсальным решением для мониторинга ваших устройств.
- Отправка случайных метрик, которые вы планируете оценить позже: я видел такой подход неоднократно. Если метрика не отслеживает что-то полезное или не имеет отчётливого общего знаменателя, относительно которого можно было бы выполнять агрегирование, она не станет волшебным образом полезной и должна быть исключена. Это «мусор на входе — мусор на выходе» (GIGO; garbage in, garbage out). Именно поэтому я настоятельно рекомендую внедрять в проекты паттерны метрик отслеживания пульса устройств. Они невероятно хорошо сработали для меня в прошлом и имеют хорошую защиту от дурака, ограждая вас от проблем, возникающих в мире встроенного ПО.
▍ Реализуйте мониторинг в начале проекта
Когда-то я считал, что передача информации по воздуху (OTA, over-the-air) и мониторинг являются последними элементами, которые нужно наладить, прежде чем отправлять устройство в продакшен. Теперь же я знаю, что этот подход в корне ошибочен.
Сначала нужно наладить работу устройства на минимальном уровне, затем уже реализовывать OTA, потом создавать конвейер мониторинга и, наконец, начинать работать над реальной функциональностью, которую устройство должно поддерживать.
Именно по такой схеме мы действовали в Pebble, и результат был невероятным. Для каждых новых часов, разработанных после их первого поколения, выполнялась подготовка, собирались логи, метрики, дампы ядра, после чего на эту базу уже накладывалась основная функциональность. В течение первых месяцев разработки нового устройства наша продуктивность была на высоте!
И, естественно, мы постоянно отправляли метрики состояния батареи. Если во время внутреннего тестирования батарея быстро разряжалась, я отправлял тикет в поддержку и собирал данные, помогая исправить этот баг.
Если бы мы не налаживали стек мониторинга изначально, а делали это перед самой стадией продакшена, вряд ли мы бы успевали поставить продукт вовремя и наверняка были бы вынуждены урезать множество функций.
▍ Активно выполняйте внутреннее тестирование
Закладывайте в набор данных как можно больше отчётов. Сделайте так, чтобы люди использовали свои устройства активно, и это, как минимум, будет аналогично их использованию вашими клиентами.
При этом в прежних компаниях мы основательно полагались на использование групп бета-тестеров. В Pebble у нас по всему миру были поклонники, которые с радостью помогали тестировать новейшие прошивки, даже если те оказывались менее стабильны и зачастую сокращали длительность работы батареи.
▍ Упаковывайте и отправляйте прошивку как можно быстрее
В Pebble у нас была очень хорошо налажена схема отправки прошивок. Каждые несколько дней мы рассылали их нашим сотрудникам внутри компании, а раз в пару недель отправляли нашим клиентам. Самое большое преимущество такой частой поставки ПО в том, что каждый новый релиз, загруженный в часы сотрудника компании или клиента, имел небольшое количество изменений или коммитов.
Если одна из внутренних сборок вдруг вела к значительной регрессии батареи, нам приходилось просмотреть всего 10-20 коммитов, чтобы понять в каком из них скрывалась проблема. Если регрессию вызывала клиентская сборка, нам приходилось пройти командой git bisect примерно 100 коммитов. Это было больно, но вполне выполнимо.
Реальная проблема возникала в случае поставки прошивки раз в 3-6 месяцев. За это время у вас накапливаются сотни, если не тысячи, коммитов, которые могут вызывать регрессию в различных подсистемах. И к этому моменту практически однозначно на ресурс батареи уже будет влиять не одна проблема.
Обновление прошивки является благословением, которое также может обернуться проклятьем. При использовании правильных инструментов и сбора данных частая поставка обновлений станет именно благословением, которое позволит вам быстро находить и исправлять проблемы.
Использование Memfault в качестве стека мониторинга
В Memfault все наши сотрудники напряжённо думали над тем, как лучше мониторить жизнь батареи, и мы создали продукт, который были бы рады использовать в прошлых компаниях. Memfault может работать на всевозможных встроенных системах и для всех типов топологий сети, будь то домашние или стандартизированные вроде WiFi или Bluetooth.
Если вы хотите подробнее узнать о том, как можно инструментировать жизнь батареи с помощью Memfault, рекомендую почитать страницу документации, Tracking Battery Life with Memfault.
Заключение
Мир был бы лучше, если бы все электронные устройства питались от обычных розеток, но с каждым днём мы всё дальше уходим от этого метода. Хотя лично меня, как потребителя, это радует. Пылесося пол в доме, я могу свободно танцевать и прыгать через диваны, благодаря своему беспроводному Dyson и Bluetooth-наушникам. И я знаю, что firmware-инженеры в этих IoT-компаниях усиленно трудятся, чтобы обеспечить надёжность своих устройств и обеспечить длительную жизнь их батарей.
Надеюсь, эта статья помогла вам понять, какие шаги необходимы для создания и поставки прекрасного автономного устройства, или что вы узнали какие-то новые нюансы, которые сможете привнести в вашу команду для улучшения работы батареи в разрабатываемом продукте.
Автор: Дмитрий Брайт