Embedded HandbookПриложения
Все разделы › XXVI. От макета к изделию
STM32F103, STM32F407 · уровень средний · 18 мин чтения
Открыть в интерактивном справочнике

203. ЭМС изделия: помехи, стойкость и проверка в мастерской

Прибор работает на столе — и это ничего не говорит о том, как он поведёт себя рядом с контактором, под рацией монтажника или после зимней куртки и дверной ручки. Электромагнитная совместимость — последний экзамен изделия, и сдают его дважды: изделие не должно мешать соседям и не должно падать от их помех. Выводы уже защищены (раздел 62), вход питания собран (раздел 173); здесь — картина целиком: кто в приборе шумит, что в него прилетает, как строится оборона от корпуса до прошивки и что из этого можно проверить в мастерской до платной лаборатории.

Числа раздела — расчёты _verify/emc203/wave_calc.py, спектр фронтов — ряд Фурье spectrum.py, разряд и наводка — модели ngspice в контейнере stm-lab:1, сторож конфигурации — собран и прогнан на ПК и собран для Cortex-M3 в stm-arm:1; скорости выводов — из заголовков паков.

Как это называется в документации

Оригинал Перевод
electromagnetic compatibility (EMC) электромагнитная совместимость: не мешать и выдерживать
electromagnetic interference (EMI) электромагнитная помеха
radiated / conducted emission излучение в эфир / помеха, уходящая по проводам
immunity, susceptibility стойкость к помехам, восприимчивость
contact / air discharge контактный разряд / разряд через воздух
electrical fast transient (EFT), burst пачки наносекундных импульсов
surge выброс: длинный импульс большой энергии
voltage dip, short interruption провал и кратковременное пропадание питания
pre-compliance testing предварительная проверка до формальных испытаний
pigtail «косичка»: хвостик, которым экран кабеля подпаян к земле

203.1 Две стороны ЭМС: сам шумишь — и тебя глушат

У задачи два зеркальных лица. Эмиссия: тактовые фронты, импульсный преобразователь и кабели изделия излучают и гонят помеху в сеть — за это изделие бракуют на испытаниях, даже если само оно работает безупречно. Стойкость: разряд статики с руки, пачки от искрящих контактов, выброс в проводке и провал сети — от этого изделие виснет, врёт и перезапускается у заказчика.

Помеха ходит двумя путями: по проводам (кондуктивно) и через поле (излучение и наводка). Ниже десятков мегагерц главный путь — провода, выше — эфир; граница размыта, потому что кабель, по которому помеха пришла кондуктивно, тут же работает передающей антенной.

Карта угроз изделия: слева эмиссия в эфир и по проводам и кабель как антенна, справа разряд с руки, пачки от реле, выброс, провал сети и поле рации

Карта угроз конкретного прибора составляется за вечер: выписать все кабели (питание, интерфейсы, датчики), всё, чего касается человек (корпус, кнопки, разъёмы), всё, что искрит и коммутирует рядом (реле, контакторы, двигатели), и все свои источники шума (тактовые, шины, импульсник). Дальше по разделу видно, что почти каждая пара «источник → жертва» закрывается одним из типовых средств.


203.2 Кто в приборе излучает: фронты, тактовые, кабели

Излучает не «частота 72 МГц», а фронты. Меандр — это нечётные гармоники: 72, 216, 360 МГц и дальше; их амплитуда спадает медленно, пока частота не дойдёт до излома огибающей 1/(π·t_фронта) — при фронте 1 нс это 318 МГц, при 5 нс — 64 МГц. Выше излома спектр валится быстро, поэтому чем медленнее фронт, тем короче хвост гармоник. Ряд Фурье трапеции 3,3 В на 72 МГц (spectrum.py, ДПФ сходится с аналитической формулой лучше 2 %):

Гармоника Частота Фронт 1 нс Фронт 5 нс Спад
1 72 МГц 2,083 В 1,681 В 1,9 дБ
3 216 МГц 0,648 В 0,051 В 22,0 дБ
5 360 МГц 0,336 В 0,044 В 17,7 дБ
9 648 МГц 0,102 В 0,016 В 16,3 дБ

Первая гармоника — сам сигнал — почти не изменилась, а хвост упал на порядок. Отсюда правило: скорость выводов — минимально достаточная. У F1 она задаётся в конфигурации вывода — 2, 10 или 50 МГц (перечисление GPIO_Speed_… в заголовке пака), у F4 и младше — регистром OSPEEDR. «50 МГц» на выводе, который щёлкает светодиодом, — бесплатный передатчик.

