Montaa¾      Teegid      Ülesanded      
Tagasisidestus Serialprintln(); abil Jadaühenduse kaudu tekstilise fraasi kuvamine jadaühenduse ekraanil (ingl. Serial Monitor) on üheks kõige lihtsamaks ja informatiivsemaks meetodiks, et saada aru, millises programmiosad loogikatehete tulemusel töötavad ja millised on selles kasutatud dünaamilised muutujad. Samuti on kolmas, pr() programmi kirjutamisel kõige lühem ja elegantsem lahendus Tagasisidestus Serial. println(); abil

Programmeerimine

C++ keele põhjal, praktiliste harjutustega

Tagasisidestus Serial.println(); abil

Jadaühenduse kaudu tekstilise fraasi kuvamine jadaühenduse ekraanil (ingl. Serial Monitor) on üheks kõige lihtsamaks ja informatiivsemaks meetodiks, et saada aru, millises programmiosad loogikatehete tulemusel töötavad ja millised on selles kasutatud dünaamilised muutujad.

Tagasisidestus Serial.println(); abil

Tüüpiliselt ei luba Arduino teek liita Serial.print() käsu siseselt liita kokku mitut tekstilist fraasi, mis on vaikimisi const char ja  täisarvulisi int muutujaid (ingl. int) vaheldumisi sõnedega. Näiteks harjutuses "laborirobot" on kolm muutujat, mootori number, selle staatus (sees või väljas) ja reeversi staatus (kas sees või väljas). Selleks, et saada vaikimisi Arduino standardit kasutades dünaamiline tagasiside lause kujul, näiteks 

 

1. mootor on 1, reevers 0

 

tuleks klassikalises Arduino C++ käsitluses kirjutada järgnevalt

Serial.print("1");
Serial.print(". mootor on");
Serial.print(o1);
Serial.print(", reevers ");
Serial.println(o4);

Pane tähele, et esimesed read on Serial.print(); ja viimane Serial.println(); mille ln - on lühend "line" ehk lisab jadaühenduse sõnumile lõppu ka reavahetuse, mille tulemusena algab järgmine rida uuelt realt.

 

Sellist meetodit nimetatakse kettimiseks, sest iga element on justkui eraldi ketilüli. Kirjaviisi poolest on see üsna kohmakas, võtab programmikoodis palju ridu ja väljendit Serial.print() tuleb kirjutada üha uuesti ja uuesti. Vaata näiteks komplekssemat, viie erineva andmetüübiga kettimise näidet

 

x.concat(y)

Arduino String klass (ek sõne) sisaldab vaikimisi funktsiooni, millega on võimalik liita mitu sõnet kokku üheks pikemaks sõneks, näiteks vaatame järgnevat skripti

String x = "Tere ";
String y = "protsessor";
x.concat(y); 

muudab sõne x väärtuseks "Tere protsessor". Funktsiooni concat nimi tuleb ingliskeelsest väljendist concatenate, mida võiks antud kontekstis nimetada eesti keeles sõnede ühendamiseks. 

 

+ operaatoriga

Suurepäraselt lihtne võimalus on liita kokku mitut muutujat, mille puhul on tüüpide puhul pisut rohkem vabadust, saab kokku liita sõne ja numbrilise (int) muutuja

String x = "Temperatuur ";
int y = 21;
String z = x + y;

nüüd on z väärtusega "Temperatuur 21", kuid silmas tasub pidada, et tekstiline element peab olema eksplitsiitselt olema eelnevalt sõne (ingl String), mitte "const char". Selline eelnevalt sõnena defineerimine võib olla kohmakas, kuid õnneks on võimalik muutujaid lihtsal moel ühtlustada ja muuta sõneks String() funktsiooniga, näiteks Serial.print() jaoks käsitlemiseks järgnevalt

 

Serial.print("Temperatuur " + String(21));

 

Mis annab jadapordi kaudu täpselt samamoodi väljundiks "Temperatuur 21" nagu eelmise näitega

 

C++ vs. Python

Tüüpide konverteerimine on üsna universaalne erinevates keeltes, siis on vahetevahel ühelt keelelt teisele üleminekul segiminekuoht, mida võib suurepäraselt tasandada originaalfunktsioonidega, näiteks lihtne funktsioon võimaldab jadaühenduse Serial.println muuta lühemaks ja universaalsemaks ning saada lahti segiminekuprobleemist. 

void print(String inText){ 
  Serial.println(inText); 
}

mida võib nüüd kasutada lühema ja segiminekut vältiva süntaksiga

print("Temperatuur" + String(21));

ja jadaühenduse väljundiks on täpselt samamoodi "Temperatuur 21" nagu varemgi. 

 

Samamoodi võib pakendada Arduino sõne funktsiooni String() lühemaks, Pythoni sarnaseks kui kirjutada originaalfunktsioon str() järgneval kujul

void str(int inp){
    return String(inp);
}

mis on kohandatud täisarvu int tüübi konverteerimiseks sõneks (ingl String), et kasutada seda print() funktsioonis vaikimisi const char tüüpi tekstiga ühe lausungina järgnevalt

