Pull to refresh

Заряжаем ноутбук Dell XPS от любого адаптера питания

Reading time 8 min
Views 118K
image

Не так давно я решил произвести обновление своего ноутбука и приобрёл на Ebay Dell XPS 13 9350. Цена вышла очень приятная (в 2 раза дешевле, чем в отечественных магазинах, отлично проходило в лимит 1000 евро, при этом комплектация максимальная, а состояние «New»). Ноутбук мне очень понравился (стоит ли говорить — туда отлично встал Linux без каких-либо танцев с бубном кроме перевода SSD из режима RAID в режим AHCI одной галкой в UEFI). И я даже отлично попользовался им 2 недели, а потом… а потом блок питания ноутбука перестал работать.

Конечно, я немного огорчился, но блок питания вещь не такая уж дорогая (как относительно стоимости ноутбука, так и относительно выгоды от заказа на ebay), а пытаться что-то выяснять с продавцом из-за такого пустяка — лишняя трата времени, так что я отправился в местный компьютерный магазин. Тут меня ждало первое разочарование — с подходящим штекером БП не нашлось. Я отправился в следующий магазин, но и там меня постигла неудача. В таком случае я рассудил, что можно позаимствовать штекер и кусочек провода от неисправного БП и сделать переходник, поэтому приобрёл произвольный БП с подходящей мощностью и выходным напряжением, а также совместимый с ним штекер (не резать же провод у нового БП).

Однако всё было не так просто…

Когда я вернулся домой, меня ждало второе разочарование — после разреза провода оригинального БП оказалось, что там целых 3 жилы (2 «экрана» и центральный провод). У меня не осталось выбора — я распилил оригинальный БП (его конструкция такова, что альтернатив не особо то было). Исходя из обозначений на его печатной плате выяснилось, что внешний «экран» это GND, внутренний «экран» это VOUT (то есть 19 вольт), а центральный провод — ID.

Для начала я подключил GND и VOUT кабеля соответствующим образом к новому БП, а ID пин остался висеть в воздухе. Ноутбук увидел блок питания и перешёл на внешнее питание, однако при загрузке выдал предупреждение, что адаптер питания какой-то непонятный и батарея «может не заряжаться». Обычно на практике такая фраза означает, что она не «может», а обязательно не будет заряжаться. Так и вышло.

image

Разумеется, мириться с подобной ситуацией я не собирался. Самый очевидный вариант — купить оригинальный адаптер Dell. Однако, во-первых, это ожидание доставки (в моём городе таких нет), во-вторых, дополнительные финансовые затраты (я уже купил один блок питания, а оригинальный стоит ещё и дороже в 2 раза), в-третьих, приобретённого адаптера вполне достаточно для полноценной работы ноутбука (он даже немного мощнее), зачем его менять. В то же время можно освежить свои знания микроконтроллеров и получить полезный опыт.

Первое куда я отправился — был Google. По запросу «dell power adapter id» я нашёл статью. В принципе, на этом можно было остановиться, однако, во-первых, мой ноутбук более новый и даже другой линейки, так что потенциально Dell мог что-то изменить, а, во-вторых, автор использовал MSP430, которого опять же нет в моём городе и надо заказывать и ждать.

Для начал я произвёл первый эксперимент — соединил GND и ID пины старого адаптера с соответствующими линиями кабеля (при этом питание по-прежнему поступало от нового), а затем подключил его к ноутбуку. Эксперимент удался — ноутбук распознал адаптер как совместимый и начал заряжаться. Таким образом я получил возможность заряжать аккумулятор, пока не найду более подходящее решение. При этом определение параметров адаптера происходит лишь в момент подключения, после этого плату старого адаптера можно отключить.

Из статьи следует, что в адаптере питания установлена микросхема с интерфейсом 1wire, что отлично соотносится с количеством линий, используемых для идентификации. К счастью, у меня имеется Bus Pirate, который позволяет удобно общаться с устройствами в том числе по этому протоколу. Поскольку, земли USB и адаптера питания соединены, когда последний подключен, мне осталось лишь подключить линию ID к пину MOSI BusPirate (именно он используется в режиме 1wire). Кстати, ещё я приметил, что ноутбук подтягивает линию ID к 3.3В, что потом повлияло на выбор напряжения питания микроконтроллера-эмулятора.

image

Открываем любую программу для работы с последовательным портом (BusPirate отображается в системе именно как он) и вводим команду «m 2» для переключения в режим 1wire, а затем выполняем команду "[ 0x33 r:8". Данная команда реализует сброс шины, отправляет байт 0x33 (считать адрес единственного устройства на шине), а затем принимает 8 байт.