Сам по себе сантиметровый проводник на плате излучает слабо — плохи кабели: провод длиной в четверть волны — уже настроенная антенна. Длина волны λ = c/f:

Частота λ λ/4
72 МГц 4,16 м 1,04 м
216 МГц 1,39 м 34,7 см
360 МГц 0,83 м 20,8 см

Метровый кабель питания — четвертьволновая антенна прямо на тактовой частоте, а тридцатисантиметровый хвостик к датчику — почти антенна для пятой гармоники. Раскачивает антенну синфазный ток — тот, что течёт по всем жилам кабеля в одну сторону и возвращается через ёмкость на окружение: оценка по формуле короткого диполя даёт от 5 мкА синфазного тока на 30-см кабеле на 216 МГц поле около 68 мкВ/м в трёх метрах — порядок допустимого для бытовой обстановки. Микроамперы! Поэтому синфазный дроссель или ферритовая бусина на кабеле (раздел 168) делают для эмиссии больше, чем любая правка схемы.

Третий источник — импульсный преобразователь (раздел 58): сотни килогерц коммутации и гармоники до десятков мегагерц. Его лечат на плате: минимальная площадь горячей петли и сплошная земля под ней (разделы 130, 181), а скоростные цепи и возвраты токов — раздел 132г.

⚠️ Частоту не спрятать, фронт — можно. Тактовую вниз не сдвинешь — она нужна работе. А фронты почти всегда быстрее, чем требует схема: и у GPIO, и у SPI, и у затвора ключа импульсника (там фронт задаёт резистор затвора). Замедление фронтов — первое и самое дешёвое средство.


203.3 Стойкость: разряд, пачки, выброс, провал

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

Разряд статики. Человек в сухом помещении — заряженный конденсатор: модель испытательного генератора — 150 пФ, заряженные до единиц-десятков киловольт, разряжаемые через 330 Ом (рука с металлическим предметом). Модель ngspice esd.cir при 8 кВ: пик тока 24,2 А, спад до 1/e за 49,5 нс, в резисторе выделилось 4,8 мДж — интеграл сошёлся с формулой E = CU²/2 = 0,5 · 150 пФ · (8 кВ)² = 4,8 мДж (Ф·В² = Кл·В = Дж — размерность сходится). Пиковая мощность — U²/R ≈ 194 кВт: миллиджоули, но за наносекунды. Это в 24 раза больше энергии, чем в модели человеческого тела из паспорта микросхемы, — почему встроенной защиты не хватает, разобрано в 62.8. Разряд бьёт во всё, чего касается человек: корпус, кнопки, разъёмы, — причём контактный разряд злее разряда через воздух: у него нормированный наносекундный фронт со спектром до гигагерц.

Пачки. Каждый контактор и реле в щите при размыкании индуктивной нагрузки искрит серией наносекундных импульсов. Катушка небольшого реле (100 мГн, 30 мА) хранит всего 45 мкДж, но без гасящей цепи разрыв раскачивает контур катушки до U = I·√(L/C) ≈ 2,1 кВ — и искра повторяется, пока контакты расходятся. Энергия каждого импульса ничтожна, страшен фронт: модель coupling.cir прикладывает фронт 300 В за 5 нс к «чужому» проводу, лежащему в одном жгуте с нашим (10 пФ ёмкости между ними):

Куда пришло через 10 пФ Пик на линии
высокоомный вход, подтяжка 10 кОм 293 В
линия с нагрузкой 100 Ом 60 В
100 Ом плюс конденсатор 1 нФ 2,9 В
тот же фронт, но за 1 мкс, на 100 Ом 0,3 В

Три вывода из одной таблицы: наносекундный фронт пролезает через пикофарады (i = C·dU/dt = 10 пФ · 60 В/нс = 0,6 А); высокоомные входы беззащитны, низкоомные — в пять раз лучше, а конденсатор у входа гасит наводку в сто раз; медленному выбросу те же 10 пФ безразличны.

Выброс. Микросекундно-миллисекундный импульс от коммутации мощных нагрузок и грозовых наводок: напряжение ниже, чем у статики, но энергия — уже не милли-, а джоули. Его встречает не вывод МК, а вход платы: ограничитель, предохранитель и их правильный порядок — раздел 173.

