четверг, 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