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

204. Надёжность: запасы, старение и испытания у себя

Изделие собрано (199), включилось (200), проходит тест на линии (201), откалибровано (202) и пережило помеху (203). Остался вопрос, на который не отвечает ни один стенд одним измерением: сколько оно проживёт? Надёжность нельзя «допаять» в конце — она складывается из запасов, заложенных в схему, из того, как быстро стареют конкретные детали, и из испытаний, которые находят слабое место до заказчика. Всё это доступно и без лаборатории: арифметика старения умещается на листке, а прогон при повышенной температуре — в коробке с лампой.

Числа раздела — расчёты _verify/rel204/aging_calc.py и therm_calc.py; ресурс Flash, удержание и тепловые сопротивления — из даташитов F103 и F407 в паках (достаёт flash_ds.py); модель записи настроек wear_budget.c собрана gcc 12 в образе stm-lab:1 и прогнана — числа сохранений взяты из её вывода.

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

Оригинал Перевод
mean time between failures (MTBF) наработка на отказ
failure rate, FIT интенсивность отказов; 1 FIT — один отказ на миллиард прибор-часов
bathtub curve «ванна отказов»: ранние отказы, плато, износ
infant mortality ранние отказы первых часов работы
wear-out износовые отказы: ресурс детали кончился
acceleration factor во сколько раз жёсткий режим ускоряет старение
power cycling циклы включения-выключения
elevated temperature soak выдержка под напряжением при повышенной температуре
no fault found (NFF) «дефект не подтвердился» при разборе возврата

204.1 Надёжность в числах: наработка на отказ и «ванна отказов»

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

Кривая ванны отказов: спадающий склон ранних отказов, плоское дно нормальной эксплуатации и растущий склон износа, с подписями что срезает склоны

Наработка на отказ (MTBF) описывает только дно. MTBF = 100 000 ч — это не «прибор живёт 11 лет», а «на дне ванны отказы случаются в среднем раз в 100 000 часов». Для одного прибора это вероятность: шанс отказать в первый год — 1 − exp(−8760/100 000) = 8,4 %; из сотни приборов у заказчиков за год откажет примерно восемь (aging_calc.py). Срок службы задаёт не MTBF, а правая стенка ванны — самая быстро стареющая деталь: прибор с расчётным MTBF в десятки лет и электролитом у горячего стабилизатора кончится за три года.

Интенсивности отказов складываются: прибор из 100 деталей по 50 FIT — это 5000 FIT, наработка 10⁹/5000 = 200 000 ч, около 23 лет. Отсюда два следствия. Каждая лишняя деталь — вклад в знаменатель: схема из половины деталей вдвое надёжнее при прочих равных. И один плохой компонент портит всю сумму: FIT у деталей отличаются на порядки, поэтому охотиться надо не «за надёжностью вообще», а за худшей строкой списка — ей и посвящён следующий подраздел.

⚠️ Ранние отказы срезают до отгрузки. Левый склон ванны — брак, который почти проявился: он вылезет в первые десятки часов работы. Прогон собранных приборов под напряжением — на выходных, при повышенной температуре (204.5) — переносит эти отказы с участка заказчика на ваш стол. Именно поэтому «погонять неделю перед отправкой» — не суеверие, а перенос точки отказа.


204.2 Что стареет первым

Стареет не «прибор вообще» — стареют конкретные детали, каждая по своему механизму.

Карта старения: электролит сохнет от тепла, паяные соединения устают от термоциклов, разъёмы и кнопки изнашиваются циклами, Flash расходует стирания, полупроводники и резисторы деградируют от перегрева

Электролитические конденсаторы — почти всегда первые: электролит сохнет, и скорость сушки удваивается на каждые 10 °C. Паспортные 2000 ч при 105 °C превращаются (aging_calc.py, подробно — 167.6):

Температура в корпусе Срок
105 °C 2000 ч
65 °C 32 000 ч — 3,7 года
45 °C 128 000 ч — 14,6 года