Провал и пропадание питания. Сеть «моргает» на полпериода-период: прибор должен либо прожить это на запасённой энергии, либо корректно перезапуститься — но не зависнуть и не испортить данные во флеш. Что из этого выбрано — решение, которое надо принять и записать до испытаний, а не после.


203.4 Первая линия обороны: вход питания, интерфейсы, корпус

Общий принцип: помеху встречают на границе, пока у неё один путь внутрь, а не десять.

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

Вход питания — цепочка из раздела 173: предохранитель, защита от переполюсовки, ограничитель, за ним фильтр и стабилизатор. Провал сети держит накопительный конденсатор: 1000 мкФ, разряжаемые нагрузкой 1 Вт от 12 до 8 В, дают 40 мс — период сети с запасом. Дольше — уже не конденсатор, а осознанное «перезапустимся»: детектор просадки PVD (раздел 10.7) успевает предупредить прошивку, чтобы та дописала журнал и не начинала запись во флеш.

Интерфейсы. Всё, что уходит с платы, получает последовательный резистор и ограничитель у разъёма (разделы 62.3, 62.9), длинные и межблочные линии — RS-485 со своими защитами (раздел 89.4), самое злое окружение — гальваническую развязку (раздел 54). От синфазной помехи и для эмиссии — синфазный дроссель или бусина на кабель (раздел 168). Конденсатор в единицы нанофарад у входа — та самая строка «2,9 В вместо 293 В» из таблицы выше.

Корпус и земля. Металлический корпус — экран и приёмник разряда: статика уходит в него, минуя схему, — если земля платы соединена с корпусом у разъёмов и путь разряда не проходит через плату. Правила, которые дают большую часть результата:

🔧 Заложить оборону заранее. Посадочные места под ограничители, бусины и RC у каждого разъёма разводят на плате с первой версии — не запаяны, стоят ноль. Если лаборатория найдёт проблему, доработка — паяльник и час, а не новая плата и месяц.


203.5 Прошивка, которая переживает помеху

Электроника гасит энергию, но часть помех доходит до кристалла — и тогда изделие спасает прошивка. Её оборона — три эшелона.

Сторож (раздел 12) — последний рубеж: независимый IWDG перезапустит намертво зависшую программу. Но сброс — это признание поражения на десятки миллисекунд: для счётчика это потерянные импульсы, для регулятора — рывок. Поэтому выше сторожа стоит второй эшелон.

Сверка конфигурации периферии. Помеха умеет перещёлкнуть бит в регистре конфигурации: программа цела, цикл крутится, сторож сыт — а UART молчит, потому что у него сбросился делитель. Регистры конфигурации не защищены ничем, кроме прошивки, — значит, после полной инициализации снимается эталон, а в главном цикле он сверяется:

enum { NCFG = 8 };
volatile uint32_t *cfg_addr[NCFG];         /* что охраняем: заполняется при инициализации */
static uint32_t cfg_good[NCFG];            /* эталон после инициализации */
static uint32_t cfg_ref;                   /* его контрольная сумма */
void cfg_snapshot(void)                    /* вызвать после полной инициализации */
{
    for (int i = 0; i < NCFG; i++)
        cfg_good[i] = *cfg_addr[i];
    cfg_ref = cfg_crc();
}

int cfg_guard(void)                        /* из главного цикла, раз в десятки мс */
{
    if (cfg_crc() == cfg_ref)
        return 0;                          /* всё на месте — дёшево: одна сумма */
    int fixed = 0;
    for (int i = 0; i < NCFG; i++)
        if (*cfg_addr[i] != cfg_good[i]) {
            *cfg_addr[i] = cfg_good[i];    /* вернуть как было */
            fixed++;
        }
    return fixed;                          /* и записать событие в журнал */
}

В cfg_addr[] кладут адреса регистров конфигурации — GPIOA->CRL, USART1->CR1, — только конфигурацию, не данные и не флаги. Прогон _verify/emc203/emc_guard.c на ПК: подмена одного бита обнаружена и восстановлена за один вызов, подмена в двух регистрах — «восстановлено регистров: 2», контрольная сумма после ремонта совпала. Для Cortex-M3 весь механизм собрался в 172 байта кода и 68 байт ОЗУ.

Восстановление того, что снаружи. Разряд посреди транзакции I²C оставляет ведомого с зажатой SDA — шину оживляют тактами вручную (рецепт 17.6). Приёмник UART после помехи пересинхронизируют по ошибке кадра. Кварц, задушенный помехой, подхватывает система защиты тактирования: она переводит МК на внутренний генератор (раздел 6). Входы читают трижды и берут совпавшее большинство, а состояние критичных выходов периодически перезаписывают — как и конфигурацию.