print("Temperatuur" + str(21));

mis annab vastuseks täpselt samamoodi "Temperatuur 21", nagu ka varasematel juhtudel. Lihtsamate täisarvuliste muutujate puhul on selline lühendamine käepärane ja lihtsustab koodi, muudab selle ka ülevaatlikumaks. Siiski tasub silmas pidada, et selline lihtne int => String konversioon on kitsalt ainult nende tüüpide vaheliseks muutuseks, ega hõlma teisi tüüpe nagu näiteks ujukomaarvud (ingl. float). 

 

Toimivate lahenduste võrdlus

Võrdleme selguse huvides toimivaid lahendusi, milles on külg-külje kõrval näha Pythonis kasutatavad stringide liitmise ja printimise võtted, teises veerus Arduino String klassi meetodid ja kolmandas nanoTronic 0.68 versiooni teegipõhine lahendus, milles on kitsalt int => String konversioon

 

PythonArduino C++nanoTronic 0.68 v
t = 21int t = 21; int t = 21; 
print("Temperatuur " + str(t))Serial.println("Temperatuur " + String(t))print("Temperatuur " + str(t));

 

 

Ülaltoodud näited kasutavad Arduino String klassi meetodit, kuid efektiivsemaks mälukasutuseks on oluline aru saada sõnede tüüpide erinevusest

 

Arduino programmeerimisel on const char* ja String kaks erinevat viisi tekstiga (sõnedega) tegelemiseks, millel on suured erinevused mäluhalduse ja efektiivsuse osas.

1. const char* (C-stiilis sõne)

const char* viitab C-stiilis sõnele (string), mis on tegelikult:

  • char tüüpi massiiv (array), mis hoiab teksti sümboleid (ühte baiti sümboli kohta).

  • Massiivi viimane element on alati null-terminaator (, ASCII 0), mis annab märku sõne lõpust.

  • const char* on konstantne viit (pointer) selle massiivi esimesele sümbolile (esimesele char tüüpi elemendile).

  • const märge tähendab, et sõne sisu (sümbolid) ei saa pärast defineerimist muuta. Sellise sõne puhul salvestatakse tekst reeglina otse programmi mällu (Flash, program space), mis on väga mälusäästlik.

Defineerimine

Sõne defineerimiseks on kõige levinum kasutada massiivi ja const märget.

// 1. Kõige tüüpilisem ja mälusäästlikum viis konstantse sõne jaoks
const char* konstante_sone = "See on konstantne C-stiilis sõne.";
// Või massiivi abil
const char konstante_massiiv[] = "Teine konstantne sõne."; 
// F-makro kasutamine, et tagada sõne salvestamine Flash-mällu
Serial.println(F("See läheb otse Flash-mällu."));

 

2. String (Arduino String klass)

String on klass (class) ehk objekt, mis pakub mugavamaid vahendeid sõnedega töötamiseks (nt. liitmine, alamstringid, pikkus).

  • See haldab mälu dünaamiliselt (kasutab heap mälu), mis tähendab, et iga kord, kui Stringi sisu muudetakse (nt. liidetakse teine String), võib String-objekt küsida mälult uue ja suurema mälubloki ning vana vabastada.

  • See on programmeerija seisukohalt mugav, kuna see hoolitseb mälu halduse eest automaatselt.

Defineerimine

// 1. Lihtne String-objekti defineerimine
String muudetav_sone = "Algne tekst";
// 2. String-objekti loomine teisest andmetüübist
int number = 42;
String number_sone = String(number);

 

Omadusconst char* (C-stiilis sõne)String (Arduino klass)
MälupaikFlash-mälu (program space) või fikseeritud koht SRAM-is (muutuvmälu).SRAM (dünaamiline heap mälu).
Mälu kasutusVäga efektiivne. Kasutab mälu täpselt nii palju kui vaja (+ ). Eriti säästlik, kui kasutatakse F() makrot.Vähem efektiivne. Iga kord, kui Stringi muudetakse (liidetakse), võidakse luua uus mälublokk, mis põhjustab mälu killustumist (memory fragmentation).
MuudetavusKonstantne (const): ei saa muuta. Muutuva pikkusega sõne jaoks on vaja kasutada char massiivi ja käsitsi mälu hallata.Muudetav. Sobib dünaamilise teksti jaoks.
KiirusKiire lugemine ja edastamine, kuna mäluaadress on fikseeritud.Liitmisoperatsioonid on aeglasemad dünaamilise mäluhalduse ja uute mälublokkide loomise tõttu.

Järeldus: Väikese mäluga mikrokontrollerites, nagu Arduino, võib String-klassi sage kasutamine ja liitmine põhjustada mälu killustumist ja programmi ebastabiilsust (nt. jookseb kokku). const char* on alati eelistatud konstantse teksti puhul.

 

Kõige mälusõbralikum lahendus

