Zajištění plynulého chodu palubního softwaru představuje komplexní výzvu. Při návrhu celkové architektury jsem musel vyřešit fundamentální problém: jak zajistit, aby procesor stíhal obsluhovat všechny připojené senzory a zároveň udržoval nepřerušenou rádiovou komunikaci. Detailně jsem proto analyzoval dva odlišné přístupy – tradiční sekvenční provádění kódu a využití operačního systému reálného času (FreeRTOS).

Ačkoliv by se mohlo zdát, že pro načítání dat ze senzorů postačí jednoduchá nekonečná smyčka while(1), já jsem ve svém projektu implementoval pokročilejší multi-tasking pod správou FreeRTOS. Sekvenční kód totiž funguje na principu absolutní linearity; procesor vykonává instrukce striktně jednu po druhé. Pokud jeden senzor, například SHT45, vyžaduje určitý čas na vnitřní převod naměřených hodnot, celý běh programu se zastaví a systém pasivně čeká. Pro mou aplikaci, kde bylo kriticky důležité kontinuálně odesílat a přijímat telemetrii přes modul HC-12, by toto blokování znamenalo neakceptovatelnou ztrátu dat a celkovou nestabilitu systému.

Rozhodl jsem se proto celý systém rozdělit do zcela nezávislých vláken (Tasků). Vytvořil jsem specifický Task, který má za úkol pouze pravidelně vyčítat hodnoty z environmentálních senzorů, a zcela oddělený Task, který je neustále připraven přijímat rádiové povely. (viz. článek: Rádiová komunikace s ESP) Operační systém FreeRTOS pak s mikrosekundovou přesností přepíná pozornost procesoru mezi těmito vlákny. Tím vzniká vysoce efektivní iluze paralelního zpracování, díky které žádná část systému neblokuje tu druhou. Celý sestavený kód s vytvořením nového vlákna pak může vypadat nějak takto:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
// Toto je tělo Tasku pro čtení dat
void sensor_reading_task(void *pvParameters) {
while(1) {
printf("Čtu data ze senzorů...\n");
// Místo zastavení celého čipu uspíme pouze tento Task na 1 sekundu
// pdMS_TO_TICKS přepočítá milisekundy na systémové tiky
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
void app_main(void) {
// Zde vytvářím samotný Task
xTaskCreate(
sensor_reading_task, // Název funkce, kterou chceme v novém Tasku spustit
"SensorTask", // Textový název pro ladění
4096, // Velikost paměti (Stack size) v bajtech vyhrazené pro tento nový Task
NULL, // Parametry předávané funkci
5, // Priorita úkolu (čím vyšší číslo, tím důležitější)
NULL // Handle (odkaz) na task, pokud ho nepotřebujeme, dáme NULL
);
printf("Hlavní program pokračuje, zatímco Task běží na pozadí.\n");
}

Sestavením kódu tímto způsobem zajistím, že bude hlavní smyčka sloužit pouze pro například výpisy a nebude blokovaná komunikací se senzory. Což také výrazně zrychlí chod celého systému protože například SHT45 potřebuje pár milisekund na přípravu dat.

Srovnání odezvy systému (Zkušební měření)

Architektura softwaruPrůměrné vytížení procesoruZpoždění čtení (Latence)Reakce na rádiový povel
Sekvenční smyčka98 %150 milisekundČasto zmeškáno (timeout)
FreeRTOS Tasky15 %2 milisekundyOkamžitá a stabilní

Slovníček pojmů:

  • Sekvenční kód: Program, který čte a vykonává příkazy přesně v tom pořadí, v jakém jsou napsány, bez možnosti dělat více věcí najednou. Zastavení jednoho příkazu zastaví vše.
  • Multi-tasking: Schopnost systému provádět (nebo zdánlivě provádět) více nezávislých úloh současně díky rychlému přepínání kontextu.
  • FreeRTOS: Specializovaný operační systém pro mikrokontroléry, který precizně řídí, kdy a jak dlouho se bude jaká část kódu vykonávat.
  • Task (Vlákno): Samostatná a izolovaná část programu, která běží nezávisle na ostatních částech pod dohledem operačního systému.
  • Latence: Zpoždění mezi odesláním požadavku (např. dotaz na senzor) a skutečnou reakcí či dodáním dat.

Kategorie