⚠️ Каждый сброс — в журнал. Флаги причины сброса (раздел 12.4) и счётчик срабатываний cfg_guard в энергонезависимой памяти или телеметрии (раздел 190) — единственный способ узнать, что прибор у заказчика ловит помеху раз в час. Прибор, который «просто иногда моргает», — это прибор, который молча перезапускается.


203.6 Проверка в мастерской: зажигалка, реле, приёмник

До лаборатории грубые дыры находятся подручными средствами — если честно понимать, что они показывают, а что нет.

Пьезозажигалка — генератор разряда. Пьезоэлемент без горелки даёт искру 3–4 мм; воздух пробивается примерно при 3 кВ/мм, то есть это импульс порядка 9 кВ — уровень серьёзного испытания. Щёлкать по корпусу, возле кнопок, в разъёмы, вдоль щелей; прибор при этом работает, а рядом человек смотрит на поведение.

🔧 Как щёлкать. Сначала — косвенный разряд: искра в металлическую пластину, стоящую в паре сантиметров от изделия; потом — в корпус и металл разъёмов; в последнюю очередь — рядом с пластиковыми кнопками и швами. В открытую плату без корпуса не разряжать вовсе: живой кристалл такой опыт переживает не всегда, а изделие испытывают в сборе — как его увидит человек с наэлектризованной рукой.

Реле — генератор пачек. Реле, коммутирующее собственную катушку через свой же размыкающий контакт, — классический зуммер: контакты искрят непрерывно, и без гасящей цепи каждый разрыв — звон в киловольты (расчёт из 203.3: около 2,1 кВ). Пару витков провода от этого «стенда» вокруг жгута изделия — и видно, переживают ли интерфейсы наносекундные фронты. Провал сети имитируется проще всего: выдернуть и воткнуть вилку, отпустить кнопку блока питания на полсекунды — и смотреть, перезапустился ли прибор корректно.

Приёмник — индикатор эмиссии. АМ-приёмник средних волн, дешёвая рация или SDR-свисток рядом с платой слышат «пение» импульсника и тактовых. Абсолютный уровень так не измерить, но сравнение «до/после» работает отлично: замедлили фронты, надели бусину, закрыли крышку — шипение в приёмнике упало или нет.

Стенд Что имитирует Чего НЕ покажет
пьезозажигалка разряд статики ~9 кВ нормированные ток и фронт; «сколько кВ держим»
реле-зуммер у жгута пачки от контакторов уровень связи с реальной проводкой
дёрганье вилки провал и пропадание сети форму и фазу нормированного провала
приёмник у платы излучение в ближнем поле абсолютный уровень, дальнее поле, весь диапазон частот

⚠️ Домашний стенд ловит провалы в обороне, а не подтверждает запас. Ни один из этих опытов не нормирован: энергия зажигалки не равна энергии испытательного пистолета, связь реле со жгутом — произвольная. «У нас дома всё прошло» означает «грубых дыр нет», и только.


203.7 Когда в лабораторию и что взять с собой

В лабораторию идут, когда изделие продаётся или встраивается в чужие системы: перечень формальных испытаний зависит от рынка и класса изделия, а домашняя проверка из 203.6 экономит платные часы — на нормированном стенде дорого искать то, что нашлось бы зажигалкой.

Собранный к поездке набор отличает подготовленную команду:


203.8 Грабли

На столе всё проходит, у заказчика падает. Кабель — часть антенны: другой длины и укладки хвост меняет и эмиссию, и стойкость; λ/4 для пятой гармоники 72 МГц — всего 21 см. Испытывать со штатными кабелями, уложенными по-боевому.

Сторож перезапускает, а прибор всё равно «мёртв». Помеха перещёлкнула регистр конфигурации: цикл крутится, сторож сыт, периферия молчит. Нужна сверка и восстановление конфигурации (203.5), а не только IWDG.

Экран есть — толку нет. Экран кабеля подпаян «косичкой» 10 см: это ~100 нГн, и фронт разряда поднимает землю экрана на ~2,4 кВ. Экран — на корпус у самого входа, коротко или по окружности.

Разряд в пластиковую кнопку валит прибор. Пробой идёт не сквозь пластик, а по щели вокруг кнопки к дорожкам за ней: при ~3 кВ/мм восьми киловольт хватает почти на 3 мм воздуха. Дорожки и контакты отводят от щелей, щели закрывают.