Правило 10 °C — главная формула раздела: минус десять градусов — вдвое дольше жизнь. Оно же в обратную сторону: электролит, прижатый к горячему стабилизатору, стареет вдвое-вчетверо быстрее соседа в холодном углу платы.

Паяные соединения устают от термоциклов. Плата и деталь расширяются по-разному: у чип-корпуса длиной 3,2 мм при разнице коэффициентов расширения 10 ppm/°C и перепаде 60 °C концы «гуляют» на 1,9 мкм за цикл (aging_calc.py). Микроны, но каждый день включения-выключения — цикл, и за годы припой накапливает усталостные трещины — классический отказ «работает, пока не остынет». Лечится уменьшением перепадов (204.4) и механикой: тяжёлое — крепить, большие корпуса без выводов — не ставить на изгибаемый край платы (см. трещины керамики в 199.9).

Разъёмы и кнопки изнашиваются циклами: истирается покрытие контактов, растёт сопротивление, появляется дребезг там, где его не было. Ресурс — от десятков до тысяч циклов — пишет производитель в паспорте; сравните его с реальностью изделия: разъём, который дёргают десять раз в день, набирает 3650 циклов в год.

Flash микроконтроллера — единственная стареющая деталь внутри камня, и у неё ресурс задокументирован. Даташиты F103 и F407 дают одинаковые числа (flash_ds.py достаёт их из PDF паков):

Параметр (F1 и F4 — числа совпадают) Гарантия
стираний страницы или сектора 10 000
удержание после 1 тыс. циклов при 85 °C 30 лет
удержание после 1 тыс. циклов при 105 °C 10 лет
удержание после 10 тыс. циклов при 55 °C 20 лет

Прочитайте таблицу как историю старения: изношенная Flash забывает быстрее (после 10 тыс. циклов удержание меряют уже при 55 °C), а горячая — быстрее втрое: 30 лет при 85 °C против 10 лет при 105 °C, то есть ×1,7 на каждые 10 °C — рядом с правилом 10 °C. Прошивку, записанную один раз, это не тревожит; страницу с настройками, которую стирают каждый день, — очень (204.6).


204.3 Запасы: деррейтинг

Запас — это работа детали на доле от паспортного предела. Не из перестраховки: у предела деградация нелинейна, и каждая доля запаса покупает годы. Типовые доли и почему именно столько:

Параметр Типовая доля Почему именно столько
напряжение конденсаторов 50 % — тантал, 70–80 % — керамика и электролит отказ тантала — короткое замыкание (167.6); запас покрывает выброс, прошедший мимо ограничителя (173.3)
мощность резисторов 50 % номинал дан при 25 °C на открытом воздухе; в корпусе при 60 °C от него и так остаётся половина (166)
ток ключей и диодов 50–70 % нагрев растёт как квадрат тока: 70 % тока — половина мощности
температура кристаллов и электролитов минус 20–30 °C от предела правило 10 °C: минус 20 °C — вчетверо дольше жизнь

Обоснование везде одно из двух. Либо квадрат: мощность и нагрев растут как I² и U², поэтому доля 0,7 по току или напряжению — это уже половина по теплу. Либо экспонента старения: срок службы падает вдвое на каждые 10 °C, поэтому запас по температуре — самый дешёвый способ купить годы: он не требует других деталей, только другое расположение на плате.

⚠️ Запас закладывают в перечень, а не вспоминают при возврате. Доля считается не от «обычного» режима, а от худшего: максимальная сеть, максимальная нагрузка, лето, закрытый корпус. Конденсатор 16 В на шине 12 В выглядит запасом в 25 %, пока не вспомнить про выброс до 14,5 В от зарядки аккумулятора — остаётся 9 %.


204.4 Тепло: перегрев по тепловому сопротивлению

