Arduino struktúrák

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()
{
  // ...
}

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
}

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

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

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

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

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++;
}

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

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

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

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
}

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:

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

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);
}
operátor jeleleírásamegjegyzés
=értékadásHa 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
operátor jeleleírásamegjegyzé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
operátor jeleoperátor neveleírásapélda
&&logikai ésigaz, ha minden operandus igaz
összekeverhető az "&" operátorral!
if (digitalRead(2) == HIGH  && digitalRead(3) == HIGH)
||logikai vagyigaz, ha az egyik operandus igaz
összekeverhető az "|" operátorral!
if (x > 0 || y > 0) 
!logikai nemigaz, ha a "!"-t követő operandus hamis
if (!x)
operátor jeleneveleírásamegjegyzé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égrea baloldali "becsúszó" pozíciókat 0-kkal tölti fel
»bitenkénti "shift right"bitenkénti balra eltolás műveletet hajt végrea 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 
operátor jeleneveleírásamegjegyzés
++növelés++x azonos ezzel: x = x + 1;
--csökkentés--x azonos ezzel: x = x - 1;
+=összetett hozzáadásx += y; azonos ezzel: x = x + y;
-=összetett kivonásx -= y; azonos ezzel: x = x - y;
*=összetett szorzásx *= y; azonos ezzel: x = x * y;
/=összetett osztásx /= y; azonos ezzel: x = x / y;
%=összetett maradék-képzésx %= y; azonos ezzel: x = x % y;
&=összetett bitenkénti ésx &= y; azonos ezzel: x = x & y;
|=összetett bitenkénti vagyx |= y; azonos ezzel: x = x | y;
operátorleírásapé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);
}