В результате я получил: 0x09 0x52 0x8D 0xED 0x65 0x00 0x00 0xEF, что соответствует 1wire EEPROM на 1024 бит (128 байт), исходя из первого байта адреса, который определяет семейство. Это может быть, например, DS2502 (такое же предположение сделал и автор статьи выше, что показывает, что мы на верном пути).

Открываем даташит (или читаем англоязычную статью внимательнее) и узнаём, что для чтения используется команда 0xF0, за которой следует 2 байта смещения (сначала младший байт, затем старший). Пробуем эту команду на нашем подопытном: "[ 0xCC 0xF0 0x00 x00 r:130". 0xCC перед командой означает «игнорировать адрес» и позволяет не указывать адрес устройства (тогда бы надо было отправить байт 0x55 и за ним 8 байт адреса), если оно одно на шине. Ответом является последовательность из 130 байт:

0x8D
0x44 0x45 0x4C 0x4C 0x30 0x30 0x41 0x43 0x30 0x34 0x35 0x31 0x39 0x35 0x30 0x32
0x33 0x43 0x4E 0x30 0x43 0x44 0x46 0x35 0x37 0x37 0x32 0x34 0x33 0x38 0x36 0x35
0x51 0x32 0x37 0x46 0x32 0x41 0x30 0x35 0x3D 0x94 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF 0xFF
0xCA


Первый байт — CRC-8 от 3 байт команды, затем следует 128 байт данных из EEPROM, последний байт — CRC-8 от данных EEPROM. Можно воспользоваться любой утилитой проверки CRC-8, чтобы убедиться, что она верная. Это окончательно доказывает, что мы верно определили требуемый способ взаимодействия с адаптером питания.

Этот массив байт станет гораздо понятнее, если трактовать байты в нём как ASCII коды (последующие 0xFF являются пустыми ячейками EEPROM и неинтересны нам).

"DELL00AC045195023CN0CDF577243865Q27F2A05=\x94"


Назначение большинства байт становится очевидно, если соотнести их с шильдиком на БП, проблема возникла лишь с последними двумя байтами, однако после некоторых исследований (спасибо plm за предоставленные дампы других БП) я выяснил, что 2 байта после серийного номера — CRC-16/ARC от всех предыдущих байт.

Таким образом, формат описания БП имеет вид:

Смещение Размер Содержимое Описание
0 4 DELL Метка производителя
4 4 00AC Тип адаптера (AC — адаптер переменного тока, что в этом поле отдают аккумуляторные адаптеры, мне неизвестно)
8 3 045 Мощность в ваттах (45)
11 3 195 Напряжение в десятых долях вольта (19.5В)
14 3 023 Ток в десятых долях ампера (2.3А)
17 23 CN0CDF577243865Q27F2A05 Серийный номер
40 2 0x3D 0x94 Контрольная сумма CRC-16/ARC (сначала младший байт, затем старший) первых 40 байт


Теперь у нас имеется 2 варианта действий. Можно купить готовую микросхему 1wire eeprom (ту же самую DS2502), либо выпаять имеющуюся из адаптера питания. На самом деле это предпочтительный вариант, ибо он гарантированно сработает, к тому же обладает минимальной трудоёмкостью и максимальной компактностью (можно легко уместить всё в штекер питания). Однако я пошёл по более сложному пути. Выпаивать микросхему из БП мне не хотелось, потому что я боялся её повредить и вообще лишиться возможности заряжать аккумулятор. Приобретать новую — опять же ждать доставки, пусть даже несколько дней.

Поэтому я пошёл по тому же пути, что и автор статьи с hackaday — я реализовал 1wire slave на базе микроконтроллера. Правда, взял более распространённый и компактный ATTINY85. Заработала моя прошивка не сразу, пришлось потратить какое-то время на отладку (BusPirate очень помог тем, что я мог эмулировать запросы ноутбука с его помощью), но в результате получилось как-то так — github.com/KivApple/dell-charger-emulator. Объём кода вышел небольшой — 1660 байт ПЗУ и 22 байта ОЗУ, поэтому можно использовать другие МК той же серии — ATTINY45 или ATTIN25, только подредактировать параметр -mmcu в Makefile. Использование других микроконтроллеров может потребовать модификации исходного кода.

При прошивке следует настроить фьюзы на использование внутреннего RC-генератора на 8 МГц без делителя. При желании можно также подключить внешний кварцевый резонатор на 8 МГц (потребуется изменить фьюзы соответствующим образом), но лично у меня всё работает и без него.

image