Selleks, et vältida SRAM mälu ülekoormamist ja String objektiga seotud ebaefektiivsust tuleks kas pigem kasutada Serial.println(); kettimist või lahendada muul moel väljundisse sõnede saatmisel String objekti kasutamist ja eelistada alati char tüüpi. 

 

Lahenduseks on originaalfunktsioon, mis aktsepteerib sisendina erinevaid andmetüüpe, ilma et peaks muretsema nende eelneva konverteerimise pärast (int, float, bool, char*, String, jne). Samas väldib SRAM ülekoormamist, sest String objektiga tehteid ei teha. Lisa enda teeki või programmi algusesse järgnev funktsioon

void pr(){// mugavam print funktsoon
  Serial.println(); // tühi uus rida
}
template<typename T, typename... Args>
void pr(T first, Args... rest){
  Serial.print(first);
  pr(rest...);
}// end pr

Mis võimaldab ülimugavalt printida erineva tüübiga elemente ühes lauses, täpselt nagu Pythonis

int t = 21;
String cyh = "C";
float rhk = 101.3;
const char* ryh = "hPa";
bool rvs = true;

pr("Temperatuur ", t, " ", cyh, " ja rõhk ", rhk, " ", ryh, " reevers ", rvs);

Prindib lause "Temperatuur 21 C ja rõhk 101.30 hPa reevers 1"

 

Võrreldes varasemate lahendustega on see nii SRAM suhtes mälusõbralikuim lahendus kui ka oluliselt lihtsam arenduse poolest koodi kirjutada. 

 

Laboriroboti staatused

Seega käsitlesime siin sellel lehel erinevaid võimalusi, kuidas kettimise asemel võiks tagasisidestust kirjutada ühele reale. Toome siinkohal ära need kolm töötavat näidet, mis oli selle lehe alguses harjutuse "Laborirobot" mootorite tagasidestuseks, lausungi "1. mootor on 1, reevers 0" kuvamiseks. 

Serial.println(String(1) + ". mootor on " + o1 + ", reevers " + o4);
print(str(1) + ". mootor on " + o1 + ", reevers " + o4);
pr(1, ". mootor on ", o1, ", reevers ", o4);

Millest esimene kirjutab välja standard jadapordi väljundi Serial.prinln() ja kasutab selle sees String() sõnede liitmist + plussmärkidega 

 

Teine variant on modifitseeritud nanoTronic 0.68 versiooni teegis sisalduvate print() ja str() kasutusega, kuid toimib põhimõtteliselt samamoodi sõnede liitmise meetodil.

 

Kolmas lahendus on lisada kas programmi algusesse või teeki täiesti uus rekursiivne funktsioon pr() milles käsitletakse erinevaid sisendeid (int, float, bool, char*, String, jne) ilma neid konverteerimata ja selleks SRAM mälu kasutamata. Samuti on kolmas, pr() programmi kirjutamisel kõige lühem ja elegantsem lahendus. 

Monteeri lihtsalt ja kiiresti

Riistvara montaa¾ on jaotatud etappideks ja toetatud õppevideodega. Vaata lähemalt.

 

Tarkvaratugi

Loe riistvaralist portide lugemist ja muutujate defineerimist toetava tarkvarateegi kohta

C++ on masinate keel
Maailmas kõige enam kasutusel olev seadmete programmeerimiseks kasutatav keel on C++ mis võimaldab väikestel kiipidel ökonoomselt programmiloogikat lahendada ja teha ka suuri kõrgkeelele omaseid andmetöötlusi. 

Populaarne Nano standard
Laiendusplaadi nanoTronic disainimisel on aluseks võetud Arduino Nano standard, mis võimaldab teha nii automatiseerimist, vanade asjade digitaliseerimist kui ka luua akutoitel töötavaid ökonoomseid mobiilsid seadmeid. 

Ülesanded samm-sammult
Selleks, et C++ paremini tundma õppida on loodud ülesannetekogu, milles saab alguses teha lihtsamaid, samm-sammult keele võimalusi tutvustavaid harjutusi ja siirduda siis järjest edasi jõukohaste väljakutsetega.

Projekti fookusest
Projekt nanoTronic on loodud eelkõige hariduslikel eesmärkidel, et edendada mehhatroonika erialal programmeerimise süvendatud õpet, parema struktuuri ja loogikakasutusega skriptide kirjutamist. 

Veebilehe disain ja CMS

Tagasisidestus Serialprintln(); abil

Tüüpiliselt ei luba Arduino teek liita Serial print() käsu siseselt liita kokku mitut tekstilist fraasi, mis on vaikimisi const char ja täisarvulisi int muutujaid (ingl Jadaühenduse kaudu tekstilise fraasi kuvamine jadaühenduse ekraanil (ingl. Serial Monitor) on üheks kõige lihtsamaks ja informatiivsemaks meetodiks, et saada aru, millises programmiosad loogikatehete tulemusel töötavad ja millised on selles kasutatud dünaamilised muutujad.

Tagasisidestus Serial. println(); abil

nanotronic.eu © 2025 nanoTronic » Populaarne standard ja suur jõudlus