Температура — множитель всех механизмов старения, поэтому тепловой расчёт — первый расчёт надёжности. Даташит даёт тепловое сопротивление кристалл-среда θJA в °C/Вт, и перегрев считается в одну строку: T_кристалла = T_среды + P · θJA.

Корпус θJA, F103 θJA, F407
LQFP48 7×7 мм 55 °C/Вт —
LQFP64 10×10 мм 45 °C/Вт 46 °C/Вт
LQFP100 14×14 мм 46 °C/Вт 43 °C/Вт
LQFP144 20×20 мм — 40 °C/Вт

Считаем худший случай по даташитам (therm_calc.py). F103 в LQFP48 на 72 МГц со всей периферией — не больше 50 мА: P = 3,3 В × 50 мА = 0,165 Вт, перегрев 0,165 × 55 = 9,1 °C. F407 в LQFP100 на 168 МГц — до 117 мА: P = 0,386 Вт, перегрев 0,386 × 43 = 16,6 °C. В комнате это никого не волнует. Но поставьте прибор в шкаф на солнце, где вокруг платы 85 °C, — кристалл F407 окажется на 102 °C при пределе 105 °C: запаса нет, и это ещё без соседей.

Практические следствия:

🔧 Перегрев измеряется, а не только считается. Встроенный датчик температуры кристалла (14.7) читается двумя строками: снимите его сразу после холодного включения и через полчаса работы в закрытом корпусе — разница и есть ваш реальный перегрев плюс нагрев коробки. Горячие точки на плате находятся термистором или DS18B20 (96), прижатыми к деталям, — или пальцем, но палец не пишет журнал.


204.5 Испытания у себя: прогон, температура, циклы

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

Прогон при повышенной температуре. Коробка из фанеры, лампа накаливания или ТЭН с терморегулятором, термометр — и приборы работают неделю при 60 °C под штатной нагрузкой. Повышенная температура — ускоритель времени: по правилу 10 °C переход 25 → 60 °C ускоряет химическое старение в 11 раз (более точная экспоненциальная модель с типовой энергией активации 0,7 эВ даёт 17 раз — тот же порядок, aging_calc.py). Неделя такого прогона — примерно 2,6 месяца жизни при комнатной температуре: ранние отказы (204.1) она вытаскивает почти все, а заодно проявляет зависания, которые случаются только у тёплого прибора.

Циклы включения-выключения. Реле с таймером щёлкает питание: 30 секунд цикл — 2880 циклов за сутки, за неделю — двадцать тысяч (aging_calc.py). Это проверка сразу трёх вещей: броска тока при включении, корректности старта прошивки из любого состояния и термоциклов «включили-прогрелся-выключили-остыл» в миниатюре. Прибор при этом должен не просто включаться, а каждый раз доживать до рабочего состояния — проверяет это прошивка с журналом (204.6), а не человек у стенда.

Честные оговорки — что домашний стенд покажет и чего нет:

Стенд Покажет НЕ покажет
неделя при 60 °C ранние отказы, «виснет тёплым», слабые электролиты влагу, вибрацию, нормированный ресурс
циклы питания бросок тока, старт из любого состояния ресурс разъёмов и кнопок — их щёлкают отдельно
оба вместе грубые дыры конструкции статистику: MTBF на трёх штуках не измерить

⚠️ Три прибора за месяц — не статистика. Отсутствие отказов у трёх экземпляров доказывает только отсутствие грубых дефектов. Настоящая статистика надёжности набирается там же, где живут приборы, — у заказчиков; чтобы она не пропала, каждый прибор возит с собой журнал (204.6), а каждый возврат разбирается (204.7).


204.6 Прошивка и ресурс

Прошивка не стареет — но распоряжается тремя вещами, которые стареют или спасают.

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

Запись настроек — с бюджетом ресурса. У страницы Flash 10 000 стираний (204.2), и наивная прошивка тратит их незаметно. Модель wear_budget.c: пользователь крутит яркость каждые 5 минут по 16 часов в день — 192 изменения за сутки:

