Реализация USB-интерфейса ИБП на основе ARM-платы MC HCK

  • Tutorial
Возникла задача сделать USB-устройство, которое, будучи вставленным в NAS, воспринималось бы им как USB-линк к источнику бесперебойного питания (именно через такое USB-соединение NAS узнает от ИБП об исчезновении питания, разрядке батарей и т.д.).

1. Внутри USB


Для решения задачи важно понимать, как USB устроен и работает. Очень короткое и доходчивое введение для знающих английский язык называется USB in a NutShell (upd: есть перевод). Затем советую по возможности пролистать книгу "USB Complete".

После этого, если потребуется, уже можно что-то уточнять в спецификациях, изучать классы, знакомиться с USB 3.0 SuperSpeed и т.д., но я уверен, что текста USB in a Nutshell и хороших примеров достаточно, чтобы сделать свое первое экспериментальное устройство.

2. USB-протокол ИБП/хост


В моем NAS операционная система основана на Linux и для общения с ИБП использует Network UPS Tools (NUT).

Выбирем в исходных текстах NUT самый простой драйвер; на всякий случай проверим, что он есть в списке ИБП, поддерживаемых NAS.

Самым простым и коротким показался drivers/richcomm_usb.c для устройств какого-то китайского производителя. Если сравнить его со скелетом, то становится ясно, что протокол у китайцев максимально примитивен: это «сухие контакты» без каких-либо подробностей; даже не HID-устройство. Но нас это вполне устраивает.

Рассмотрим основную функцию общения с ИБП:

#define STATUS_REQUESTTYPE	0x21
#define REPLY_REQUESTTYPE	0x81
#define QUERY_PACKETSIZE	4
#define REPLY_PACKETSIZE	6

static int execute_and_retrieve_query(char *query, char *reply)
{
        . . .
	usb_control_msg(udev, STATUS_REQUESTTYPE, REQUEST_VALUE, MESSAGE_VALUE, 
                          INDEX_VALUE, query, QUERY_PACKETSIZE, 1000);
        . . .
	usb_interrupt_read(udev, REPLY_REQUESTTYPE, reply, REPLY_PACKETSIZE, 1000);
}


Видно, что при совершении запроса хост посылает устройству управляющий пакет плюс 4 байта, адресуя все это интерфейсу/классу (0x21; см. описание полей USB request). Устройство отвечает 6 байтами, которые отправляются в endpoint 1 (0x81; см. описание Endpoint Address).

Значения отсылаемых байт можно посмотреть в функции query_ups(), а смысл принятых байт — в функции upsdrv_updateinfo(). Если кратко, то мы отсылаем вместе с control message массив { 0x01, 0x00, 0x00, 0x30 }, а в принятом массиве смотрим на пару бит в нужном байте: они и сообщают статус питания (от сети/от батарей) и состояние батареи (заряжена/почти разряжена).

Отдельно отмечу: в качестве Vendor ID китайцы решили использовать 0x925 — число, которое они напрямую скопировали из примеров к упоминавшейся выше книге «USB Complete» Яна Аксельсона. Естественно, это плохое решение, потому что данный Vendor ID выдан Lakeview Research, компании Яна Аксельсона, и использовать его в своих проектах как минимум некорректно. Китайцы могли бы хотя бы почитать FAQ по проблеме USB VendorID/Product ID или послушать интересный доклад на эту же тему на Open Hardware Summit 2012.

Для того, чтобы наше устройство определилось драйверами Network UPS Tools, нам тоже придется использовать чужой Vendor ID/Product ID. Конкретно в данном случае (отсутствие массового производства, осознанная мимикрия и т.д.) ничего страшного в этом нет.

3. Железо


Итак, всей этой информации достаточно, чтобы начать программировать. В качестве платформы для реализации я решил попробовать плату MC HCK на микроконтроллере Freescale Kinetis K20: я заказывал несколько прототипов MC HCK в прошлом году. Мне понравилась идея недорогой ($5-7), но достаточно мощной платы для различных экспериментов, выполненная в удобном форм-факторе.



Кстати, нацеленная практически на эту же нишу, но гораздо более известная плата Teensy 3.1 использует аналогичный МК, но с большим объемом памяти.

Описание использованного контроллера можно найти здесь. Если кратко, то это очень недорогой ARM Cortex-M4 50Mhz с 32kb flash + 32kb data и различными прелестями, из которых нам наиболее актуальна аппаратная реализация USB. По минимуму для подключения процессора к USB требуется лишь несколько резисторов и конденсаторов.

