====== 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);
}