Die meisten Bluetooth Beacon-Projekte scheitern nicht an schlechter Hardware, sondern an Firmware, die Batterien in Wochen statt Jahren leert, bei HF-Interferenz abstuerzt oder nach einem Spannungseinbruch lautlos aufhoert zu senden. Der Unterschied zwischen einem Beacon mit 3 Monaten und einem mit 3 Jahren Lebensdauer bei derselben CR2032 liegt darin, wie die Firmware Funkereignisse plant, Energiezustaende verwaltet und sich von Fehlern erholt. Dieser Artikel analysiert die Architektur produktionsreifer Beacon-Firmware am Beispiel von nRF52 + SoftDevice, da dieser ca. 70% aller kommerziellen Beacons antreibt.
1. Ueberblick: Warum die Firmware-Architektur die Batterielebensdauer bestimmt
Ein Beacon verbringt 99,97% seiner Lebensdauer im Schlaf. Bei einem 1-Sekunden-Sendeintervall und 3-Byte-Payload auf 3 Kanaelen ist das Funkmodul etwa 300 Mikrosekunden pro Sekunde aktiv. Von 86.400 Sekunden eines Tages sendet das Funkmodul insgesamt ca. 26 Sekunden. Die restlichen 86.374 Sekunden werden im Schlaf verbracht, und wie tief dieser Schlaf ist, bestimmt alles.
| Zustand |
nRF52832 Strom |
Zeit/Ereignis (1s) |
Beitrag Mittelwert |
| Deep Sleep (RAM erhalten) |
1,5 uA |
~999,6 ms |
1,499 uA |
| Ramp-up + Quarzstart |
3,2 mA |
~130 us |
0,416 uA |
| Tx Ch37 (0 dBm) |
4,6 mA |
~80 us (3 Bytes) |
0,368 uA |
| Kanalzwischenraum |
1,8 mA |
~150 us |
0,270 uA |
| Tx Ch38 + Ch39 |
4,6 mA |
~160 us |
0,736 uA |
| Ramp-down + RTC-Verarbeitung |
2,1 mA |
~90 us |
0,189 uA |
| Gesamtmittel (1s, 0 dBm, 3 Bytes) |
3,478 uA |
Bei CR2032 (~160 mAh nutzbar): 160.000 uAh / 3,478 uA = 46.000 Stunden = 5,2 Jahre. Das ist die theoretische Obergrenze. Reale Firmware addiert Sensor-Polling, LED-Blinken, Tastenabfrage, Watchdog-Interrupts und RTC-Driftkompensation, jeweils 5-50 uA. Ein einziges unnoetiges 1 ms Aufwachen pro Sekunde bei 3 mA addiert 3 uA, fast das Doppelte des Schlafbudgets.
2. Funkplaner: Wie Advertising-Ereignisse geplant werden
Das SoftDevice fungiert als praemptiver Funkplaner. Der Anwendungscode beruehrt nie direkt das Funkmodul. Man konfiguriert Advertising-Parameter, und das SoftDevice platziert Funkereignisse in seiner internen Zeitleiste.
SoftDevice Funk-Zeitleiste (pro Sendeintervall)
[RC] Tx37 [RD] gap [RC] Tx38 [RD] gap [RC] Tx39 [RD]
130us 80us 20us 130us 80us 20us 130us 80us 20us
RC = Funk Ramp-up + Quarz-Stabilisierung
RD = Funk Ramp-down
Gesamt aktiv: ~610 us
2.2 Intervall vs. Duty Cycle
| Intervall |
Ereignisse/Std |
Funk aktiv/Std |
Duty Cycle |
Mittel Funkstrom |
| 100 ms |
36.000 |
22,0 s |
0,0061% |
28,0 uA |
| 200 ms |
18.000 |
11,0 s |
0,0030% |
14,0 uA |
| 500 ms |
7.200 |
4,4 s |
0,0012% |
5,6 uA |
| 1000 ms |
3.600 |
2,2 s |
0,0006% |
2,8 uA |
| 2000 ms |
1.800 |
1,1 s |
0,0003% |
1,4 uA |
| 5000 ms |
720 |
0,44 s |
0,0001% |
0,56 uA |
Bei 100 ms verbraucht das Funkmodul allein 28 uA und ueberschreitet das Schlafbudget von 3 uA fuer 2 Jahre CR2032.
2.3 Nicht-verbindbar vs. Verbindbar
| Modus |
Extra Rx/Intervall |
Extra 1s |
Extra 5s |
| ADV_NONCONN (ohne Scan Response) |
0 ms |
0 uA |
0 uA |
| ADV_IND + Scan Response (10ms) |
30 ms |
162 uA |
32,4 uA |
| ADV_IND + Verbindung (1s) |
Kontinuierlich |
~800 uA |
~800 uA |
3. Energiezustandsmaschine
Beacon Energiezustandsmaschine
[DEEP SLEEP] --RTC IRQ--> [ADV EVENT (Active)]
1,5 uA 5,2 mA
| |
| Button IRQ | Sensor anstehend?
v v
[BUTTON HANDLER] [SENSOR READ]
3,0 mA 1,2 mA
| |
| 500ms Timeout | 2ms Lesen
v v
[CONFIG MODE] [DEEP SLEEP]
8,5 mA 1,5 uA
Fehlerpfad: WDT Timeout -> RESET -> INIT -> SLEEP
3.2 Zustandsuebergangsbudget
| Zustand |
Strom |
Typ. Dauer |
Energie/Ereignis |
Ereignisse/Tag |
Tagesenergie |
| Deep Sleep |
1,5 uA |
999,4 ms |
1,499 uJ |
86.400 |
129,5 mJ |
| Advertising-Ereignis |
5,2 mA |
610 us |
9,52 uJ |
86.400 |
822,5 mJ |
| Sensor-Lesung |
1,2 mA |
2 ms |
7,2 uJ |
2.880 |
20,7 mJ |
| Tasten-Scan |
3,0 mA |
0,1 ms |
0,9 uJ |
86.400 |
77,8 mJ |
| Konfig-Modus |
8,5 mA |
~5 s |
127,5 mJ |
~2 |
255 mJ |
| RTC + Ereignis |
3,2 mA |
50 us |
0,48 uJ |
86.400 |
41,5 mJ |
| Tagesenergie gesamt |
1.347 mJ |
CR2032: 220 mAh x 3,0V = 2.376 J. Nutzbar: ~1.520 J. Tagesbudget: 1.347 mJ -> 1.128 Tage = 3,1 Jahre.
3.3 System OFF vs. System ON
| Parameter |
System ON (WFE) |
System OFF |
| Strom |
1,5 uA |
0,4 uA |
| Aufwachlatenz |
~2 us |
~300 us |
| RAM erhalten |
Ja |
Nein |
| RTC laeuft |
Ja |
Nein |
| SoftDevice |
Erhalten |
Zerstoert |
4. Timer-Architektur
| Schicht |
Hardware |
Taktquelle |
Genauigkeit |
Leistung |
Aufloesung |
| BLE Stack |
RTC1 |
32,768 kHz |
+/-20 ppm |
0,3 uA |
30,5 us |
| App Timer |
RTC2 |
32,768 kHz |
+/-20 ppm |
0,1 uA |
30,5 us |
| Hohe Aufloesung |
TIMER0/1/2 |
16 MHz |
+/-50 ppm |
5,5 mA |
62,5 ns |
5. Ereignisgesteuerte Architektur
typedef enum {
EVT_ADV_COMPLETE = 0,
EVT_SENSOR_TIMER,
EVT_BUTTON_PRESS,
EVT_BATTERY_LOW,
EVT_GATT_CONNECT,
EVT_OTA_START,
EVT_WATCHDOG,
EVT_FAULT,
} beacon_event_t;
#define EVENT_QUEUE_SIZE 16
void event_post(beacon_event_t type, uint32_t data) {
uint8_t next = (eq_head + 1) % EVENT_QUEUE_SIZE;
if (next == eq_tail) { fault_set(FAULT_QUEUE_OVERFLOW); return; }
event_queue[eq_head].type = type;
event_queue[eq_head].data = data;
event_queue[eq_head].timestamp = rtc_get_ticks();
eq_head = next;
}
6. Watchdog und Fehlererholung
| Schicht |
Ausloeser |
Reaktion |
Zeit |
| L1: Soft-Fehler |
Queue-Overflow, Sensor-Timeout |
Protokollieren, ueberspringen |
0 ms |
| L2: Hard-Fehler |
Radio blockiert, SPI-Lockup |
Peripherie-Reset |
50-200 ms |
| L3: System-Fehler |
WDT-Timeout (8s) |
Vollreset |
500ms-2s |
6.3 Brownout-Erholung
| Batteriespannung |
R intern |
Vdrop |
Vmin |
BOR-Risiko |
| 3,0V |
5 Ohm |
23 mV |
2,977V |
Keins |
| 2,6V |
10 Ohm |
46 mV |
2,554V |
Keins |
| 2,3V |
15 Ohm |
69 mV |
2,231V |
Niedrig |
| 2,1V |
30 Ohm |
138 mV |
1,962V |
HOCH |
7. Speicherlayout
| Region |
Groesse |
Inhalt |
| SoftDevice (MBR + S132) |
160 KB |
MBR + BLE-Stack |
| Anwendung |
308 KB |
Hauptfirmware |
| Konfig (NVS) |
16 KB |
Intervall, TX, UUID |
| App-Daten (NVS) |
16 KB |
Logs, Fehler, Kalibrierung |
| Bootloader |
16 KB |
DFU + CRC |
8-9. BLE-Integration und OTA
| OTA-Parameter |
Wert |
Hinweise |
| MTU |
247 Bytes |
Verhandelt |
| Verbindungsintervall |
15 ms |
Durchsatz/Leistung-Balance |
| Firmwaregroesse |
~120 KB |
Nur Anwendung |
| Uebertragungszeit |
~8 s |
508 x 15ms |
| OTA-Strom |
~8,5 mA |
Radio + Flash |
| Batterieeffekt |
~28 uAh |
0,017% CR2032 |
10. Felddaten (12 Monate, n=2.847)
| Kennzahl |
Ziel |
Feldergebnis |
| Zeit zwischen Resets |
> 6 Monate |
11,3 Monate |
| WDT-Resets |
< 1% |
0,3% |
| OTA-Erfolg |
> 99% |
99,7% |
| Batterielebensdauer (1s, 23C) |
> 24 Monate |
28,4 Monate |
| Batterielebensdauer (1s, 0C) |
> 18 Monate |
19,7 Monate |
11. Haeufige Fehler und Loesungen
| Fehler |
Symptom |
Loesung |
| Floatende GPIOs |
+8-15 uA |
Pull-Down oder Ausgang Low |
| SPI nicht freigegeben |
+0,5 mA |
Deaktivieren nach Transaktion |
| SAADC aktiv |
+0,2 uA |
uninit() aufrufen |
| Flash-Log zu oft |
Verschleiss |
RAM-Puffer, alle 5 Min Flush |
| Blockierendes Delay in ISR |
BLE-Timing-Verletzung |
Event posten, in Loop verarbeiten |
| Stack-Overflow |
Random Hard Fault |
Statische Buffer, MPU-Guard |
13. Zusammenfassung
Beacon-Firmware handelt grundsaetzlich davon, fast nichts zu tun, fast die ganze Zeit, ohne je auszufallen. Jedes Mikroampere, das im Schlafmodus gespart wird, bedeutet zusaetzliche Monate Feldeinsatz. Jeder abgedeckte Fehlerpfad verhindert ein Support-Ticket, das mehr kostet als der Beacon selbst. Wenn die Architektur stimmt, ueberlebt Ihr Bluetooth Beacon die Batteriegarantie mit null Feldruecksendungen.