4. Практическая реализация


Для разработки необходимо установить:

  1. Компилятор; я использовал GCC ARM embedded toolchain
  2. Сам SDK: MC HCK toolchain
  3. dfu-util для заливки прошивки

Сам SDK состоит из библиотек, облегчающих доступ к возможностям контроллера, бутлодера и примеров. Наверное, стоит сказать, что SDK еще не очень зрел (да и сам MC HCK пока в массы не вышел), но вполне может использоваться в различных проектах (например, внутри сенсоров окружающей среды с низким энергопотреблением). Библиотека работы с USB отличается практически полным отсутствием документации, но код чист и понятен, а существующих примеров достаточно.

Вспомним иерархию внутри любого USB-устройства:



Учитывая простоту нашего USB-протокола, основной объем исходного кода занимают дескрипторы USB-устройства, одной конфигурации, одного интерфейса и одного endpoint'a («одного» — потому что endpoint для управляющих пакетов создается по умолчанию и не зависит от нас). Названия полей выступают в роли комментариев.


static const struct usb_desc_dev_t device_dev_desc = {
        .bLength = sizeof(struct usb_desc_dev_t),
        .bDescriptorType = USB_DESC_DEV,
        .bcdUSB = { .maj = 2 },
        .bDeviceClass = USB_DEV_CLASS_SEE_IFACE,
        .bDeviceSubClass = USB_DEV_SUBCLASS_SEE_IFACE,
        .bDeviceProtocol = USB_DEV_PROTO_SEE_IFACE,
        .bMaxPacketSize0 = EP0_BUFSIZE,
        .idVendor = RCM_VENDOR,
        .idProduct = RCM_PRODUCT,
        .bcdDevice = { .sub = 1 },
        .iManufacturer = 1,
        .iProduct = 2,
        .iSerialNumber = 3,
        .bNumConfigurations = 1,
}

static const struct usb_config_1 usb_config_1 = {
        .config = {
                .bLength = sizeof(struct usb_desc_config_t),
                .bDescriptorType = USB_DESC_CONFIG,
                .wTotalLength = sizeof(struct usb_config_1),
                .bNumInterfaces = 1,
                .bConfigurationValue = 1,
                .iConfiguration = 0, 
                .one = 1,
                .bMaxPower = 10
        },
        .usb_function_0 = {
                .iface = {
                        .bLength = sizeof(struct usb_desc_iface_t),
                        .bDescriptorType = USB_DESC_IFACE,
                        .bInterfaceNumber = 0, 
                        .bAlternateSetting = 0, 
                        .bNumEndpoints = 1,  
                        .iInterface = 0, 
                        .bInterfaceClass = RCM_CLASS,
                        .bInterfaceSubClass = RCM_SUBCLASS,
                        .bInterfaceProtocol = RCM_PROTOCOL,
                        .iInterface = 0
                },
                .int_in_ep = {
                        .bLength = sizeof(struct usb_desc_ep_t),
                        .bDescriptorType = USB_DESC_EP,
                        .bEndpointAddress = UPS_REPLY_EP,
                        .type = USB_EP_INTR,
                        .wMaxPacketSize = UPS_REPLY_EP_SIZE,
                        .bInterval = 0xFF
                }
        },
};

В коллбэк-функции, которая вызывается при успешной инициализации, мы зададим коллбэк rcm_handle_control() для обработки управляющих запросов и структуру tx_pipe для отсылки ответов:

static const struct usbd_function usbd_function = {
        .control = rcm_handle_control,
        .interface_count = 1
};

usb_attach_function(&usbd_function, &usbd_ctx);

tx_pipe = usb_init_ep(&usbd_ctx, 1, USB_EP_TX, UPS_REPLY_EP_SIZE);

Стандартные USB-запросы вроде Get Descriptor или Set Configuration возьмет на себя SDK и нам останется отработать лишь конкретный запрос:

static int rcm_handle_control(struct usb_ctrl_req_t *req, void *data)
{
        static unsigned char buf[UPS_REQUESTSIZE];

        if (req->recp     == USB_CTRL_REQ_IFACE && 
            req->type     == USB_CTRL_REQ_CLASS &&
            req->bRequest == UPS_REQUESTVALUE &&
            req->wValue   == UPS_MESSAGEVALUE &&
            req->wIndex   == UPS_INDEXVALUE &&
            req->wLength  == UPS_REQUESTSIZE)
        {
                usb_ep0_rx(buf, req->wLength, rcm_handle_data, NULL);
                return (1);
        }

        return 0;
}

