четверг, 27 марта 2025 г.

Компенсация потерь на защите от обратной полярности

 Ранее я описывал схему защиты АЦП INA226 от обратной полярности которую я добавил в измеритель ёмкости аккумуляторов

Результатом стала погрешность измерений напряжения из-за падения напряжения на сопротивлении R1 при протекании через него тока. Этот ток складывается из обратных токов диода шоттки D1 и стабилитрона D2 а также тока через вход АЦП INA226 (он незначительный, но не равен нулю).

Если сравнить показания напряжения INA226 с показаниями точного мультиметра (в моём случае это Agilent U3402A с заявленной точностью по постоянному напряжению ± 0,012% + 5), то получается заметная погрешность

В первой колонке напряжение измеренное с помощью Agilent U3402A, во второй колонке - измерения напряжения INA226 и в третьей колонке - погрешность измерения если принять показания U3402A за эталон.

среда, 26 марта 2025 г.

Очередное усыхание Docker Hub

 Всего через 5 дней (с 1 апреля 2025) Docker Hub вводит новые лимиты на скачивание образов. Изначально их планировали вводить с 1 марта 2025, но сдвинули на один месяц:

  • 10 скачиваний в час для неавторизованных пользователей
  • 100 скачиваний в час для авторизованных пользователей с бесплатным аккаунтом

Сейчас действуют такие лимиты (посмотреть их можно через Wayback Machine):

  • 100 скачиваний за 6 часов для неавторизованных пользователей
  • 200 скачиваний за 6 часов для  авторизованных пользователей с бесплатным аккаунтом

