206. Certification: conformity assessment and radio modules
The board has been assembled at the factory (199), powered up (200), passed the line (201–202) and withstands interference (203). One obstacle is left, and neither a soldering iron nor a debugger can take it: the right to sell. In almost any market, selling electronics means conformity assessment: tests, documents and a mark on the enclosure. For a microcontroller developer there are two practical questions here: what exactly will be tested on your product — and why a product with radio is almost always better off with a ready-made certified module than with its own transmitter. This section is a map: no regulation numbers (they change and depend on the product — the laboratory will name them), but with the arithmetic of the decisions and a recipe for the test firmware the test bench will ask for.
The numbers in this section come from two runs: the "module versus your own radio" comparison
and the economics of pre-compliance — _verify/cert206/cost.py in conventional
units (c.u.) with explicit assumptions; the test modes in rf_test.c were built
and run on a PC (stm-lab:1) and built for Cortex-M3 (stm-arm:1).
Terms used in the documentation
Term Meaning conformity assessment confirming that a product may be put on the market declaration of conformity the manufacturer declares conformity and is liable for it accredited laboratory a laboratory whose test report the regulator accepts test report results for each kind of test technical file the set of evidence: schematics, calculations, test reports intentional radiator a product that transmits a radio signal itself modular approval the approval of a radio module carries over to the product host product the device into which a ready-made module is built continuous wave (CW) an unmodulated carrier: a "bare" signal for measurements
206.1 Selling a device means conformity assessment
While a device lives on your desk or in your own workshop, no conformity system is interested in it. Everything changes the moment the product leaves your hands: it is sold, rented out, built into someone else's installation. From that moment it is not the "circuit" that answers for it, but the manufacturer — and almost every market requires you to show what backs that responsibility.
Conformity systems in different markets work in a similar way, but have different names:
- EAEU (Eurasian Economic Union; Russia's home market): depending on the kind of product, you issue either a declaration (the manufacturer declares, relying on the test reports of an accredited laboratory) or a certificate (issued by an independent body after its own checks). Which of the two your product needs is the first question for the certification body or the laboratory, not a matter of guesswork.
- CE (the European market): based on self-declaration: the manufacturer collects the evidence, signs the declaration and bears the responsibility; for radio products an independent body is, in effect, involved in the process.
- FCC (the US market): primarily about radio: unintentional radiators go through a simplified path, intentional ones through a full approval with test reports from an accredited laboratory.
What all three have in common: the manufacturer is liable, the evidence is test reports, and the "paper" is not the laboratory's property but your statement, backed by the test reports. And one more thing in common: an approval in one market is not valid in another — this will hurt in 206.3.
⚠️ Conformity is assessed for the complete product — as the customer sees it: with the enclosure, the standard cables and the power supply. A "certified board" without an enclosure is not a thing: change the enclosure or the power supply and you have, in effect, changed the product (206.6).
206.2 What is tested on electronics
An electronic product has three typical exams, and all three are already familiar from neighbouring sections:
- EMC (section 203): the product does not disturb its neighbours and does not fail from their interference. Practically every electronic product takes it.
- Electrical safety (section 208): the product does not give shocks and does not catch fire. How strict it is depends on the power supply: anything that plugs into the mains is tested seriously; for a battery device with a safe voltage this exam is, in effect, easy.
- Radio: only for intentional radiators: power, occupied bandwidth, spurious emissions, behaviour on the edge channels. A device without radio does not take this exam at all — but its emissions as an unintentional radiator are still measured as part of EMC.
The map "which product → which tests", roughly:
| Product | EMC | Safety | Radio |
|---|---|---|---|
| battery sensor, no radio | yes | minimal | no |
| mains-powered device | yes | full | no |
| product with a ready-made certified module | yes, as the host | depends on supply | covered by the module approval |
| product with its own radio | yes | depends on supply | full cycle |
Special classes — medical, transport, explosion-proof design — carry their own additional systems on top of these three; if your product is one of them, the list of tests is discussed with the certification body before the board layout, not after.
The module row is the most interesting one: one row of the table differs from its neighbour by a whole cycle of radio tests. How much that is in money is the next subsection.
206.3 A radio module or your own radio
"Your own radio" is not only a transceiver laid out on your board; a microcontroller with built-in radio (the STM32WB and STM32WL families, appendices A17–A18) is, from the testing point of view, also your radio: you are the manufacturer of a transmitter with everything that follows from it. The alternative is a ready-made module with modular approval: its radio part has already been tested by the module manufacturer, and the approval carries over to your host product — provided you meet the conditions in the module documents: an antenna from its list (or the built-in one), supply within tolerance, and firmware that does not push the radio parameters beyond the permitted limits.
The honest arithmetic is in conventional units, because laboratory and module prices
vary from market to market; what matters is not the amounts but the ratio
(run cost.py, the assumptions are in the same file):
- the extra cost of a module over your own RF part is Δ, of the order of 100–400 c.u. per unit;
- your own radio path up to series production is C: RF design, board iterations and a full cycle of radio tests, of the order of 500000–3000000 c.u.;
- tests of the host product itself are needed in both cases — they drop out of the comparison.
The break-even point is the production run at which your own radio pays off:
N* = C / Δ (c.u. / (c.u./unit) = units):
C\Δ 100 200 400
500000 5000 2500 1250
1000000 10000 5000 2500
2000000 20000 10000 5000
3000000 30000 15000 7500
Over the whole grid of assumptions N ranges from 1250 to 30000 units; at the central point (C = 1000000, Δ = 200) it is 5000. For a run of 1000 units the module costs 200000 c.u. of extra cost against a million to enter your own radio — 5 times cheaper, and that is without the months of RF board iterations and without the risk of retesting. Hence the small-run rule: radio is bought as a module*, and you build your own radio when the count reaches tens of thousands of units — or when a module physically does not fit in size, power consumption or frequency band.
🔧 How to choose a module. Before the board layout, open the module documents and check four things: the approvals exist for your markets (an approval does not carry over between systems); your antenna is the built-in one or from the module list; the approval is valid and the module is not at the end of its life cycle (otherwise recertification will land on you); the module board has test pads brought out and test modes available — the laboratory will thank you.
206.4 The laboratory: what it will ask for and what to put in the firmware
The kit you prepare for testing resembles the list from 203.7, but for a radio product one more item is added, and it is the one most often remembered only at the test bench. The laboratory will ask for:
- two or three samples, complete, with the standard cables and the standard power supply;
- a product description: what it does, how it is powered, which interfaces and radio bands it has, what the transmitter power is;
- schematics, photos, a user manual: they go into the technical file;
- a way to control the product on the bench: exactly those test modes.
The regular firmware is almost useless for measurements: the stack transmits short
packets with random pauses, listens to the air, hops between channels
and goes to sleep. The measuring instrument, however, needs a stable worst case: a carrier
without modulation on a given channel — including the edge ones, back-to-back packets,
pure reception and the point of maximum current consumption. These modes are built into the firmware
in advance and triggered through the service console of the mini-projects (196–198) —
all our radio code already sits behind the radio_reg() driver, so the commands
come down to a table:
struct cmd {
const char *name; /* слово команды консоли */
void (*run)(int ch);
uint8_t need_ch; /* команде нужен номер канала */
};
static const struct cmd cmds[] = {
{ "cw", rf_cw, 1 }, /* эмиссия: несущая на канале */
{ "pkt", rf_pkt, 1 }, /* занятая полоса «как в жизни» */
{ "rx", rf_rx, 1 }, /* стойкость приёмника */
{ "off", rf_off, 0 }, /* вернуть штатный режим */
{ "max", load_max, 0 }, /* наибольшее потребление */
{ "stat", stat_show, 0 }, /* жив / сколько перезапусков */
};
Each handler is a few writes to the radio module registers; the register numbers of your module will be different, from its datasheet:
static void rf_cw(int ch) /* несущая без модуляции */
{
radio_reg(R_CHAN, (uint8_t)ch);
radio_reg(R_PWR, PWR_MAX); /* испытывают на максимуме мощности */
radio_reg(R_MODE, M_TX_CW);
reply("cw: канал ", (uint32_t)ch, ", несущая без модуляции, мощность максимум");
}
A run on a PC with a stub instead of the radio (rf_test.c, a hypothetical module
with 16 channels): the console answers every command and does not allow
going beyond the channel grid —
> cw 15
радио <- регистр 0x02 = 15
радио <- регистр 0x03 = 8
радио <- регистр 0x01 = 3
cw: канал 15, несущая без модуляции, мощность максимум
> cw 16
? канал: 0..15
> stat
stat: жив, перезапусков 0
The stat command is the "alive / restarted" criterion from 203.7: without it,
a short glitch on the immunity bench goes unnoticed. For
Cortex-M3 the whole set — six commands with string parsing — built
into 1103 bytes of code and 84 bytes of RAM: cheaper than one hour of bench time.
⚠️ The test modes must not ship to the customer. A device that,
on a console command, turns into a continuous transmitter at maximum
power is unacceptable in the field — and the module approval is valid only while the
firmware does not push the radio parameters beyond the permitted limits. For testing,
build a separate firmware (a build flag, like NO_HOST_TEST
in rf_test.c) or lock the console with a service jumper; record the version of the
tested firmware — it goes into the test report.
206.5 Pre-compliance: weed it out at home
A formal test cycle costs noticeable money and means a queue of weeks, so coming to the laboratory with an unexamined product is a way to pay twice. The bench from 203.6 — a piezo lighter, a relay buzzer, a receiver, and for radio products an SDR dongle as well, which shows the carrier and its harmonics "before and after" a fix — weeds out the gross holes: a product that fails from a discharge to the enclosure; a switching regulator the receiver hears across the whole room; and, finally, firmware without test modes.
The arithmetic is the same as in the whole section — ratios, not amounts (run
cost.py): a full test cycle is of the order of 100000 c.u.; a failure
means rework and a second visit — in effect 30–50 % of the cycle
and lost months; a home bench is of the order of 1000 c.u., that is
about 1 % of the cycle. One problem caught at home pays for the bench
30–50 times over. What the bench will not show is also from 203.6: the margin in decibels
and the band mask are confirmed only by a standardised test site.
A sensible order for a product with radio: your own bench → if in doubt, a day of measurements without a test report (many laboratories offer this — it is cheaper than the formal cycle) → the formal cycle with test reports. Each step filters out holes that would cost an order of magnitude more at the next one.
206.6 After the tests: marking, documents, changes
The test reports are in, the declaration or certificate is issued — what remains are three obligations that live longer than the project itself.
Marking. The market's conformity mark goes on the product or the packaging (in the home market, the EAEU circulation mark; in the European one, the CE mark), next to the model, the manufacturer and everything else your system requires; products with a module inside, in effect, often also carry the text "contains module such-and-such" with the module's approval number. What exactly to write comes from the documents of your system and of the module, not from photos of other people's enclosures.
Technical file. A declaration without evidence is just a statement: the file holds the test reports, schematics, description, user manual, photos, the list from 199 and the version of the tested firmware. It is kept for years — in effect around ten years; in an inspection or a claim it is your only defence.
Product changes. Conformity is confirmed for a specific configuration — and every change is checked against it:
| What changed | What to do |
|---|---|
| a part replaced by an equivalent from the list | an entry in the change log |
| switching supply, board layout, enclosure | repeat the affected part of the tests |
| antenna or radio module | the radio part again: the module approval no longer covers it |
| firmware: logic, interface | an entry + your own tests (201) |
| firmware: clocks, edges, radio power | in effect a new product — back to measurements |
Series production must match the tested sample: "equivalent" substitutions in purchasing (199.2) go through the developer, they are not decided in the warehouse.
206.7 Pitfalls
"The module is certified, so the product is certified." No: modular approval covers only the radio part. The host product still takes its own exams — EMC as a complete product and safety according to its supply; its row of the table in 206.2 is shorter than its neighbours, but not empty.
You fitted a "better" antenna — and the approval stopped being valid. A higher-gain antenna that is not in the module list makes you the manufacturer of a new transmitter — with the full cycle of radio tests. The antenna is chosen from the module documents before the layout, not by what is in stock.
The module is approved — but not for your market. An FCC approval is not valid in the EAEU, an EAEU one is not valid in Europe, and vice versa: these are different systems with different test reports. The module's list of approvals is checked against the product's list of markets — in writing, before ordering a batch of modules.
The laboratory asks for a carrier — and the firmware can only "send a packet". The regular stack cannot do CW on a given channel or back-to-back packets; adding test modes through correspondence with the bench is the most expensive engineering hours of the project. The six commands from 206.4 take an evening to write before the trip.
You brought a sample with a lab power supply and a short cable. The test report applies to the tested assembly: at the customer's, with a different supply and a one-metre cable, the product is already a different antenna with different emissions (203.2). Test with the standard cables of standard length — as you sell it.
After the tests you "slightly" updated the firmware. The firmware version is part of the tested configuration: changing clocks, edges or radio power changes the measured values. You may change logic with your own checks; anything that affects emissions is a reason to go back to measurements (206.6).
206.8 Summary
- Selling = conformity assessment: in the EAEU a declaration or a certificate, under CE a self-declaration, under the FCC a radio approval; the manufacturer is always liable, the evidence is test reports from an accredited laboratory, approvals do not carry over between markets.
- There are three exams: EMC (203) for almost everyone, electrical safety (208) depending on the supply, radio only for intentional radiators.
- Module versus your own radio: N* = C/Δ; over the grid of assumptions (Δ = 100–400 c.u./unit, C = 0.5–3 million c.u.) the break-even point is from 1250 to 30000 units, 5000 at the centre; a run of 1000 units with a module is 5 times cheaper than entering your own radio.
- Test modes for the bench: six console commands (cw, pkt, rx, off, max, stat), a hypothetical module with 16 channels, protection against a channel outside the grid; on Cortex-M3: 1103 bytes of code and 84 bytes of RAM.
- Pre-compliance: a home bench costs about 1 % of a test cycle, one catch pays for it 30–50 times over; the margin is confirmed only by the laboratory.
- Afterwards: the mark on the enclosure, the technical file kept around ten years, changes checked against the tested configuration; the antenna, the module and the firmware's radio parameters are reasons for new measurements.
Full sources
rf_test.c — radio test modes for the laboratory.
/* Раздел 206.4: тестовые режимы радиочасти для лаборатории.
*
* Штатный стек передаёт пакетами, слушает эфир и уходит в сон — лаборатории
* этого мало: ей нужны непрерывная несущая на заданном канале, пакеты
* вплотную, чистый приём и точка наибольшего потребления. Эти режимы
* зашиваются в прошивку заранее и дёргаются командами сервисной консоли
* (разделы 196–198). Здесь, на компьютере, вместо радиомодуля — заглушка,
* печатающая записи в его регистры; сами команды и разбор — те же, что
* поедут в изделие.
*
* Сборка на ПК: gcc -O2 -Wall -Wextra -o rf_test rf_test.c && ./rf_test
* Для кристалла: arm-none-eabi-gcc -mcpu=cortex-m3 -mthumb -Os -DNO_HOST_TEST -c rf_test.c
*/
#include <stdint.h>
#ifndef NO_HOST_TEST
#include <stdio.h>
#endif
void con_out(const char *s); /* строка в консоль: у изделия — UART */
void radio_reg(uint8_t reg, uint8_t val); /* запись регистра радиомодуля — драйвер */
uint32_t reset_count; /* сколько раз перезапускались: журнал, 12.4 */
static uint8_t no_sleep; /* 1 = не спать: точка наибольшего потребления */
enum { NCHAN = 16, PWR_MAX = 8 }; /* каналы и шаги мощности нашего модуля */
/* регистры условного модуля — у вашего будут свои, из даташита */
enum { R_MODE = 0x01, R_CHAN = 0x02, R_PWR = 0x03 };
enum { M_SLEEP = 0, M_RX = 1, M_TX_PKT = 2, M_TX_CW = 3 };
static char *dec(char *p, uint32_t v) /* число в строку, без printf */
{
char t[10];
int n = 0;
do { t[n++] = (char)('0' + v % 10); v /= 10; } while (v);
while (n)
*p++ = t[--n];
*p = 0;
return p;
}
static void reply(const char *a, uint32_t n, const char *b)
{
static char line[80];
char *p = line;
while (*a) *p++ = *a++;
p = dec(p, n);
while (*b) *p++ = *b++;
*p = 0;
con_out(line);
}
static void rf_cw(int ch) /* несущая без модуляции */
{
radio_reg(R_CHAN, (uint8_t)ch);
radio_reg(R_PWR, PWR_MAX); /* испытывают на максимуме мощности */
radio_reg(R_MODE, M_TX_CW);
reply("cw: канал ", (uint32_t)ch, ", несущая без модуляции, мощность максимум");
}
static void rf_pkt(int ch) /* пакеты вплотную, без пауз протокола */
{
radio_reg(R_CHAN, (uint8_t)ch);
radio_reg(R_PWR, PWR_MAX);
radio_reg(R_MODE, M_TX_PKT);
reply("pkt: канал ", (uint32_t)ch, ", пакеты вплотную, пауза 0");
}
static void rf_rx(int ch) /* чистый приём: стойкость приёмника */
{
radio_reg(R_CHAN, (uint8_t)ch);
radio_reg(R_MODE, M_RX);
reply("rx: канал ", (uint32_t)ch, ", только приём, передатчик выключен");
}
static void rf_off(int ch)
{
(void)ch;
no_sleep = 0;
radio_reg(R_MODE, M_SLEEP);
con_out("off: радио в сон, изделие в штатный режим");
}
static void load_max(int ch) /* для замера питания и провалов сети */
{
(void)ch;
no_sleep = 1; /* главный цикл не зовёт WFI */
rf_cw(NCHAN / 2);
con_out("max: ядро без сна, передатчик включён — снимайте потребление");
}
static void stat_show(int ch) /* критерий «жив» для стойкости, 203.7 */
{
(void)ch;
reply("stat: жив, перезапусков ", reset_count, "");
}
struct cmd {
const char *name; /* слово команды консоли */
void (*run)(int ch);
uint8_t need_ch; /* команде нужен номер канала */
};
static const struct cmd cmds[] = {
{ "cw", rf_cw, 1 }, /* эмиссия: несущая на канале */
{ "pkt", rf_pkt, 1 }, /* занятая полоса «как в жизни» */
{ "rx", rf_rx, 1 }, /* стойкость приёмника */
{ "off", rf_off, 0 }, /* вернуть штатный режим */
{ "max", load_max, 0 }, /* наибольшее потребление */
{ "stat", stat_show, 0 }, /* жив / сколько перезапусков */
};
static int str_eq(const char *a, const char *b)
{
while (*a && *a == *b) { a++; b++; }
return *a == *b;
}
void rf_console(const char *line) /* вызвать из приёма сервисной консоли */
{
char word[8];
unsigned wl = 0;
int ch = -1;
const char *p = line;
while (*p && *p != ' ' && wl + 1 < sizeof word)
word[wl++] = *p++;
word[wl] = 0;
if (*p == ' ') { /* необязательный номер канала */
ch = 0;
for (p++; *p >= '0' && *p <= '9'; p++)
ch = ch * 10 + (*p - '0');
}
for (unsigned i = 0; i < sizeof cmds / sizeof cmds[0]; i++)
if (str_eq(word, cmds[i].name)) {
if (cmds[i].need_ch && (ch < 0 || ch >= NCHAN)) {
con_out("? канал: 0..15");
return;
}
cmds[i].run(ch);
return;
}
con_out("? команды: cw pkt rx off max stat");
}
#ifndef NO_HOST_TEST
void con_out(const char *s)
{
printf("%s\n", s);
}
void radio_reg(uint8_t reg, uint8_t val)
{
printf(" радио <- регистр 0x%02X = %u\n", reg, val);
}
int main(void)
{
static const char *script[] = {
"cw 0", "cw 15", "cw 16", "pkt 7", "rx 7",
"max", "off", "stat", "qq",
};
for (unsigned i = 0; i < sizeof script / sizeof script[0]; i++) {
printf("> %s\n", script[i]);
rf_console(script[i]);
}
printf("no_sleep после off: %u\n", no_sleep);
return 0;
}
#endif
Next: section 206а "EAEU certification step by step" — regulations, declaration or certificate, scheme, the EAC mark.