1. Vývojové prostředí 2. Dálkové ovládání 3. Nový projekt 4. První program 5. Formátování kódu 6. Komentáře 7. Proměnná 8. Větvení 9. Cyklus 10. Funkce 11. LEDky 12. LED pásek 13. Sériová linka 14. Koncová tlačítka 15. Práce s tlačítky 16. Ultrazvuk 17. IR senzor 18. Motory 19. Monitorování robotky 20. Serva (hloupá) 21. Úpravy dálkového ovládání Layout Reakce na události Zobrazování dat z Robotky Dokumentace Dokumentace Příklady

Úpravy dálkového ovládání

Jak upravit to, co vidíte na telefonu nebo počítači v aplikaci RBController?

Tato kapitola předpokládá, že upravuješ rbcontroller-android-app z našeho balíku příkladů pro Robotku, viz Dálkové ovládání.

Ovládání na telefonu pouze zobrazuje to, co mu pošle tvoje Robotka. V příkladu dálkového ovládání je to pouze jeden joystick, ale to můžeš rychle změnit. K ovládacímu rozhraní totiž existuje “návrhář”:

Otevři si ho v prohlížeči.

Layout

Layout je popis celého ovládacího rozhraní - kde všechny prvky (widgety) jsou, jak se jmenují a jaké mají parametry. Layout je výstupem z návrháře a v projektu už jeden máš jako soubor src/layout.h. Najdi si ho ve VSCode, otevři, a zkopíruj celý jeho obsah do schránky (ctrl+c).

Poté přejdi do návrháře a klikni na žluté tlačítko Import layout vlevo nahoře. Do dialogu vlož (ctrl+v) obsah souboru src/layout.h, který máš ve schránce.

Výsledek by měl vypadat takto:

Zkus do layoutu přetáhnout z levého sloupce jeden Button (tlačítko), prozatím mu nic dalšího nenastavuj.

Upravený layout dostaneš do programu zpátky tak, že klikneš na Copy to Clipboard vpravo nahoře v boxu Generated C++, předeš zpátky do VSCode do souboru src/layout.h, a celý jeho obsah nahradíš tím, co máš ve schránce (ctrl+a ctrl+v).

Poté nahraj program do Robotky, připoj se přes RBController aplikaci a tam obnov stránku. Přidané nové tlačítko by mělo být vidět, zatím ale nic nedělá.

Reakce na události

Některé widgety (např. Button, Checkbox, Joystick…) vytvářejí určité události: tlačítko stisknuto, checkbox odšrtnut/zaškrtnut nebo joystick se pohl.

Na tyto události můžeš v kódu reagovat, viz joystick v příkladu rbcontroller-android-app:

1
2
3
4
5
6
7
8
    auto builder = Layout.begin();

    builder.Joystick1
        .onPositionChanged([&](Joystick &joy) {
            rkMotorsJoystick(joy.x(), joy.y());
        });

    builder.commit();

Zde si všimni prvního a posledního řádku - ty musí být v každém programu používající RBController a dálkové ovládání. Mezi nimy je prostor pro zpracovávání událostí. Pojďmě si rozebrat, co se v kódu děje:

  • 1
    
    builder.Joystick1.onPositionChanged(...
    

    Tato konstrukce říká, že chceme pracovat s prvkem, který má ID Joystick1, a že chceme zpracovat událost PositionChanged. ID se nastavuje v návrháři, zkuste vybrat některý z widgetů a ID bude žlutě zvýrazněné napravo ve sloupci Properties.

  • 1
    2
    3
    
    [&](Joystick &joy) {
        rkMotorsJoystick(joy.x(), joy.y());
    }
    

    Události využívají tzv. lambda funkce - malinkaté funkce, které vytvoříte syntaxí [&](<parametry>){ <kód> }. V případě návrháře budou parametry vždy (<Typ widgetu> &widget) - v tomto případě je typ Joystick. Kód, který je pak v těle funkce, se vykoná vždy, když daná událost nastane.
    Zde nastavujeme výkon motorů podle toho, v jaké poloze je Joystick1.

Příklad: reagování na stisknutí tlačítka

Do layoutu jsme přidali jedno tlačítko. Přejdi zase do návrháře, vyberte ho, a v pravém sloupci Properties změňte ID na něco jiného, například prepniLed. Layout opět nakopíruj do svého projektu ve VSCode.

Přejdi do src/main.cpp a přidej do zpracování událostí tvé tlačítko. Všimni si, že VSCode ti po napsání builder. začne napovídat ID widgetů, které jsou v tvém layoutu. Stejně tak začne po napsání builder.prepniLed. napovídat, co všechno lze s tlačítkem dělat.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
    auto builder = Layout.begin();

    builder.Joystick1
        .onPositionChanged([&](Joystick &joy) {
            rkMotorsJoystick(joy.x(), joy.y());
        });
    
    builder.prepniLed
        .onPress([&](Button& b) {
            rkLedGreen(true);
        })
        .onRelease([&](Button& b) {
            rkLedGreen(false);
        });

    builder.commit();

Nahrej program do Robotky a vyzkoušej, jestli funguje. Výsledkem by mělo být, že zelená LED svítí, dokud držíš tlačítko v aplikaci stisknuté.

Zobrazování dat z Robotky

Komunikace může probíhat i druhým směrem, můžeš tak zobrazovat informace z Robotky na tvém telefonu. Zkusíme to nejprve s napětím baterie.

V návrháři přidej do layoutu jeden Text widget a nastav mu ID, například napetiMv. Layout opět zkopíruj do svého projektu.

Kód bude vypadat takto (reagování na události vynecháno):

1
2
3
4
5
6
7
8
    auto builder = Layout.begin();
    ...
    builder.commit();

    while(true) {
        Layout.napetiMv.setText(fmt::format("{} mV", rkBatteryVoltageMv()));
        delay(500);
    }

Přidali jsme nekonečnou smyčku, která každých 500 ms (půl vteřiny) nastaví obsah Textu s ID napetiMv.

  • Posílání dat do telefonu přijde, narozdíl od zpracování událostí, až pod řádek builder.commit();.
  • Lze nastavovat spoustu jiných parametrů, zkus napsat Layout.napetiMv. a bude ti napovězeno, co všechno můžeš použít.
  • Funkce fmt::format převede výsledek funkce rkBatteryVoltageMv(), což je int, na textový řetězec (std::string) a přidá za něj jednotku mV (millivolty).
  • fmt:format má jako první parametr “šablonu”, v našem případě "{} mV". Všechny {} v šabloně jsou nahrazeny hodnotou dalších parametrů, v našem případě je {} nahrazeno výsledkem rkBatteryVoltageMv(). V šabloně může být vice než jeden {}.

Data lze zobrazovat i ze zpracování událostí. Následující kód také funguje, protože lambda funkce událostí jsou volány až po té, co proběhne builder.commit();.

1
2
3
4
5
6
7
8
    auto builder = Layout.begin();

    builder.Joystick1
        .onPositionChanged([&](Joystick &joy) {
            Layout.textJoystick.setText(fmt::format("{}x{}", joy.x(), joy.y()));
        });

    builder.commit();

Dokumentace