Видно, что при совпадении всех полей SETUP-пакета, мы собираемся прочитать от хоста оставшиеся данные и устанавливаем для этого коллбэк rcm_handle_data(). Сам коллбэк мигает светодиодом и отсылает хосту в endpoint 1 текущий статус питания и заряда батареи:

static void rcm_handle_data(void *buf, ssize_t len, void *data)
{
        // Demonstration
        static int counter = 0;
        switch (counter++) {
                case 0:  ups_online(1); ups_batterystatus(1); break;
                case 30: ups_online(0); break;
                case 40: ups_online(1); break;
                case 50: ups_online(0); break;
                case 60: ups_batterystatus(0); break;
        }

        onboard_led(ONBOARD_LED_TOGGLE);

        // Send ACK for this request
        usb_handle_control_status(0);

        usb_tx(tx_pipe, ups_reply, UPS_REPLYSIZE, UPS_REPLY_EP_SIZE, NULL, NULL);
}

В общем-то, это всё…

void main()
{
        usb_init(&rcm_device);

        // Wait for interrupts
        sys_yield_for_frogs();
}

5. Проверка в реальной жизни


После сборки проекта командой make, необходимо нажать на MC HCK кнопку RESET, переводящую его на некоторое время в режим программирования, и набрать make flash для его прошивки с помощью dfu-util. Теперь плату можно вставлять в различные компьютеры и смотреть, как они на нее реагируют.

Проверим, как определяется наше устройство NAS'ом:



Подробности покажет USB-Prober для OS X:



Если немного подождать, то в логах Synology DSM можно увидеть, что наше устройство работает корректно:

info	2014/08/09 16:23:12	SYSTEM:	Local UPS was plugged in.
info	2014/08/09 16:23:13	SYSTEM:	The UPS was connected.
warning	2014/08/09 16:25:14	SYSTEM:	Server is on battery.
info	2014/08/09 16:26:04	SYSTEM:	Server back online.
warning	2014/08/09 16:26:54	SYSTEM:	Server is on battery.
warning	2014/08/09 16:27:45	SYSTEM:	Server going to Safe Shutdown.

6. Заключение


Казалось бы, пора подключать к пинам MC HCK что-то реальное — то есть то, для чего устройство предназначалось… но к этому моменту я уже потерял интерес.

Откровенно говоря, я просто хотел сэкономить на ИБП для NAS, взяв что-нибудь за максимально смешную сумму и добавив к нему USB-линк самостоятельно. Судя по отзывам о таких ИБП, их качестве и их батареях, это была дурацкая идея. Так что я купил недорогой APC, вмешиваться в работу которого не потребовалось: он и так поддерживает USB HID power device class.

Тем не менее, этот пример может оказаться кому-то полезен хотя бы для того, чтобы понять, как всё несложно. Полный исходный текст выложен на GitHub.
Поддержать автора
Поделиться публикацией

