Table of Contents
Общие принципы работы SuperVOOC
Ток
SuperVOOC отличается от других протоколов зарядки тем, что увеличивает скорость зарядки не за счёт повышения напряжения, а за счёт увеличения тока. Увеличение тока требует качественного кабеля, поэтому SuperVOOC использует собственные кабели со встроенным чипом, который подтвержает телефону и зарядке готовность пропускать большие токи. Компании Oneplus/Oppo/Realme выпустили больше количество версий кабелей, у части имеется маркировка на манжете USB A разъема с указанием допустимого тока, а у других присутствует только ревизия - одна буква или вообще отсутствует маркировка. Несмотря на то, что сейчас прикладываются 10-12A кабели, никто не наблюдал потребление больше 8A.
Напряжение
За счет повышения тока SuperVOOCу не требуется регулятор напряжения, поэтому на выходе зарядки напряжение совпадает с напряжением, которое требуется аккумулятору. У флагманов была сделана еще одна доработка: двойная батарея, у которой каждая часть может заряжаться независимо, удваивая скорость. За счёт этого на телефон подается буквально удвоенное напряжение.
Используемые инструменты
Для измерения протокола SuperVOOC я использую:
- USB-тестер ChargerLab KM003C. Он умеет определять и пропускать SuperVOOC. Дальше его показания будут считаться объективными данными, снимаемыми с зарядки. Из тестера берется два параметра:
- Ток зарядки
- Напряжение зарядки
- Внутренний лог телефона, который я получаю на десктоп через поднятый по сети adb с помощью команды adb logcat. Из лога можно извлечь несколько категорий записей.
- Записи healthd. Это встроенный в Android менеджер аккумулятора, который логгирует процесс зарядки. Важно, что этот уровень использует низкоуровневый сервис от вендора, поэтому он видит несколько приукрашенную картинку. Например, он получает напряжение, приведенное к одной ячейке, видимо среднее значение от напряжения двух ячеек. В этом логе есть следующие параметры:
- Уровень зарядки l
- напряжение в mv v
- Температура t
- enum с здоровьем аккумулятора (здоров/убит) h
- emum со статусом аккумулятора (заряжается/разряжается) st
- ток аккумулятора как ток потребления - ток зарядки . Отрицательное значение соответствует зарядке. с
- максимальное значение заряженности в микро(!)ампер-часа. На самом деле похоже на константу fc
- число полных циклов зарядки за всё время жизни аккумулятора cc
- однобуквенный статус зарядки (проводная зарядка/usb-порт/беспроводная зарядка) chg
- Записи charge_time от сервиса vendor.oplus.hardware.charger-V7-service. Он знает истинную картину зарядки, разделяет зарядку по фазам SuperVOOC и CDP/DCP (стандартные USB 5V2A), а также ведет двойную бухгалтерию процентов заряженности soc (честный state of charge) и ui_soc (то, что отдается в healthd) и такую же двойную бугалтерию по времени до завершения зарядки (time to full charge): ttf и ui_ttf.
- У сервиса vendor.oplus.hardware.charger-V7-service есть еще записи типа read content, но их содержимое пока не расшифровано
Наличие нескольких источников разной степени доверия приводят к тому, что данные нужно сопоставлять между собой и становятся видны допустимые неточности в замерах и отметках времени. Так, при сопоставлении времен logcat и тестера приходилось сдвигать показания на секунды, после чего оказывалось, что точность отметок плывет.
Общие наблюдения за процессом зарядки
Процесс зарядки можно разделить на нескольк фаз. Начальную фазу, когда идёт согласование протокола можно игнорировать, она длится буквально пару секунд и в логе тип зарядки определяется как cdp/dcp. Вторая фаза самая важная - это собственно SuperVOOC. Она длится 33-40 минут до примерно 97-98% заряда по ui_soc, что соответствует 95-96% честного soc. Третья фаза - это опять cdp/dcp на 5V. Это очень сомнительная фаза, потому что в это время пользовательский интерфейс будет писать 100% заряда и продолжать заряжать до написания Full charge. По логам есть три точки “завершения”. Лог charge_time перестаёт следить за процессом когда ui_soc достигает 100%. Но зарядка продолжается. Где-то через минуту измененяется статус зарядки с 2 (BATTERY_STATUS_CHARGING) на 5 (BATTERY_STATUS_FULL). А еще через 2.5 минуты статус меняется на 3 (BATTERY_STATUS_DISCHARGING) и вот это уже точно всё. Но все эти события происходят на 40+ минут, что не так красиво как рекламировать 36 минут. Дальше мы будем говорить только про основную фазу svooc.
Сравнение графиков напряжения
Начнём с изучения графика напряжений. У нас есть напряжение, которое создаёт зарядка и напряжение на контактах аккумуляторной батареи. В логах charge_time нет напряжения, будем брать его из логов healthd. Мы помним, что healthd обманывают, подсовывая ему напряжение в пересчете на одну ячейку из двух. Поэтому кроме графика напряжения зарядки добавим на график еще одну линию: половину напряжения на зарядке.И становится видно, что в фазе svooc зарядное устройство буквально следует за напряжением на аккумуляторе. Это сильно отличается от линейных графиков Power Delivery. В реальности зарядка скорее всего отстаёт от напряжения, но пока непонятно насколько именно.
Фаза cdp/dcp малоинтересна. Подаём 5 вольт, аккумулятор показывает 4.4-4.5 вольт, причём после ухода с svooc напряжение слегка снижается, потому что аккумулятор перестали пинать.
Переключение фаз выглядит вот так:
09:31:57.224 2145 2145 D healthd : system healthd: battery l=98 v=4576 t=34.6 h=2 st=2 c=-1848 fc=5920000 cc=93 chg=a 09:31:57.407 2145 2145 D healthd : system healthd: battery l=98 v=4574 t=34.5 h=2 st=2 c=-1838 fc=5920000 cc=93 chg=a 09:31:57.791 2145 2145 D healthd : system healthd: battery l=98 v=4574 t=34.5 h=2 st=2 c=-1417 fc=5920000 cc=93 chg=a 09:31:57.900 2145 2145 D healthd : system healthd: battery l=98 v=4574 t=34.5 h=2 st=2 c=-1417 fc=5920000 cc=93 chg=a 09:32:02.529 2145 2145 D healthd : system healthd: battery l=98 v=4483 t=34.5 h=2 st=2 c=0 fc=5920000 cc=93 chg=a 09:32:07.649 2145 2145 D healthd : system healthd: battery l=98 v=4474 t=34.4 h=2 st=2 c=0 fc=5920000 cc=93 chg=a 09:32:11.438 2145 2145 D healthd : system healthd: battery l=98 v=4474 t=34.4 h=2 st=2 c=0 fc=5920000 cc=93 chg=a 09:32:12.774 2145 2145 D healthd : system healthd: battery l=98 v=4467 t=34.4 h=2 st=2 c=-20 fc=5920000 cc=93 chg=a 09:32:17.891 2145 2145 D healthd : system healthd: battery l=98 v=4491 t=34.4 h=2 st=2 c=-557 fc=5920000 cc=93 chg=a 09:32:23.008 2145 2145 D healthd : system healthd: battery l=98 v=4491 t=34.3 h=2 st=2 c=-558 fc=5920000 cc=93 chg=a 09:32:28.128 2145 2145 D healthd : system healthd: battery l=98 v=4491 t=34.3 h=2 st=2 c=-559 fc=5920000 cc=93 chg=a 09:32:33.256 2145 2145 D healthd : system healthd: battery l=98 v=4490 t=34.3 h=2 st=2 c=-559 fc=5920000 cc=93 chg=a
Резюмируем: напряжение в фазе svooc просто следует за суммарным напряжением батареи.
Ток зарядки
Сравнение токов зарядки и аккумулятора осложнено тем, что с аккумулятора снимается ток с учётом тока потребления. И в целом график это подтвержает тем, что графики совпадают с точностью до провалов на аккумуляторе, которые вызваны активностью телефона.
Видна попытка взять 7 ампер, но это длится буквально секунду. Что не сложилось - неизвестно. Температура, наличие тестера на линии или еще что-то. Дальше видно, что протокол долго сидит на 5A и потом снижает ток ступеньками, причём ступеньки в основном равны 1А и немного 0.5А.
Фаза cdp невнятная: берем 1.1-1.2A c зарядки, до аккумулятора доходит 3.5А. Возможно это потери на преобразовании 5V в 4.6V аккумулятора.
State of Charge
Уровень заряженности устройства в процентах - это простая конструкция с точки зрения пользователя, но имеющая свои тонкости под капотом. Скорее всего уровень является нелинейной (или линейной, но по-разному на разных регионах) функцией от напряжения аккумулятора. Лог charge_time вносит еще один уровень косвенности - честный soc и нечестный уровень наружу ui_soc. Разница между ними в reserve_soc=2 на 100%. То есть ui_soc = soc * (100/(100-reserve_soc)). Если еще вспомнить, что charge_time ориентируется на ui_soc, то смысл вычисления честного soc вообще неясен. Возможно, что после получения 100% в ui_soc проценты зарядки перестают обновляться, но статус BATTERY_STATUS_CHARGING сменяется после достижения 100% в честном soc. Но, поскольку этого нет в логах, это всего лишь гипотеза. Будем считать, что эти 2% увеличивают жизнь аккумулятора.
Time to full charge (ttf)
Еще один элемент двойной бухгалтерии - это время до полной зарядки, которое существует в двух переменных: честном ttf и “для интерфейсов” ui_ttf. Почему их два можно догадаться: честный ttf может резко меняться, когда зарядка изменяет силу тока, а ui_ttf меняется консервативнее, единичные выбросы сглаживаются. Вот несколько примеров значений
# самое начало, до переключения в svooc. 08:57:52.598 2337 7247 D charge_time: type=cdp/dcp,reserve_soc=2,soc=4,ui_soc=4,current=-226,avg=1100,ttf=9080(02:31:20),ui_ttf=9080(02:31:20) # только переключились в svooc, оба времени оптимистично уменьшились 08:57:54.599 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=4,ui_soc=4,current=-330,avg=2000,ttf=4648(01:17:28),ui_ttf=4648(01:17:28) # а вот участок, на котором видно, что честное ttf снизилось до реальных значений, а ui_ttf продолжает считать по-старому 08:58:35.647 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=5,ui_soc=5,current=5078,avg=2522,ttf=3690(01:01:30),ui_ttf=4886(01:21:26) 08:58:36.647 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=5,ui_soc=5,current=5078,avg=3164,ttf=3017(00:50:17),ui_ttf=4885(01:21:25) 08:58:37.648 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=5,ui_soc=5,current=5078,avg=3802,ttf=2616(00:43:36),ui_ttf=4884(01:21:24) 08:58:38.649 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=5,ui_soc=5,current=6916,avg=4807,ttf=2253(00:37:33),ui_ttf=4883(01:21:23) # и только через пару минут значения выравниваются 09:00:14.754 2337 7247 D charge_time: type=svooc,reserve_soc=2,soc=10,ui_soc=10,current=4889,avg=4875,ttf=2128(00:35:28),ui_ttf=2128(00:35:28) # и последний пример, где в завершающей фазе честный ttf начинает выдавать пессимистичные значения, # а ui_ttf продолжает считать по-старому. В результате ui_ttf накидывает только 3 минуты, вместо десяти 09:33:48.634 2337 7247 D charge_time: type=cdp/dcp,reserve_soc=2,soc=96,ui_soc=98,current=140,avg=224,ttf=792(00:13:12),ui_ttf=213(00:03:33) 09:33:49.635 2337 7247 D charge_time: type=cdp/dcp,reserve_soc=2,soc=96,ui_soc=98,current=140,avg=140,ttf=1327(00:22:07),ui_ttf=212(00:03:32) 09:33:50.635 2337 7247 D charge_time: type=cdp/dcp,reserve_soc=2,soc=96,ui_soc=98,current=211,avg=154,ttf=1196(00:19:56),ui_ttf=211(00:03:31)