запись при каждом изменении  192 зап./сут; без журнала    52 дн; журнал 11.8:   3333 дн =   9.1 лет
отложенная запись (прогон)   15 зап./сут; без журнала   666 дн; журнал 11.8:  42666 дн = 116.9 лет

Запись «сразу и в одну страницу» убивает прибор за 52 дня. Журнал на двух страницах (11.8) растягивает ресурс в 64 раза — до 9,1 года. А отложенная запись добавляет ещё порядок: настройки помечаются изменёнными, пишутся не чаще раза в час, а при уходе питания — дописываются немедленно по прерыванию детектора просадки PVD (10.7):

void cfg_mark_dirty(uint32_t now)          /* вызывать при каждом изменении */
{
    if (!dirty) {
        dirty = 1;
        dirty_since = now;
    }
}

void cfg_tick(uint32_t now)                /* раз в секунду из главного цикла */
{
    if (dirty && now - dirty_since >= WRITE_HOLDOFF_S) {
        cfg_save(&current);
        dirty = 0;
    }
}

void cfg_power_down(void)                  /* по прерыванию PVD: питание уходит */
{
    if (dirty) {
        cfg_save(&current);                /* дописать, пока держит конденсатор */
        dirty = 0;
    }
}

В прогоне сутки дали 15 сохранений вместо 192 — журнала хватает на 116,9 года: ресурс Flash перестал быть самой короткой строкой в списке старения. Куда класть коэффициенты калибровки — 202.5; им отложенная запись не нужна: их пишут один раз на линии.

Журнал отказов изделия. Строка о выпуске каждой платы уже лежит в вашем журнале производства (201.7); прибор должен вести встречный — о своей жизни: счётчики сбросов по причинам, часы наработки, максимум температуры кристалла, срабатывания сверки конфигурации (203.5). Пишется он редко — раз в сутки и по событию, — так что ресурса почти не тратит, а при возврате превращает «не работает» в диагноз (204.7).


204.7 Разбор отказов: возвраты и «не воспроизводится»

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

  1. Сначала зафиксировать, потом чинить. Фото, внешний осмотр, чтение журнала отказов и флагов сброса — до первой пайки: ремонт уничтожает улики. Половина причин видна глазами — по следам перегрева, коррозии и механики.
  2. «Не воспроизводится» — не вердикт, а симптом. Прибор, который на столе работает, вернули не просто так. Смотреть журнал (сбросы? максимум температуры?), расспрашивать про окружение — шкаф, солнце, контактор за стеной (203) — и греть на стенде 204.5: плавающие отказы чаще всего температурные или помеховые.
  3. Искать общее, а не чинить поштучно. Серийный номер ведёт в журнал выпуска (201.7): одна партия деталей? одна версия платы? одни числа калибровки на границе допуска? Три возврата с одинаковым отказом — это не три случайности, а один системный дефект.
  4. Методика поиска причины на плате — та же, что при первом включении (200.7): от питания к камню, деля схему пополам.

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


204.8 Грабли

Прибор прошёл недельный прогон — возвраты пошли через год. Прогон срезает левый склон ванны, износ он не отменяет: неделя при 60 °C — это лишь ~2,6 месяца жизни при 25 °C. Против износа работают запасы (204.3) и холодные электролиты, а не прогон.

В расчёте MTBF 23 года — электролит высох за четыре. MTBF описывает дно ванны, срок службы задаёт самая быстрая деталь на правой стенке: 2000-часовой электролит при 65 °C в корпусе — 3,7 года, и никакой MTBF это не отменит.

Настройки перестали сохраняться через два месяца. Запись при каждом изменении в одну и ту же страницу: 192 записи в сутки съедают 10 000 стираний за 52 дня. Журнал на двух страницах и отложенная запись (204.6) — годы вместо недель.

На столе работает, в шкафу летом виснет. Свои 16,6 °C перегрева у F407 плюс горячий воздух шкафа — кристалл у предела. Считать от температуры среды у платы, мерить встроенным датчиком (14.7), а не термометром на стене.