Количество скачиваний учитывает запросы к манифесту (/v2/*/manifests/*), для multi-arch образов будет два запроса вместо одного.

Образы которые участвуют в программах Docker Sponsored Open Source и Docker Verified Publisher не должны учитываться в этих лимитах.

Новых лимитов скорее всего не хватит чтобы даже мелкий kubernetes кластер пережил апгрейд нод. Если вы используете образы с DockerHub в своих окружениях, то стоит задуматься над использованием зеркал (например Amazon ECR Public Gallery) или загрузить нужные образы в локальный registry до того как это станет проблемой.

В GCP Cloud Build и GKE используется кеширование популярных образов Docker Hub через использование mirror.gcr.io:

Google Cloud services such as Cloud Build and Google Kubernetes Engine automatically check for cached images before attempting to pull an image from Docker Hub.

Грабли при обновлении ingress-nginx до 1.12.1

Вчера срочно обновлял ingress-nginx до 1.12.1 (версия чарта 4.12.1) после новости о критической уязвимости CVE-2025-1974 и наступил на грабли - релиз обновился, но все существующие ingress'ы потеряли привязку к IP адресу балансировщика.

Полез смотреть events в кластере, но там ничего криминального не нашлось. В логах ingress-nginx контроллера присутствовали ошибки вида

E0325 12:26:36.275715       7 store.go:938] annotation group ConfigurationSnippet contains risky annotation based on ingress configuration

но сходу у меня не сложилась связь этих ошибок с отсутствием привязки к IP адресу. А вот когда попробовал пересоздать один из ingress'ов всё стало на свои места

Error: INSTALLATION FAILED: admission webhook "validate.nginx.ingress.kubernetes.io" denied the request: annotation group ConfigurationSnippet contains risky annotation based on ingress configuration

Во всех ингресах присутствовала аннотация nginx.ingress.kubernetes.io/configuration-snippet через которую делается тонкий тюнинг приложений и нет простого способа отказаться от использования этой опции.

вторник, 25 марта 2025 г.

Алгоритм подсчёта отданной ёмкости аккумулятора

Переношу предыдущие наработки в прошивку для измерителя ёмкости аккумуляторов и решил описать алгоритм подсчёта отданной ёмкости в ампер-часах и ватт-часах.

Напряжение на аккумуляторе будет изменяться по мере разряда или заряда, а ток будет изменяться при разряде на резистивную нагрузку или по мере заряда аккумулятора.

В этом случае подойдет суммирование отдельных интервалов - график измерений тока и напряжения разбивается на промежутки:

  • ёмкость в ампер-часах будет Cah = I1 * t1 / 3600 + I2 * t2 / 3600 + ... + In * tn / 3600, где I1, I2, ..., In - измерения тока в конце каждого интервала и t1, t2, ..., tn - длина каждого интервала в секундах.
  • ёмкость в ватт-часах будет Cwh = I1 * t1 / 3600 * V1 + I2 * t2 / 3600 * V2 + ... + In * tn / 3600 * Vn, где I1, I2, ..., In - значения тока в амперах в конце каждого интервала и t1, t2, ..., tn - длина каждого интервала в секундах, а V1, V2, ..., Vn - значения напряжения в вольтах в конце каждого интервала.

Достоинства:

  • подходит для изменяющихся напряжения и тока.

Недостатки:

  • точность зависит от длины интервала t.
  • точность измерения ёмкости в ампер-часах снижается если напряжение изменилось внутри интервала.

воскресенье, 23 марта 2025 г.

Подсчёт времени на ATmega328P

В прошивке измерителя ёмкости аккумуляторов есть код, который считает время разряда аккумулятора. Этот код я нашёл на одном из форумов посвящённых Arduino тематике и он выглядит довольно простым:

volatile uint8_t runTimeIsr = 0;
uint8_t runTimeLoop;
uint32_t runTime;

// https://gist.github.com/raspberrypisig/8bf856ae9b55bb433d4c11ac9540a881
void timerInit() {
    noInterrupts();
    // Clear registers
    TCCR1A = 0;
    TCCR1B = 0;
    TCNT1 = 0;

    // 1 Hz (16000000/((15624+1)*1024))
    OCR1A = 15624;
    // CTC
    TCCR1B |= (1 << WGM12);
    // Prescaler 1024
    TCCR1B |= (1 << CS12) | (1 << CS10);
    // Output Compare Match A Interrupt Enable
    TIMSK1 |= (1 << OCIE1A);
    interrupts();
}

ISR(TIMER1_COMPA_vect) {
    runTimeIsr += 1;
}

После запуска таймера переменная runTimeIsr считывается в основном цикле и затем обнуляется. Поскольку операция сложения с четырёхбайтной переменной занимает несколько циклов, то используется промежуточная переменная runTimeLoop чтобы избежать конфликта с обработчиком прерывания

void timerDo() {
    runTimeLoop = runTimeIsr;
    runTimeIsr = 0;
    runTime += runTimeLoop;
}

В теории обработчик прерывания должен вызываться каждую секунду если микроконтроллер работает на частоте 16 МГц, но в реальности за 3 часа тестирования время, измеренное микроконтроллером отстало от реального на 35 секунд.

При этом посчитанная ёмкость составила 299 мАч вместо ожидаемых 300 - выглядит как допустимая погрешность, но стало любопытно в чём причина.

вторник, 18 марта 2025 г.

Схема измерителя ёмкости аккумуляторов

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

Полная схема устройства

Далее я рассмотрю отдельно интересные части схемы.

Источник питания


Для питания схемы нужен источник постоянного напряжения от 7,5 В до 9 В и током 500 мА. От неправильной полярности защищает диод по входу, напряжение 5В берётся с выхода линейного стабилизатора L7805.

Схема потребляет до 350 мА (если включены оба реле) и при питании от 9 В на стабилизаторе рассеивается около 1,2 Вт. Поскольку корпус TO-220 не может рассеять больше 1 Вт, то на линейном стабилизаторе установлен небольшой радиатор.

четверг, 13 марта 2025 г.

Проверка работы Distribution Registry

 Чтобы проверить работоспособность Distribution Registry достаточно только curl. Для примера получу манифест для образа registry.example.com/helloworld-python:latest

$ REGISTRY_USERNAME=read-only
$ REGISTRY_SERVER=registry.example.com
$ IMAGE_NAME=helloworld-python
$ IMAGE_NAME=latest

$ curl --user $REGISTRY_USERNAME \
  --header 'Accept: application/vnd.docker.distribution.manifest.v2+json' \
  https://$REGISTY_SERVER/v2/$IMAGE_NAME/manifests/$IMAGE_TAG

среда, 12 марта 2025 г.

Защита входа АЦП для INA226

В процессе наладки схемы измерителя я умудрился поджарить микросхему INA226, подав 5 В на вход VBUS в обратной полярности. Согласно документации абсолютный максимум напряжения на входе VBUS у INA226 от -0,3 В до 40 В. Поначалу микросхема не определялась микроконтроллером, но чуть позже стала отвечать но показания напряжения было около 88 В на входе VBUS. Перепаивать мелкий корпус INA226 несколько раз (первая замена оказалась контрафактной) было тем ещё "удовольствием".

Чтобы не повторить ошибку собрал схему защиты от обратной полярности и перенапряжения

От обратной полярности защищает диод шоттки 1N5819. В случае неправильного подключения он открывается и ограничивает напряжение на входе АЦП.

суббота, 8 марта 2025 г.

Очередная замена диска в домашнем сервере

В домашнем сервере есть жёсткий диск Toshiba DT01ACA300 на 3 TB который работает почти 8 лет или 69623 часов, если быть точным.

На этой неделе мониторинг оповестил что показатель S.M.A.R.T. "Current_Pending_Sector" у этого диска вырос до 32

при этом показатели Reallocated_Sector_Ct и Reallocated_Event_Count пока по нулям.

Для меня это означает что пора искать замену для этого старичка, но особой спешки нет, т.к. этот диск - часть RAID1 и потерю одного диска можно пережить. Однако существует вероятность что второй диск откажет в момент синхронизации массива после добавления нового диска. Прошлый раз менять диск в массиве пришлось 4,5 года назад, но тогда ситуация была печальнее.

На замену взял диск Seagate ST4000VX015 на 4 TB. У этого диска технология записи CMR (Conventional Magnetic Recording), он предназначен для работы 24x7 и есть поддержка Error Recovery Control. Скорость вращения шпинделя меньше 7200 RPM (я не нашёл точной цифры в документации производителя, а продавцы указывают 5900 RPM), но это перестало быть критичным после переноса системы на SSD.

среда, 5 марта 2025 г.

SMD зажим-пинцет для мультиметра

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

При разомкнутых щупах мультиметр показывает сопротивление около 43 МОм. Это указывает на проблемы с изоляцией где-то внутри пинцета.

Как результат - будут искажаться показания высокоомных сопротивлений - измерил SMD сопротивление номиналом 1 МОм, с обычными щупами мультиметр показывает 0,999 МОм, а с пинцетом 0,982 МОм. Для простой проверки сгодится, но подбирать номинал сопротивления таким пинцетом точно не стоит.

При измерениях конденсаторов скорее всего будет показывать ток утечки (но мне нечем проверить эту теорию), хотя сам конденсатор не виноват. Измерил номинал конденсатора 100 нФ - показания мультиметра с обычными щупами и пинцетом близкие, но в случае пинцета они не фиксируются как от плохого контакта.

воскресенье, 2 марта 2025 г.

Корпус для измерителя ёмкости аккумуляторов

Делаю новый проект измерителя ёмкости аккумуляторов на замену модулю ZB2L3 который ограничен напряжением 15 В и током 3 А. Модуль ZB2L3 не отличается точностью из-за отсутствия четырёхпроводной схемы измерения напряжения.

Когда проверял ёмкость нового аккумулятора для робота-пылесоса конфигурация которого 4S2P (напряжение полностью заряженного аккумулятора 16,8 В), то использовать ZB2L3 не получилось. В дизайн своего устройства закладываю поддержку напряжения до 30 В и тока до 20 А (ограничение силового реле по постоянному току) а также соединение с компьютером для передачи измерений напряжения и тока.

Сейчас идёт этап написания прошивки для микроконтроллера и доводка принципиальной схемы. Чтобы не возиться с ворохом проводов на столе решил потратить несколько часов и смоделировать корпус в OpenSCAD.

Печатную плату изолированного преобразователя USB UART экспортировал из Kicad PCB Editor (в меню "File" / "Export" / "STEP/GLB/BREP/XAO/PLY/STL...", выбрать формат STL и остальные параметры оставить без изменения).

Остальная электроника смонтирована на макетной плате и я рисовал в Kicad только её габаритный аналог с отверстиями для крепления и тактовыми кнопками. Далее экспортировал в STL аналогично плате преобразователя.

Шунт на 20 А упрощённо смоделировал чтобы посмотреть на габарит и совпадение креплений.

После прикидки взаимного расположения печатных плат, шунта и реле внутри корпуса его размеры получились 150х150х50 мм. Чтобы видеть как расположена начинка внутри корпуса сделал его стенки прозрачными