Замедлили фронты — интерфейс перестал успевать. Скорость вывода — минимально достаточная, а не минимальная: фронт входит в бюджет времени сигнала, у быстрых шин — жёстко (раздел 132г).

«Развязали» землю разрезом — помех стало больше. Обратный ток пошёл в обход разреза большой петлёй, петля стала антенной (раздел 181). Сплошная земля почти всегда лучше художественных разрезов.

Импульсник шумит только под нагрузкой. На холостом ходу преобразователь пропускает импульсы и токи малы; слушать приёмником и снимать эмиссию — под рабочей нагрузкой.


203.9 Итоги

Полные исходники

emc_guard.c — сверка конфигурации периферии после помехи.

/* Раздел 203.5: сверка конфигурации периферии после помехи.
 *
 * На плате в cfg_addr[] кладут адреса регистров конфигурации:
 * &GPIOA->CRL, &USART1->CR1, &TIM2->CR1, ... — только конфигурацию,
 * не данные и не флаги. Здесь, на компьютере, вместо периферии —
 * массив fake_regs, а «помеха» перещёлкивает в нём один бит.
 *
 * Сборка на ПК:  gcc -O2 -Wall -Wextra -o emc_guard emc_guard.c && ./emc_guard
 * Для кристалла: arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -O2 -DNO_HOST_TEST -c emc_guard.c
 */
#include <stdint.h>
#ifndef NO_HOST_TEST
#include <stdio.h>
#endif

enum { NCFG = 8 };
volatile uint32_t *cfg_addr[NCFG];         /* что охраняем: заполняется при инициализации */
static uint32_t cfg_good[NCFG];            /* эталон после инициализации */
static uint32_t cfg_ref;                   /* его контрольная сумма */

static uint32_t cfg_crc(void)
{
    uint32_t crc = 0xFFFFFFFFu;
    for (int i = 0; i < NCFG; i++) {
        crc ^= *cfg_addr[i];
        for (int b = 0; b < 32; b++)
            crc = (crc >> 1) ^ (0xEDB88320u & (0u - (crc & 1u)));
    }
    return crc;
}

void cfg_snapshot(void)                    /* вызвать после полной инициализации */
{
    for (int i = 0; i < NCFG; i++)
        cfg_good[i] = *cfg_addr[i];
    cfg_ref = cfg_crc();
}

int cfg_guard(void)                        /* из главного цикла, раз в десятки мс */
{
    if (cfg_crc() == cfg_ref)
        return 0;                          /* всё на месте — дёшево: одна сумма */
    int fixed = 0;
    for (int i = 0; i < NCFG; i++)
        if (*cfg_addr[i] != cfg_good[i]) {
            *cfg_addr[i] = cfg_good[i];    /* вернуть как было */
            fixed++;
        }
    return fixed;                          /* и записать событие в журнал */
}

#ifndef NO_HOST_TEST
static volatile uint32_t fake_regs[NCFG];  /* «периферия» для опыта на ПК */

int main(void)
{
    for (int i = 0; i < NCFG; i++) {       /* «инициализация периферии» */
        fake_regs[i] = 0xB4430000u + 0x111u * (uint32_t)i;
        cfg_addr[i] = &fake_regs[i];
    }
    cfg_snapshot();
    printf("эталон: %d регистров, CRC 0x%08X\n", NCFG, cfg_ref);
    printf("тихий проход: guard=%d (расхождений нет)\n", cfg_guard());

    fake_regs[3] ^= 1u << 13;              /* «помеха» перещёлкнула бит */
    printf("помеха: бит 13 регистра 3 перещёлкнут, CRC 0x%08X\n", cfg_crc());
    printf("guard: восстановлено регистров: %d\n", cfg_guard());
    printf("после восстановления: CRC %s\n",
           cfg_crc() == cfg_ref ? "совпал" : "НЕ совпал");

    fake_regs[1] ^= 1u << 0;               /* и два регистра сразу */
    fake_regs[6] ^= 1u << 31;
    int fixed = cfg_guard();
    printf("помеха в двух регистрах: guard=%d, CRC %s\n",
           fixed, cfg_crc() == cfg_ref ? "совпал" : "НЕ совпал");
    return 0;
}
#endif

Дальше: раздел 204 «Надёжность: запасы, старение и испытания у себя» — прибор пережил помеху; теперь — чтобы жил годами.

Открыть в интерактивном справочнике