====== Arduino struktúrák ====== Forrás: https://www.arduino.cc/en/Reference/HomePage ===== setup() ===== A funkció a board bekapcsolása illetve újraindítása után, egyszer fut le, a program futását megelőzően. Kezdeti beállításokat tartalmaz, itt lehet: * változókat inicializálni * a pin-ek paramétereit (pl. az adott pin olvas vagy ír) beállítani * könyvtárak kezdeti értékeit beállítani * a kommunikációs paramétereket állítani ==== Példa ==== int buttonPin = 3; void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); } void loop() { // ... } ===== loop() ===== A funkció a kezdeti értékadásokat elvégző setp() funkció lefutása után folyamatosan és ciklikusan futtatja a programot. Ennek a programnak a futását a [[hu:arduino:start#isr|megszakítások]]kal lehet csak kvázi "felülírni". === Példa === const int buttonPin = 3; // a setup funkció beállítja a "serial" kommunikáció és a pin működését void setup() { Serial.begin(9600); pinMode(buttonPin, INPUT); } // a loop() funkció figyeli a pin állapotát // és jelzést ad a monitorra, ha a rá kötött nyomógomot aktiválják void loop() { if (digitalRead(buttonPin) == HIGH) Serial.write('H'); else Serial.write('L'); delay(1000); // a program futásának felfüggesztése 1 másodpercre } ===== Kontroll-struktúrák ===== ===== if ===== {{anchor:if}} Az **if** egy elágazás, mely egy feltételtől teszi függővé a tartalmának a végrehajtását. A "feltétel" blokkban, a zárójelen belül [[#comp_operators|összehasonlító operátorok]]kal definiálhatjuk a feltételt. A végrehajtási részhez, több sornyi tartalom esetén kapcsos-zárójeleket kell alkalmazni, lásd a példánál. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. === Szintaktika === if (feltétel) {} \\ and ==, !=, <, > (összehasonlító operátorok) === Példa === if (x > 120) digitalWrite(LEDpin, HIGH); if (x > 120) digitalWrite(LEDpin, HIGH); if (x > 120){ digitalWrite(LEDpin, HIGH); } if (x > 120){ digitalWrite(LEDpin1, HIGH); digitalWrite(LEDpin2, HIGH); } // mindegyik megoldás helyes ===== if..else ===== {{anchor:if_else}} Az **if** egy elágazás, mely egy feltételtől teszi függővé a tartalmának a végrehajtását. Az **else** definiálja az "egyéb" ágat, a program végrehajtása ide fut, ha a feltétel nem teljesül. A "feltétel" blokkban, a zárójelen belül [[#comp_operators|összehasonlító operátorok]]kal definiálhatjuk a feltételt. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. Az if-hez hasonló az "**? :**" operátor működése, lásd itt: [[#egyeb_operatorok|egyéb operátorok]]. === Szintaktika === if (feltétel) {} else {} \\ and ==, !=, <, > (összehasonlító operátorok) === Példa === if (i < 100) { // "a" végrehajtási rész, ha i < 100 } else { // "b" végrehajtási rész, ha i >= 100 } Az **else** ág kibővíthető további if elágazásokkal is, és persze további else-ekkel is (bár érdemes átgondolni a [[#switch|switch]] alkalmazásának a lehetőségét): if (i < 100) { // "a" végrehajtási rész, ha i < 100 } else if (i >= 5000) { // "b" végrehajtási rész, ha i >= 500 } else { // "c" végrehajtási rész; minden más eset ( 100 <= i < 500 ) } ===== for ===== {{anchor:for}} A for a feltétel-blokk teljesülése esetén futtatja a végrehajtási blokk tartalmát, mely eleve csak akkor kerülhet végrehajtásra, ha a feltételek legalább egyszer teljesülnek. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. === Szintaktika === for (inicializálás; feltételek; léptetés) { \\ \\ végrehajtás-blokk ; \\ \\ } \\ \\ inicializálás: egybeköthető a ciklusvéltozó deklarálásával is; ebben az esetben a változó csak a "for" cikluson belül használható: for (int i = 1; i < 10; i++) { // az i 1..9-ig számol, és csak a "for" cikluson belül használható serial.print(i); // az "i" kiírása a terminálra } === Példa === // Egy LED fényerejének a növelése a PWM pin-en int PWMpin = 10; // LED a 10. pin-en, egy 470 ohm-os ellenállással sorba kötve void setup() { // nincs szükség setp-ra } void loop() { for (int i=0; i <= 255; i++){ analogWrite(PWMpin, i); delay(10); } } A PWM-ről bővebben itt olvashat: [[hu:arduino:start#arduino_pwm|Arduino PWM]]. A C programozási nyelv meglehetősen rugalmasan kezeli a "for" ciklust (is). A feltétel-blokk (a for után a zárójelben) bármely eleme elhagyható, csak a ;-t kell kötelezően kitenni. A léptetés-ben akár törtszám műveletet is megadhatunk, a ciklusváltozó típusától függetlenül: for(int x = 2; x < 100; x = x * 1.5){ println(x); } A program kimenete ez lesz: 2,3,4,6,9,13,19,28,42,63,94. A feltételeket (pl. a léptetést) a program futása során is meg lehet változtatni: void loop() { int x = 1; for (int i = 0; i > -1; i = i + x){ analogWrite(PWMpin, i); if (i == 255) x = -1; // a maximumot (255) elérve a számlálás iránya megfordul delay(10); } } ===== switch case ===== {{anchor:switch}} A switch funkció az [[#if_else|if..else]] bővített válozata. A **switch** végrehajtási részében a változó adott állapotának megfelelő utasításokat lehet végrehajtani, a **case** blokkokon belül. A **break** paranccsal ki lehet lépni a switch struktúrából. Ezt általában a **case**-ek végén szokás kiadni, ellenkező esetben a program tovább fut a **switch**-en belül, a következő case kiértékelésével. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. === Példa === switch (var) { case 1: // a case-t végrehajtja, ha var = 1 break; // a program végrehajtása a switch-en kívül folytatódik case 2: // a case-t végrehajtja, ha var = 2 break; // a program végrehajtása a switch-en kívül folytatódik default: // Ha egyik "case" ág sem került végrehajtásra, a program ezt, // a "default"-ot hajtja végre. // A "default" megadása opcionális. // Ha nincs, akkor a program egyszerűen a switch után folytatódik. break; } Ha a case-en belül több utasítást kell végrehajtani, akkor ezeket kapcsos zárójellel kell blokkba szervezni: switch (var) { case 1: { // a case blokkot végrehajtja, ha var = 1 int a = 0; ....... ....... } break; default: // "default" // A "default" megadása opcionális. break; } ===== while ===== {{anchor:while}} A white egy olyan hurok, mely ciklikusan végrehajtja a tartalmát mindaddig, míg a belépési feltételei teljesülnek. Ha a feltételek nem igazak, a hurok egyszer sem kerül végrehajtásra, szemben a [[#do_while|do .. while]] hurokkal. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. === Szintaktika === while (belépési feltételek) { \\ %%//%% hurok tartalma \\ } \\ === Példa === var = 0; while(var < 200){ // valamit végrehajt 200-szor var++; } ===== do .. while ===== {{anchor:do_while}} A do .. while - hasonlóan a [[#while|while]]-hoz - egy olyan hurok, mely ciklikusan végrehajtja a tartalmát mindaddig, míg a bennmaradási feltételei teljesülnek. Külömbség, hogy ebben az esetben a hurkon belüli program legalább egyszer lefut, és csak ezt követi az első feltétel-vizsgálat. A következő utasításokkal a program lefutása jelentősen módosítható: [[#break|break]], [[#continue|continue]], [[#return|return]], [[#goto|goto]]. === Szintaktika === do \\ { \\ %%//%% hurok tartalma \\ } while (bennmaradási feltételek) \\ === Példa === do { delay(50); // várakozás a stabil szenzor-állapotra x = readSensors(); // a szenzor kiértékelése } while (x < 100); // ismétel, amíg az x < 100 ===== break ===== {{anchor:break}} A parancs a **do**, **for**, **switch** és **while** eljárásokon belül alkalmazható, azonnali kiugrást eredményez. === Példa === for (x = 0; x < 255; x ++) { analogWrite(PWMpin, x); sens = analogRead(sensorPin); if (sens > threshold){ // szenzor érzékelve x = 0; break; // a for ciklus megszakítása } delay(50); } ===== continue ===== {{anchor:continue}} A parancs a **do**, **for**, **switch** és **while** eljárásokon belül alkalmazható, azonnali visszaugrást eredményez a ciklus vagy hurok elejére, a további utasítások végrehajtása nélkül. === Példa === for (x = 0; x < 255; x ++) { if (x > 40 && x < 120){ // a feltétel teljesülése esetén vissza a ciklus elejére continue; } analogWrite(PWMpin, x); delay(50); } ===== return ===== {{anchor:return}} A funkció megszakítása, és a visszatérési értékkel visszaadja a vezérlést a funkcióhíváshoz. === Szintaktika === return; %%//%% a funkció visszatérési érték nélküli lezárása \\ return érték; %%//%% az érték lesz a funkció visszatérési értéke\\ === Példa === int checkSensor(){ if (analogRead(0) > 400) { return 1; else{ return 0; } } A parancs lehetőséget ad a program tesztelésére, mert - akár a loop() eljárásban is - a kód hátralevő részét nem futtatja. void loop(){ // a működő kód return; // a kódrész, mely még kihívásokkal kűzd // ez a rész nem kerül végrehajtásra } ===== goto ===== {{anchor:goto}} Ugrás a kijelölt cimkére. A legtöbb programozási künyv óva int a használatától, ugyanis az agyba-főbe tele-goto-zott program szerkezete egyszerűen követhetetlenné válhat, a hibakeresés pedig lehetetlen misszióvá. Nyilván vannak szituációk, például egy mélyen strukrurált for ciklus, ahonnan valamiért ki kell lépni, ilyenkor a goto használata indokolt és hasznos. === Szintaktika === //cimke:// \\ \\ goto //cimke//; \\ === Példa === for(byte r = 0; r < 255; r++){ for(byte g = 255; g > -1; g--){ for(byte b = 0; b < 255; b++){ if (analogRead(0) > 250){ goto bailout;} // további utasítások } } } bailout: ===== union ===== A union egy a C-ből megörökölt, de az Arduino refercialistában nem publikált definició. Alkalmazásával lehetővé válik, hogy egy memóriaterületre több változó is írható. Bármely változóban generált változás a többi helyen is egyidejűleg megjelenik, ezért ez a funkció például a típuskonverziókat jelentősen leegyszerűsíti. Annak ellenére, hogy az union az Arduino részéről nem publikált, remekül működik - lásd a példaprogramot. **Szintaktikája:** union [union tag] { member definition; member definition; ... member definition; } [one or more union variables]; Példaprogram a **union** definícióra: // OB121.com példaprogram - Vámos Sándor (2019) // Az union definició alkalmazása az Arduino-ban union { uint32_t bignumber; uint8_t bytes[4]; } combined; // changing the byte array to the long integer void setup() { Serial.begin(9600); } void loop() { combined.bignumber = 0xAAAAAAAA; combined.bytes[1] = 0xBB; combined.bytes[2] = 0xCC; combined.bytes[3] = 0xDD; Serial.println(combined.bignumber, HEX); delay(10000); } A fenti program futásának az eredménye 0x//DDCCBBAA// lesz. Az union például a struct-tal is ötvözhető, lásd: [[#struct|struct]] ===== struct ===== A struct egy a C-ből megörökölt, de az Arduino refercialistában nem publikált definició. Alkalmazásával összefüggő - felhasználó által definiált típusokat - struktúrákat lehet létrehozni. **Szintaktikája:** struct [structure tag] { member definition; member definition; ... member definition; } [one or more structure variables]; A lenti példában a struct és az [[#union|union]] kombinálására látható egy példa: // OB121.com példaprogram - Vámos Sándor (2019) // A stuct és union definiciók alkalmazása az Arduino-ban struct iot { int id; int voltage; char title[4]; } book; union { struct iot data ; uint8_t bytes[8]; } combined; void setup() { Serial.begin(9600); } void loop() { book.id = 0xAA; book.voltage = 12; strcpy( book.title, "ABC"); combined.data = book; Serial.println(combined.bytes[0], HEX); Serial.println(combined.bytes[2], DEC); Serial.println(combined.bytes[4], DEC); Serial.println(combined.bytes[5], DEC); Serial.println(combined.bytes[6], DEC); Serial.println(combined.bytes[7], DEC); delay(10000); } ===== aritmetikai operátorok ===== {{anchor:arithmetic_op}} ^operátor jele^leírása^megjegyzés| |=|értékadás|Ha az értékadás eredményéhez nem elegendő méretű a cél-változó, túlcsordulás léphet fel \\ Nem szabad összekeverni a "==" operátorral, mely az összehasonlításnál használt. \\ A fordító jellemzően nem fog hibát jelezni, csak a program nem fog működni.| |+|összeadás| | |-|kivonás| | |*|szorzás| | |/|osztás| | |%|maradék-képzés| | ===== összehasonlító operátorok ===== {{anchor:comparison_op}} ^operátor jele^leírása^megjegyzés| |==|egyenlő|Nem szabad összekeverni a "==" operátorral, mely az összehasonlításnál használt. \\ A fordító jellemzően nem fog hibát jelezni, csak a program nem fog működni.| |!=|nem egyenlő| | |<|kisebb, mint| | |>|nagyobb, mint| | |<=|egyenlő, vagy kisebb, mint| | |>=|egyenlő, vagy nagyobb, mint| | ===== bineáris operátorok ===== {{anchor:boolean_op}} ^operátor jele^operátor neve^leírása^példa| |&&|logikai és|igaz, ha minden operandus igaz \\ összekeverhető az "&" operátorral!|if (digitalRead(2) == HIGH && digitalRead(3) == HIGH)| |%%||%%|logikai vagy|igaz, ha az egyik operandus igaz \\ összekeverhető az "%%|%%" operátorral!|if (x > 0 || y > 0) | |!|logikai nem|igaz, ha a "!"-t követő operandus hamis|if (!x)| ===== bit-művelet operátorok ===== {{anchor:bitwise_op}} ^operátor jele^neve^leírása^megjegyzés| |&|bitenkénti "and"|bitenkénti és műveletet hajt végre| | |%%|%%|bitenkénti "or"|bitenkénti vagy műveletet hajt végre| | |%%^%%|bitenkénti "xor"|bitenkénti kizáró vagy műveletet hajt végre| | |~|bitenkénti "not"|bitenkénti negáló műveletet hajt végre| | |<<|bitenkénti "shift left"|bitenkénti jobbra eltolás műveletet hajt végre|a baloldali "becsúszó" pozíciókat 0-kkal tölti fel| |>>|bitenkénti "shift right"|bitenkénti balra eltolás műveletet hajt végre|a jobboldali "becsúszó" pozíciókat 0-kkal tölti fel| === Példa === int a = 5; // tartalom: 0000000000000101 int b = a << 3; // eredmény: 0000000000101000, vagy decimálisan: 40 int c = b >> 3; // eredmény: 0000000000000101, vissza az eredetihez int x = -16; // tartalom: 1111111111110000 int y = x >> 3; // eredmény: 1111111111111110 ===== Összetett operátorok ===== {{anchor:compound_op}} ^operátor jele^neve^leírása^megjegyzés| |++|növelés|//++x// azonos ezzel: x = x + 1;| | |%%--%%|csökkentés|//%%--%%x// azonos ezzel: x = x - 1; | | |+=|összetett hozzáadás|//x += y;// azonos ezzel: x = x + y; | | |-=|összetett kivonás|//x -= y;// azonos ezzel: x = x - y; | | |*=|összetett szorzás|//x *= y;// azonos ezzel: x = x * y; | | |/=|összetett osztás|//x /= y;// azonos ezzel: x = x / y; | | |%=|összetett maradék-képzés|//x %= y;// azonos ezzel: x = x % y; | | |&=|összetett bitenkénti és|//x &= y;// azonos ezzel: x = x & y; | | |%%|%%=|összetett bitenkénti vagy|//x %%|%%= y;// azonos ezzel: x = x %%|%% y; | | ===== Egyéb operátorok ===== {{anchor:miscellaneous_operators}} ^operátor^leírása^példa| |sizeof()|A változó aktuális méretével tér vissza.|sizeof(a), ha az "a" integer, akkor 4-gyel tér vissza.| |&|A változó címével tér visssza.|&a; Az "a" változó címét adja meg.| |*|Pointer a változóra.|*a;| |(feltétel) ? X : Y;|Feltételes kifejezés.|Ha a feltétel igaz, a ? után az X : egyébként az Y lesz az eredmény.| // OB121.com példaprogram - Vámos Sándor (2019) // spec. operátorok alkalmazása az Arduino-ban int a = 4; short b; double c; int* ptr; void setup() { Serial.begin(9600); } void loop() { /* example of sizeof operator */ Serial.print("Size of variable int is "); Serial.println(sizeof(a)); Serial.print("Size of variable short is "); Serial.println(sizeof(b)); Serial.print("Size of variable double is "); Serial.println(sizeof(c)); /* example of & and * operators */ ptr = &a; /* 'ptr' now contains the address of 'a'*/ Serial.print("value of &a is "); Serial.println(a); /* example of ternary operator */ a = 10; b = (a == 1) ? 20: 30; Serial.print("first case the value of b is "); Serial.println(b); b = (a == 10) ? 20: 30; Serial.print("second case the value of b is "); Serial.println(b); delay(30000); }