Возврат «не воспроизводится» закрыли как исправный. Без журнала отказов прибор нем: причина осталась у заказчика и вернётся следующим возвратом. Счётчики сбросов, наработку и максимум температуры пишут в каждый прибор до отгрузки (204.6).

Запас посчитан от «обычного» режима. Конденсатор 16 В на шине 12 В — запас 25 %, пока зарядка не подняла шину до 14,5 В. Доли деррейтинга (204.3) считаются от худшего случая: максимальная сеть, лето, закрытый корпус.


204.9 Итоги

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

wear_budget.c — бюджет ресурса Flash под настройки: три стратегии записи.

/* wear_budget.c — раздел 204.6: бюджет ресурса Flash под настройки.
 *
 * Модель суток: пользователь крутит яркость каждые 5 минут по 16 часов
 * в день (192 изменения). Сравниваются три стратегии записи и считается,
 * на сколько лет хватает 10 000 стираний страницы (F1 и F4) — без журнала
 * и с журналом на двух страницах из 11.8 (страница стирается раз
 * в 64 сохранения: 10 000 x 64 = 640 000 сохранений).
 *
 * gcc -Wall -Wextra -Werror -O2 -o wear_budget wear_budget.c && ./wear_budget
 */
#include <stdint.h>
#include <stdio.h>

enum { WRITE_HOLDOFF_S = 3600 };           /* не чаще раза в час */

typedef struct { uint16_t brightness; } cfg_t;
static cfg_t current;
static int dirty;                          /* настройки изменились, но не записаны */
static uint32_t dirty_since;               /* когда изменились впервые */
static long writes;

static void cfg_save(const cfg_t *c)       /* журналом из 11.8 */
{
    (void)c;
    writes++;
}

void cfg_mark_dirty(uint32_t now)          /* вызывать при каждом изменении */
{
    if (!dirty) {
        dirty = 1;
        dirty_since = now;
    }
}

void cfg_tick(uint32_t now)                /* раз в секунду из главного цикла */
{
    if (dirty && now - dirty_since >= WRITE_HOLDOFF_S) {
        cfg_save(&current);
        dirty = 0;
    }
}

void cfg_power_down(void)                  /* по прерыванию PVD: питание уходит */
{
    if (dirty) {
        cfg_save(&current);                /* дописать, пока держит конденсатор */
        dirty = 0;
    }
}

/* ── модель суток ─────────────────────────────────────────────────────── */
enum { DAY_S = 86400, ACTIVE_S = 16 * 3600, EVERY_S = 300 };
enum { ENDURANCE = 10000, JOURNAL_GAIN = 64 };

static void budget(const char *name, long per_day)
{
    long plain = ENDURANCE / per_day;                    /* дней без журнала */
    long journal = (long)ENDURANCE * JOURNAL_GAIN / per_day;
    printf("%-28s %4ld зап./сут; без журнала %5ld дн; журнал 11.8: %6ld дн = %5.1f лет\n",
           name, per_day, plain, journal, journal / 365.0);
}

int main(void)
{
    long events = 0;

    current.brightness = 0;
    for (uint32_t t = 0; t < DAY_S; t++) {
        if (t < ACTIVE_S && t % EVERY_S == 0) {          /* крутилка яркости */
            current.brightness++;
            cfg_mark_dirty(t);
            events++;
        }
        cfg_tick(t);
    }
    cfg_power_down();                                    /* конец суток: свет выключили */

    printf("изменений за сутки: %ld (каждые 5 мин по 16 ч)\n", events);
    budget("запись при каждом изменении", events);
    budget("отложенная запись (прогон)", writes);
    printf("прогон отложенной записи: %ld сохранений за сутки вместо %ld\n",
           writes, events);
    return 0;
}

Дальше: раздел 204а «Корпус прибора» — как получить корпус из той же модели платы и проверить его до печати.

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