Комментарии 21

    +1
    «Разберись как оно работает, и сделай потом как надо.»
      +1
      При разработке автономных устройств на базе всяких arm c линуксами может быть полезно.
      У меня щас стоит задача сделать автономку с батарейнмым питанием и ssd на борту. Может туда подойдет
        0
        Что это за модель Synology с таким незнакомым меню?
        Да и занимать USB порт для этих целей…
        Я вот все мечтаю задействовать аналогичную функцию через сеть по SNMP. Но останавливает одна вещь… нигде нет информации о том какие параметры по SNMP NAS запрашивает у ИБП, хоть бери да эмулятор делай. А какой ответ потом слать?

        Идея просто есть запитать NAS напрямую от аккумулятора, приделав ему простой DC-DC конвертор это будет приятней чем существующие ИБП с низким КПД из-за преобразования на 50Гц. Тоесть просто напросто заменить его штатный блок питания аналогичным только с аккумулятором.
          0
          1) Да обычный DS214play, на которой стоит DSM 5.0.

          2) Я тоже жадничал, но понял, что у меня этих портов три, и я пока не решил, чем их занять…

          3) Судя по всему, для SNMP используется драйвер snmp-ups из тех же Network UPS Tools. Там рядом и MIBы для разных моделей лежат; можно выбрать, какой попроще. Послать SNMP-пакет по ethernet несложно. Хорошая идея для проекта на уикэнд )
            0
            ага, у меня уже старичок DS112j и там с портами туго, да и стрёмно бесперебойник по USB соединять, гальванической развязки нет.

            с SNMP там несколько сложнее чем просто пакет послать, устройство должно быть сервером(в NAS встроен клиент, который будет опрашивать бесперебойник и сервер который может использоваться для оповещения остальных устройств в сети) и там пляски какие-то с двумя портами. При первом знакомстве с протоколом мне это показалось очень неочевидным, но протоколы они такие — или следуешь или гуляешь мимо. Вобщем, это с наскока решить не получится. И эта проблема с защищенностью. Голый SNMP вообще ничем не защищен — пользуйся кто хочет, подставляйся кто хочет, даже парольная защита не предусмотрена. Но защита предусмотрена только в следующей версии протокола, который трудно будет реализовать на МК, это уже будет долгая и вдумчивая разработка а не «проект на уикэнд».
            0
            Смотря какая задача стоит: потушить NAS правильно или дать NAS жить как можно дольше работать без 220В.
            От того что будет цепочка «12 В->220В-> (12В, 5В и пр.)» или «12 В-> (12В, 5В и пр.)» КПД сильно не поменяется. Не большие потери при трасформации. Однако выигрыш в габаритах сборки безусловный.

            К слову можно взять идею от CarPC. Там преобразватель уже может оценивать уровень заряда АКБ, а в качестве внешнего БП поставить например РИП-12. Но опять же по стоимости и КПД выигрыш не очень большой.
              0
              на 12В->220В КПД очень сильно страдает особенно на железном трансформаторе и на 50Гц.
              NAS требует 19В 4А это будет сильно меньшая нагрузка на аккумулятор даже с преобразователем 12В->19В и он проработает дольше чем в бытовом ИБП.
              Вобщем, опыт обещает быть интересным.
              Темболее всегда хотелось сделать что-то более информативное нежели стандартные «работа от батареи» и «батарея разряжена». Хотелось бы видеть напряжение на батарее, её ток и внутреннее сопротивление, потребляемую активную мощность по выходу — по всем этим характеристикам вести лог и прогнозировать время разряда и жизни батареи. В прошлый раз я узнал что батарея «дохлая» совершенно случайно — во время кратковременного перерыва электропитания в несколько секунд заряд батареи уменьшился сразу до 20%.
              Автоматический тест батареи по расписанию мог бы выявить эту проблему, но результаты его работы не логируются, тем самым тест имеет смысл только в присутствии человека.
                0
                В свое время собрал сервак на железках от CarPC — работал изумительно.
                А именно, Pico-UPS + M2-ATX (клон оригинального). И промышленный китайский импульсник на 18В 10А. Можно использовать зарядку от ноута на 16-18в.
                На одном и том же аккумуляторе 7Ач время автономной работы отличалось в 3-4 раза, по сравнению с APC back-ups.
                КПД такого ИБП + M*-ATX составляет более 80%. При питании от сети — примерно как у стандартного ATX блока птания

                Вопрос контроля батареи решился тогда (в 2008-м) иным способом. На pic12 был собран простенький АЦП-проверка напряжения батареи. При падении ниже 12в — блоку питания давалась команда выключения (ACC off), тот в свою очередь нажимал кнопку power на материнке и ждал пока она уйдет в shutdown. Или через 2? минуты жестко рубил питание.
                При повышении напряжение выше 14в на 2 минуты — врубаем штатно тем же способом.
                  0
                  а теперь про то, какие существуют ИБП (DC-DC) и что они умеют.
                  Сначала про M*-ATX и их клоны. Они есть трех видов.
                  1. Uвх ровно 12в
                  2. Uвх от 14 до ~19в
                  3. Uвх от 8 до 19в (иногда от 6 до 32в — зависит от модификации)
                  Мощности у них от 80 до 250Вт.

                  ИБП есть простые (как pico-UPS) — напряжение либо от БП, либо от батареи (~12В).
                  Там нет ничего кроме контроллера заряда батареи, но они дешевые и имеют рабочий ток до 10А, чего достаточно для питания даже последних i7 без внешней видеокарты.

                  Есть OpenUPS(2). Там есть всё что нам надо (USB HID battery), поддержка почти любых аккумуляторов, регулируемый выход (позволяет применять БП типа 1), но меня смущают две вещи:
                  1. Ток 5А макс
                  2. цена больше $100
                  как ни крути, а i7 встает с натягом и то только при использовании 14-18в литиевой батери.

                  Так что этот пост возможно сподвигнет меня на разработку чего-то подобного, но помощнее (скажем под M4-ATX 250Вт). USB HID наверное на STM32 буду делать.

                  Кстати тут никто не сказал, но эти DC-DC — путь к абсолютно безшумному компу, так что есть к чему стремиться.
              0
              Кстати, еще быстрее может оказаться взять какую-нибудь дешевую raspberry pi, запустить на ней network ups tools как snmp-сервер, а к нему дописать минимальный драйвер вашего аккумулятора, который будет смотреть на какую-нибудь единичку на gpio…
                0
                Быстрее может оказаться взять ИБП со встроенным SNMP контроллером… только не дёшево это всё.
              0
              У меня касательно NASa и UPS была следующая идея — у нас электроэнергия ночью стоит в 4 раза дешевле, чем днем. Я вот думал, что было бы неплохо ночью электроэнергию накапливать, а днем питать NAS от UPS :). Но когда подумал о том, как это реализовывать надо будет, решил ничего не делать :). Ваше устройство, наверное, упростило бы подобную задачу.
                0
                Стоимость экономии энергии отобъёт стоимость парочки автомобильных аккумуляторов?
                  0
                  Не знаю, не считал. Даже не считал хватит ли UPSa на день работы NASa (и, может, роутера). Тут еще плюсом было то, что в случае пропадания электричества днем, UPS использовался бы по назначению.

                  Но если кому вдруг захочется посчитать, то вот данные —
                  NAS Synology DS210j — 26 Вт, 10 Вт в режиме сна

                  Стоимость электроэнергии —
                  * пик — зона суток Т1 (7:00-10:00, 17:00-21:00): 3,18 руб
                  * ночь — зона суток Т2 (23:00-7:00): 0,81 руб
                  * полупик — зона суток Т3 (10:00-17:00, 21:00-23:00): 2,63 руб
                    +2
                    на день ему надо 416 ватт, считаем 80% кпд = 520Вт кушает + 208вт кушает он сам ночью.
                    Итого за ночь он скушает 728*0.81=0.59 рублей.
                    если его кормить круглосуточно без упса, это будет (7*26*3.18+8*26*0.81+9*26*2.63)/1000=1,36266руб
                    Соответственно, экономия в день будет составлять 0.77 копеек.
                    Стоимость упса на 800VA (мы ж считаем с запасом) = 4650руб.
                    Значит, он окупится через 6039 дней = 16 лет и 7 месяцев.
                      0
                      Только если сможет обеспечить непрерывную работу в течении дня… кажется мне, не пройдет и бесперебойник нужен мощнее с большей батареей, большей автономностью.
                      Да, за 16 лет сменишь 4-5 батарей… их тоже в ценник надо включить.
                      0
                      На пару часов хватит. даже если вот так прикинуть — емкость батареи 7А*Ч *12В = 84Вт*ч если учесть КПД инвертора, КПД блока питания НАС-а, то это будет пару часов.
                    0
                    Считали… стоимость (ресурсная) одного кВтч на аккумуляторе в разы выше дневного тарифа из розетки.
                    Если есть дохлый автомобильный аккум, который стартер уже не тянет, то можно его «припахать» беслатно, но не надо рассчитывать что он больше года проживет в таком режиме.

                    Естати на сутки работы их емкости обычно хватает.
                    0
                    В моем ИБП только COM-порт, а в NAS только USB + переходники USB2COM сломаны в ядре, так что мне пришлось использовать UART-порт NAS и самосборный переходник UART2COM
                      0
                      Спасибо за пост. Наткнулся на него случайно, изучая вопросы программирования USB на МК (у меня STM32). Хочу прикрутить к FreeNAS сенсор-драйвер вентиляторов как HID устройство, но, как оказалось, поддержка HID во FreeBSD хромает. Похоже на то, что uhid(4) корректно работает только с одним набором и контрольным Endpoint 0 (не уверен на 100%, надо код изучать, долго). ИБП APC по USB ядром FreeBSD как hid-устройство вообще не определяется, а упомянутый NUT использует ugen(4), это на один уровень ниже по стеку. Возиться на уровне ОС не хочется (скучно, к тому же FreeNAS вообще встраиваемая система), поэтому я пока решил попробовать адаптировать STMовский пример CustomHID из библиотеки STM32 USB full speed device library (UM0424). Кстати, этот пример неплохо разобран тут на хабре. Запустить эту штуку удалось, даже появилось устройство uhid0, но считать из него хоть что-нибудь командой usbhidctl(1) оказалось невозможно: выдаёт «Device not configured», перехват по USB показывает обмен со статусом STALL (который, похоже, вывешивается на Endpoint 0 и висит там). При этом запись (моргание диодом) работает, только не совсем понятно, через SET_FEATURE или ещё как. Не разобрался пока, поэтому пост не пишу:)

                      Вывод: в реальных условиях приходится работать с платформами, где поддержка столь удобной для всевозможных МК-датчиков абстракции USB HID может хромать, причём без видимых перспектив развития (ну кому может понадобиться джойстик под FreeBSD? в этих краях и мышь-то нечасто встретишь). Одно дело из-под Windows мигать диодиком, другое — реальная задача… Но это не умаляет заслуг авторов постов про мигание диодиками, и я им всем благодарен.

                      Но это не вся моя история:)
                        0
                        Продолжение истории: покупка б/у ИБП для некритичной инфраструктуры mini-HOWTO.

                        Я недавно столкнулся с похожей задачей: купить, наконец, ИБП для не очень критичного NAS :)
                        Исходил из того, что:
                        1. Брендовые изделия качественные, и кроме батареи в них особо ничего не изнашивается («надежность»; поправьте, если не так).
                        2. ИБП для рабочих станций на 700кВА — страшный неликвид, от которого любой бизнес будет только рад избавиться («дешевизна»).
                        3. Изделия APC очень распространены и довольно неплохо изучены community, уж чего только с ними не делали («поддержка»).

                        Нагрузка у меня как раз где-то 300-350Вт. Новый APC SUA750I (500Вт) по Яндекс.Маркет стоит порядка 12,000руб. Но на avito.ru нашел много предложений б/у за 1000-1500 руб. (причём продавец в итоге нашёлся чуть ли не в соседнем доме), плюс две новых «неродных» батареи по 1050руб. (в магазине, в другом соседнем доме). Т.е. всё за четверть цены, да ещё и в шаговой доступности. Из пары переходников DB9-RJ45 (каждый по €1) и обычного патч-корда Ethernet собрал изделие #940-0024C (это кабель RS-232 Smart Signalling), а бесплатной утилитой откалибровал ИБП на новую батарею. Нашлись и нюансы: сам APC ИБП при калибровке батарейную константу может только уменьшать, поэтому её надо сперва открутить вверх. Упомянутая тулза, которая это делает, работает только по RS232. Заодно я вдоволь наигрался ручными командами (они проходят только по RS-232, и требуется особая осторожность!): поменял дату установки батареи без всяких парашютов. Отличное развлечение, при «программировании» ИБП забавно тикает. Правда, потом нашел невесть откуда взявшийся шнурок USB (чёрный, в тон ИБП) и решил сравнить возможности драйверов NUT apcsmart и usbhid-ups (раз уж взялся). Действительно, один и тот же ИБП имеет разные функции в зависимости от драйвера. Остановился в итоге на варианте USB, который умеет показания тока снимать, а переходники для #940-0024C отправились в «бардачок». Мало ли чего…

                        Итог: если тема актуальна, нагрузка невелика, риски умеренные (некритичная инфраструктура), рекомендую поискать б/у изделия хороших брендов с отработавшими батареями, которые сразу заменить на новые качественные, но неродные. На avito.ru предложений по SUA750I было несколько штук, некоторые партиями. Батареи под них найти не проблема (поиск: «калибровка батареи smart ups», ну или каталог замен на сайте akbprom.ru). Только убедитесь, что с ИБП вам отдают старую батарею или все провода от неё: например, батарейный картридж для SUA750I имеет фирменный разъём питания, а также перемычку с флажковым предохранителем на 60А (если что, есть в автомобильных магазинах, номинал на 60А обычно цвета морской волны). Это всё хозяйство нужно снять со старой батареи и одеть на новую, хотя можно и паяльником (старенькая модель ИБП APC, кстати, тоже тут разобрана.). Я уже сделал несколько попупок б/у железа через авито и пока доволен, народ вполне адекватный, такие же айтишники:). Желаю удачи и простите за оффтоп.

                        Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                        Самое читаемое