ID линию штекера следует подключить к пину PB2 (именно он обладает функционалом внешних прерываний на ATTINY85), земли соединить. Сначала я попробовал использовать паразитное питание, но несмотря на применение режима энергосбережения, его недостаточно, поэтому нужно внешнее. 19В явно многовато для AVR, поэтому его нужно понизить (до 3.3В, потому что ноутбук ожидает именно такие уровни). Поскольку энергопотребление очень мало (1 мА большую часть времени, 3 мА в течении нескольких миллисекунд в моменты запроса, оценка очень грубая по даташиту на МК, в реальности скорее всего ещё меньше), можно ограничиться линейный стабилизатором. Я применил 78L33. При этом я не ставил стабилизирующие конденсаторы на питание для увеличения компактности, однако в случае проблем рекомендую их поставить.

image

К сожалению, результат так и не поместился в корпус штекера, поэтому получился не очень презентабельный (но за счёт большого количества слоёв синей изоленты достаточно жёсткий, чтобы минимизировать вероятность выхода из строя из-за механических повреждений).

image

Ноутбук подвоха не заметил и радостно начал заряжаться, рапортуя о 45 ваттном источнике питания (каковым был стандартный). Я попытался изменить отдаваемые параметры на 65 ватт, 3.5 ампера, исходя из реальных параметров нового БП, но мне это не удалось — ноутбук перестал определять зарядник как оригинальный. То ли имеется какой-то белый список параметров питания, то ли я не подправил какую-то дополнительную контрольную сумму. Впрочем, моя задача в любом случае была решена.

При разработке прошивки я активно использовал вот эту статью про 1wire. На мой взгляд, в ней всё описано достаточно просто и подробно.

И напоследок несколько предупреждений:

1. Чисто теоретически подобные манипуляции могут привести к выходу ноутбука из строя или хотя бы лишению гарантии (с другой стороны, откуда производитель узнает о новом БП, если не писать статью об этом на гиктаймс и отдать им старый?). На практике я по собственной глупости подал 19В на линию ID. Ничего не произошло. Совсем ничего (ноутбук даже не выключился аварийно, как бывает при КЗ на USB). Но вам лучше не повторять моих ошибок и быть более аккуратными.

2. Я бы не советовал подключать адаптер питания с меньшей мощностью, чем указано в содержимом EEPROM. Вероятность повредить ноутбук мала, но вот адаптер, если превышения мощности не хватит для срабатывания защиты сразу, будет медленно перегреваться, пока не выйдет из строя (а тут уже всякое может быть). Адаптер должен быть такой же по характеристикам, либо мощнее (выходное напряжение же ОБЯЗАТЕЛЬНО должно совпадать с оригинальным, либо отличаться не более, чем на 0.5В, причём лучше в меньшую сторону, чем в большую).

3. После замены БП убедитесь, что ноутбук таки нормально заряжается. Если нет, то возможно два варианта — либо обман механизма идентификации БП не сработал (но это будет видно и в BIOS), либо нужно было округлять напряжение не в меньшую сторону (19В), а в большую (20В). Если не обратить на это внимание, то аккумулятор может продолжить медленно разряжаться и выйти из строя.


Также было бы интересно услышать рекомендации по оптимизации моего кода и идеи, что же могут означать остальные байты в EEPROM. Сам я подумываю о том, чтобы когда-нибудь переделать всю схему на маленькой печатной плате и SMD-компонентах, чтобы она таки умещалась внутри штекера.

UPD: Обновил проект на GitHub. Теперь данные адаптера хранятся в EEPROM микроконтроллера и могут быть перезаписаны без перезаписи основной программы. Также они могут быть перезаписаны без программатора по протоколу 1wire (разумеется, предварительно вам нужно загрузить прошивку с помощью программатора). Перезапись осуществляется по одному байту. Нужно отправить последовательность 0xCC 0x0F <смещение> 0x00 <байт данных>. После этого следует подождать какое-то время (миллисекунды точно хватит) и не посылать никаких команд. Если же вы забудете записать что-либо в EEPROM микроконтроллера (и он изначально будет совсем пустой), то программа при первом запуске запишет туда данные моего адаптера питания на 45 ватт.

Наконец, мною была написана интерактивная консольная утилита dell-charger-data-editor.py. Эта утилита позволяет редактировать файл eeprom-data.hex (разумеется, вы можете редактировать его в любом редакторе, поддерживающим формат Intel Hex, но данная утилита автоматически выделяет нужные поля, а также пересчитывает контрольную сумму при сохранении). Также эта утилита умеет считывать как оригинальные EEPROM, так и эмулированные, а также перезаписывать эмулированные (для перезаписи DS2502 требуется подача на 480 мкс импульса 12В после каждой команды записи, что требует сложной схемотехники, к тому же это категорически нельзя делать при использовании ATTINY). При этом всё, что вам нужно — любой USB-UART преобразователь (он должен использовать логические уровни 3.3В или 5В, 12В повредят EEPROM) и один диод (подробности подключения см. в README.md).
Tags:
Hubs:
+101
Comments 205
Comments Comments 205

Articles