Arduino struktúrák
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 megszakításokkal 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
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 összehasonlító operátorokkal 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, continue, return, 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
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 összehasonlító operátorokkal definiálhatjuk a feltételt.
A következő utasításokkal a program lefutása jelentősen módosítható: break, continue, return, goto.
Az if-hez hasonló az ? : operátor működése, lásd itt: 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 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
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, continue, return, 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: 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
A switch funkció az 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, continue, return, 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
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 hurokkal.
A következő utasításokkal a program lefutása jelentősen módosítható: break, continue, return, 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
A do .. while - hasonlóan a 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, continue, return, 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
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
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
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
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 0xDDCCBBAA lesz. Az union például a struct-tal is ötvözhető, lásd: 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 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
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
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
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
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
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
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); }