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 Что стареет первым
Стареет не «прибор вообще» — стареют конкретные детали, каждая по своему механизму.
Электролитические конденсаторы — почти всегда первые: электролит
сохнет, и скорость сушки удваивается на каждые 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: запаса нет, и это ещё без соседей.
Практические следствия:
- Считать от воздуха у платы, не от комнаты. Закрытый корпус без вентиляции сам по себе тёплый: внутри на десятки градусов выше комнаты, если в нём рассеиваются ватты.
- МК редко главный печник. Линейный стабилизатор 12 → 3,3 В при
100 мА рассеивает 0,87 Вт — в 2,3 раза больше, чем весь F407, и в 5
раз больше, чем F103 (
therm_calc.py); выбор преобразователя — раздел 55. Греют и драйверы, и силовые ключи — и греют соседей: электролит рядом с ними стареет по правилу 10 °C. - Теплоотвод и продув нужны, когда перегрев считается уже не в градусах, а в десятках: θJA в неподвижном воздухе принципиально не уменьшить программно. Радиатор снижает тепловое сопротивление горячей детали, обдув — всей коробки; но каждый вентилятор — сам деталь с ресурсом, его отказ тоже идёт в расчёт.
🔧 Перегрев измеряется, а не только считается. Встроенный датчик температуры кристалла (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(¤t);
dirty = 0;
}
}
void cfg_power_down(void) /* по прерыванию PVD: питание уходит */
{
if (dirty) {
cfg_save(¤t); /* дописать, пока держит конденсатор */
dirty = 0;
}
}
В прогоне сутки дали 15 сохранений вместо 192 — журнала хватает на 116,9 года: ресурс Flash перестал быть самой короткой строкой в списке старения. Куда класть коэффициенты калибровки — 202.5; им отложенная запись не нужна: их пишут один раз на линии.
Журнал отказов изделия. Строка о выпуске каждой платы уже лежит в вашем журнале производства (201.7); прибор должен вести встречный — о своей жизни: счётчики сбросов по причинам, часы наработки, максимум температуры кристалла, срабатывания сверки конфигурации (203.5). Пишется он редко — раз в сутки и по событию, — так что ресурса почти не тратит, а при возврате превращает «не работает» в диагноз (204.7).
204.7 Разбор отказов: возвраты и «не воспроизводится»
Возврат — самый дорогой и самый информативный экземпляр партии: прибор, который нашёл слабое место конструкции за вас. Порядок обращения:
- Сначала зафиксировать, потом чинить. Фото, внешний осмотр, чтение журнала отказов и флагов сброса — до первой пайки: ремонт уничтожает улики. Половина причин видна глазами — по следам перегрева, коррозии и механики.
- «Не воспроизводится» — не вердикт, а симптом. Прибор, который на столе работает, вернули не просто так. Смотреть журнал (сбросы? максимум температуры?), расспрашивать про окружение — шкаф, солнце, контактор за стеной (203) — и греть на стенде 204.5: плавающие отказы чаще всего температурные или помеховые.
- Искать общее, а не чинить поштучно. Серийный номер ведёт в журнал выпуска (201.7): одна партия деталей? одна версия платы? одни числа калибровки на границе допуска? Три возврата с одинаковым отказом — это не три случайности, а один системный дефект.
- Методика поиска причины на плате — та же, что при первом включении (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 Итоги
- «Ванна отказов»: ранние отказы срезает прогон до отгрузки, дно описывает MTBF, правую стенку задаёт самая быстро стареющая деталь. MTBF 100 000 ч — это 8,4 % отказов за первый год, а не «11 лет без отказа»; FIT складываются: 100 деталей по 50 FIT — MTBF 200 000 ч.
- Правило 10 °C: минус десять градусов — вдвое дольше жизнь. Электролит 2000 ч/105 °C: 3,7 года при 65 °C, 14,6 года при 45 °C; термоциклы качают паяные соединения на микроны за цикл — усталость.
- Flash F1 и F4: 10 000 стираний; удержание 30 лет при 85 °C после 1 тыс. циклов, 10 лет при 105 °C, 20 лет при 55 °C после всех 10 тыс. — изношенная и горячая Flash забывает быстрее.
- Деррейтинг: 50 % мощности, 50–80 % напряжения, минус 20–30 °C
от предела; обоснование — квадрат (
I²,U²) и экспонента старения. - Перегрев = P·θJA: F103 в LQFP48 — +9,1 °C, F407 в LQFP100 — +16,6 °C; при 85 °C вокруг F407 — 102 °C из 105 допустимых. Главные печники — стабилизаторы и ключи (0,87 Вт у линейного 12 → 3,3 В при 100 мА).
- Испытания у себя: неделя при 60 °C ≈ ×11 ускорение (≈ 2,6 месяца жизни), реле-циклер — 2880 включений в сутки; они находят дыры, но не измеряют MTBF — статистику дают заказчики через журнал отказов.
- Прошивка: сторож + журнал отказов; запись настроек — только журналом
и отложенно: 52 дня → 9,1 года → 116,9 года в модели
wear_budget.c.
Полные исходники
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(¤t);
dirty = 0;
}
}
void cfg_power_down(void) /* по прерыванию PVD: питание уходит */
{
if (dirty) {
cfg_save(¤t); /* дописать, пока держит конденсатор */
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а «Корпус прибора» — как получить корпус из той же модели платы и проверить его до печати.