Skip to content
2025.11.07.
  • F
  • X
  • LinkedIn
  • YouTube
  • Instagram
  • GitHub
TavIR

TavIR

Mikrokontroller világ

  • TavIR Tudástár
  • TavIR WebShop
  • TavIR Fórum
  • Hírek
  • Könyvek
    • Egyszerű elektronika – Kezdőlap
    • ESP8266/ESP32
    • Tippek
      • Tippek-trükkök (AVR)
      • Tippek-trükkök (ESP8266/ESP32)
  • +Gyorstippek
  • +Mélyvíz
  • +Témakereső
  • Kapcsolat
  • Főoldal
  • Cikk
  • Rendszerezett Arduino programozás – avagy hogyan győztem le a spagettikódot
  • Cikk
  • Mélyvíz
  • Tippek

Rendszerezett Arduino programozás – avagy hogyan győztem le a spagettikódot

Robert 2025.05.09.
09768 spaghetti robot struggles with spaghetti code - Cseh Robert / TavIR - Arduino,spagettikód,millis()

Nem a vezetékekkel volt baj. Nem a rossz ellenállásértékkel. Nem is a haldokló szenzorokkal. A kóddal. Na, ott volt a kutya elásva. Egy szépen megcsavart, egymásba tekeredett gubanc, amit visszanézve még én sem értettem. Akkor még nem tudtam, hogy amit csinálok, azt a programozók spagetti kódnak hívják. Csak azt láttam, hogy valahogy működik. De ha hozzá kellett nyúlni, rám tört a hideg is, meleg is. Ha pár hónap múltán próbáltam meg kitalálni, mit is akartam vele, inkább hagytam az egészet.

Először vigasztalt, hogy nem vagyok egyedül ezzel. De ez a tudat egy idő után már nem nyugtatott, hanem idegesített. Kellett valami. Rendszer. Valami kapaszkodó, amivel nem csak írni tudom a kódot, de átlátható marad akkor is, ha hozzá kell nyúlni. Itt kezdtem el rájönni a rendszerezett programozás fontosságára. Nem táblázatokból meg tutoriálból, hanem a saját kísérleteimből és zsákutcaiból. Most megmutatom, honnan indultam. Nem szépítem. Lesz benne kód, bénázás, fejvakarás, és remélhetőleg egy kis fellélegzés is a végén. Ha jártál már hasonló cipőben, tudni fogod: ez rólad is szól.

Tartalomjegyzék

Toggle
  • I. Bevezető – Honnan indultam?
    • Az első Arduino kódom: másolt kód és próbálgatás
    • A működő, de érthetetlen program
    • Miért akadtam el?
    • Felismerés: nem (csak) a hardveren múlik
  • II. Mi az a spagettikód?
    • Kód, ami inkább zsonglőrmutatvány, mint építmény
    • Jellemző tünetek: ismétlődés, átláthatatlanság, nehézkes módosíthatóság
    • „Valahogy működik” – de fogalmam sincs, hogyan
    • Mikor válik igazán problémássá?
  • III. Mi a strukturált programozás és mitől jobb?
    • A program logikai tagolása
    • Függvények: újrafelhasználás és rendezés
    • Változók láthatósága: lokális kontra globális
    • Kontrollszerkezetek – egyszerűen és következetesen
    • Kommentek: miért írok a gépnek emberek helyett?
    • Az „egy funkció – egy blokk” szabály
  • IV. Gyakorlati példák – Egy projekt kétféleképpen
    • Probléma: a delay()-alapú vezérlés korlátai
    • millis() – az Arduino beépített időmérője
    • Strukturált, millis()-alapú kód – átgondolt, moduláris vezérlés
    • Műszaki elemzés – mitől jobb ez?
      • Nem-blokkoló működés
      • Moduláris logika
      • Állapotvezérelt vezérlés
      • Precíz időkezelés
  • V. Gondolkodásmód-váltás – Programozás mint építés
    • A fordulópont: nem kódot írok, hanem rendszert építek
    • Tervezés papíron – egyszerűen, gyorsan, céltudatosan
    • Kommentálás menet közben – nem „extra”, hanem művelet
    • Változók és függvények elnevezése – név = szándék
    • DRY – Don’t Repeat Yourself: ne ismételj kódot
    • Tesztelés mint szokás – nem utólagos ellenőrzés
    • Kód mentése verziókkal – egyszerűen, biztonságosan
    • IDE választás: Arduino IDE vagy PlatformIO?
  • VI. Haladó szint – Moduláris programozás Arduino környezetben
    • A pont, ahol egy fájl már nem elég
    • Több fájl, több logika – egy cél
    • Egyszerű állapotgép – strukturált eseménykezelés
      • Példa: három állapotú LED-vezérlés
    • Saját függvénykönyvtár – a „kis library-k” ereje
    • Eseményvezérelt gondolkodás: a valódi valós idejűség felé
    • Speciális fejlesztési minták
  • VII. Záró gondolatok – Nem lettem programozó, csak jobban értem
    • A legfontosabb felismerésem: a kód én vagyok
    • A strukturált gondolkodás túlmutat a képernyőn
    • „De hát én nem vagyok programozó…”
    • Minden új projekt egy új lehetőség a tanulásra
    • Te is elindulhatsz ezen az úton!
    • Források:

I. Bevezető – Honnan indultam?

Az első Arduino kódom: másolt kód és próbálgatás

Az első Arduino alaplapom egy Uno R3 klón volt, amit egy barkácsáruház polcáról emeltem le, gondolkodás nélkül. A csomagban volt pár LED, egy ellenálláscsomag, egy USB kábel, meg egy CD – amit sosem használtam. Minden, amit tudtam, az az volt, hogy „valamit lehet vele villogtatni”. Ez elég is volt ahhoz, hogy letöltsem az Arduino IDE-t, és kerestem egy példát arra, hogyan lehet LED-et villogtatni.

Az első programomat nem írtam, hanem másoltam. Nem értettem, mit csinál a setup() nevű indítófüggvény vagy a loop() nevű ismétlődő végrehajtási blokk, mi az a pinMode(), és miért kell 1000-et írni a delay() zárójelébe. De a LED villogott – és ez lenyűgözött.

Akkoriban még nem sejtettem, hogy valójában nem programoztam, csak másoltam a kódot anélkül, hogy értettem volna. Nem értettem, hogyan működik, csak lemásoltam valamit, ami látszólag működött.

A működő, de érthetetlen program

Ahogy nőtt az önbizalmam, úgy nőtt a kódom is – pontosabban a sorok száma. Először csak egy LED volt, aztán kettő, aztán bejött egy nyomógomb, majd egy hőmérő szenzor, végül egy OLED kijelző. A projektjeim egyre izgalmasabbak lettek, de a kódjaim egyre zavarosabbak.

Egy tipikus Arduino programom így nézett ki:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
void loop() {
  if (digitalRead(2) == HIGH) {
    digitalWrite(13, HIGH);
    delay(1000);
    digitalWrite(13, LOW);
  }
 
  if (analogRead(A0) > 512) {
    digitalWrite(12, HIGH);
    delay(500);
    digitalWrite(12, LOW);
  }
 
  display.setCursor(0, 0);
  display.print("T: ");
  display.print(temperature);
}

Ez így, kiragadva, nem is tűnik olyan szörnyűnek. De amikor 200 sornyi hasonló logika egymás alá kerül, köztes delay()-ekkel, egymással nem összehangolt kódrészekkel, ismétlődő sorokkal, akkor már teljes joggal lehet azt mondani rá: rendezetlen, ún. spagettikód – vagyis olyan, átláthatatlanul kusza kódszerkezet, ahol minden mindennel össze van kapcsolva.

Miért akadtam el?

A baj ott kezdődött, amikor valamin változtatni kellett. Tegyük fel, hogy a LED ne 1 másodpercig világítson, hanem 1,2 másodpercig. Oké, átírtam a delay(1000)-et delay(1200)-ra. Csakhogy négy különböző helyen szerepelt. Melyik az, ami a LED-hez tartozik? És miért kezdett el véletlenszerűen késni az OLED frissítés? Miért nem érzékelte néha a nyomógombot?

Elkezdtem belerakni Serial.println() sorokat, hogy lássam, hol jár a program. Ekkor jöttem rá, hogy a delay() nemcsak várakoztat – hanem megakaszt. Kiderült, hogy a loop()-ba zsúfolt feltételes blokkok elvileg párhuzamosan működnének, de a gyakorlatban minden egymás után történik, és a hosszú delay() miatt semmi sem reagál időben.

A legrosszabb az volt, hogy már én sem láttam át, mi történik, és miért úgy történik. Próbáltam hozzátenni új logikát, de az újabb sorok csak még jobban összekuszálták a régieket.

Felismerés: nem (csak) a hardveren múlik

Sokáig azt hittem, az Arduino „egyszerű eszköz”, amin „egyszerű dolgokat” lehet csinálni. Ez részben igaz is – de csak addig, amíg az ember nem akar valamit jól csinálni. A hardver maga megbízható, a könyvtárak működnek, a példák hasznosak – csak éppen a programlogika kialakítása marad az emberre.

Itt vált igazán fontossá a programozási szemlélet.

A felismerés akkor jött, amikor újra fel akartam használni egy korábbi projektem kódját. Be kellett volna illesztenem egy új szenzort, egy új logikát – de képtelen voltam rá. Nem értettem már, mit miért írtam korábban. A saját kódomat sem tudtam olvashatóként visszafejteni. Akkor kezdtem el keresni, hogy vajon lehet-e ezt másképp csinálni. Hogy van-e szabályos módja a gondolkodásnak az Arduino programozásában. Ekkor kezdtem el foglalkozni azzal, hogyan lehet jól megszervezni egy program működését. Először ösztönösen, később tudatosan próbáltam megérteni, mitől lesz egy kód nem csak működő, de karbantartható is.

Egy Arduino-val felszerelt munkaasztal, háttérben egy lebegő kábelgubanc és digitális kijelzők.
Amikor a kábelek is programozási hibákról árulkodnak.

II. Mi az a spagettikód?

Kód, ami inkább zsonglőrmutatvány, mint építmény

Ha visszagondolok az első komolyabb Arduino-projektjeimre, egy (két) szóval tudnám jellemezni őket: rögtönzés vagy improvizáció. Nem volt bennük előzetes tervezés, sem belső logikai rend – minden sort úgy írtam, ahogy éppen eszembe jutott. Egy-egy új funkció nem a meglévő felépítésbe illeszkedett, hanem csak úgy „hozzátoldottam” valahova a loop() közepére, csak úgy, ahol volt egy kis hely még.

Az ilyen típusú kód a számítógép számára még működőképes – a mikrokontroller elvégzi, amit mondunk neki. Az ember számára azonban teljesen átláthatatlanná válik. Egy ilyen program nem egy ház tervrajzához hasonlít, sokkal inkább egy padlón szétgurított gombolyaghoz.

A név nem véletlen: a spagettikód olyan, mint egy tál összegabalyodott spagetti tészta – nincs benne eleje vagy vége, csak tekergő szálak, amelyeket nehéz követni.

Jellemző tünetek: ismétlődés, átláthatatlanság, nehézkes módosíthatóság

Egy tipikus spagetti kódolású Arduino-projektnél a következő „tünetek” figyelhetők meg – és mindegyiket elkövettem már, többször is:

1. Hosszú loop() függvény, ahol minden logika egy helyre zsúfolódik

A loop() függvény, amely eredetileg az Arduino program ciklikus motorja lenne, nálam inkább egyfajta lerakóhely volt: minden logikai ágat ide tömörítettem. Először a LED, aztán a nyomógomb, majd a kijelző, a hőmérő és végül a WiFi modul. Minden egymás után, sorban, mint egy hosszú bevásárlólista. A program nem volt más, mint egy végtelen feltételhalmaz.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
void loop() {
  if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
  }
 
  if (millis() - lastSensorRead > 2000) {
    temperature = readTemperature();
    display.print(temperature);
    lastSensorRead = millis();
  }
 
  if (Serial.available()) {
    // újabb funkció
  }
 
  // és így tovább...
}

2. Ismétlődő kódrészletek, változók felesleges duplikálása

Az egyik leggyakoribb hibám az volt, hogy ugyanazt a logikát többször is leírtam, csak más-más értékekkel. Például három különböző LED vezérlése három if-blokkban – lényegében ugyanazzal a sémával, csak más lábkiosztással.

Ez azért veszélyes, mert ha módosítani kell valamit – mondjuk az időzítést –, akkor minden előfordulást frissíteni kellene. Elég egyet kihagyni, és máris hibás működést tapasztalhatunk.

3. Nehezen követhető logika – „az if az if-ben az if-ben”

Egy másik intő jel a túl sok egymásba ágyazott feltétel. Amikor a logikai szerkezet már nem egyszerű eldöntendő kérdésekből áll, hanem mély, átláthatatlan „if-erdőben” bolyongunk, biztosak lehetünk benne, hogy valamit rosszul csinálunk.

1
2
3
4
5
6
7
if (valami1) {
  if (valami2) {
    if (valami3) {
      doSomething();
    }
  }
}

Ez nemcsak nehezen olvasható, hanem rendkívül sérülékeny is: egyetlen logikai ág elírása teljesen eltérő működést eredményezhet.

4. Minden változó globális

Kezdőként hajlamos voltam minden változót globálisan elérhetővé tenni – vagyis a program bármely részéből módosíthatók voltak. Ez elsőre gyors és kényelmes megoldásnak tűnt, de később számos problémát okozott: bármi bármikor megváltoztathatta egy változó értékét, és egy-egy furcsa működés hátterét nagyon nehéz volt visszafejteni.

5. Hiányzó vagy félrevezető megjegyzések

Írtam ugyan megjegyzéseket, de azok gyakran elavultak voltak (a kód már megváltozott, a komment nem), vagy túlságosan általánosak. Például: // LED bekapcsolása – de melyik LED, milyen esemény hatására? Kommentek híján a kód magában nem volt értelmezhető, és pár hét után nekem is olyan volt, mintha egy idegen szkriptet próbálnék kibogozni.

„Valahogy működik” – de fogalmam sincs, hogyan

A legnagyobb probléma nem az, hogy a spagettikód nem működik – hanem az, hogy működik, csak nem értjük, miért. Olyan ez, mint amikor egy hibás kapcsolót megütögetve mégis felkapcsol a villany – de fogalmunk sincs, mi történik valójában. Ez önámítás – és hosszú távon nagyon veszélyes, mert a hibák rejtve maradnak, és csak akkor jönnek elő, amikor már nehéz visszafejteni a működést.

Egy programozó Arduino-val dolgozik, miközben a képernyőn spagetti kód jelenik meg.
Amikor az Arduino sketch kódja teljesen összegabalyodik.

Mikor válik igazán problémássá?

Az Arduino-világban gyakori tévhit, hogy „kis kód – kis gond” – hiszen csak néhány száz soros projektekről van szó, nem nagy rendszerekről. Ez azonban csalóka: a bonyolultság nem a sorok számán, hanem a logika átláthatóságán múlik.

Amint egy projekt elér egy bizonyos összetettségi szintet – például:

  • több szenzorral dolgozik,
  • különböző bemenetekre más-más válaszokat ad,
  • időzített és megszakításos események keverednek –

ekkor már nem fér bele az ötletszerű, „összeírogatom” típusú megközelítés. Ilyenkor válik elengedhetetlenné a tudatosabb, strukturáltabb tervezés, a strukturált megközelítés…

III. Mi a strukturált programozás és mitől jobb?

A program logikai tagolása

Amikor először hallottam a „strukturált programozás” kifejezést, őszintén szólva nem tudtam mit kezdeni vele. Azt hittem, ez valami egyetemi szóhasználat, ami csak nagy szoftverprojektekhez való. Arduino esetében – gondoltam – minek túlbonyolítani a dolgot? Aztán ahogy nőtt a projektjeim bonyolultsága, rá kellett jönnöm: nem arról van szó, hogy bonyolultabb lesz, hanem arról, hogy átláthatóbbá válik.

A strukturált programozás nem más, mint egyfajta programozási megközelítés, ahol a programot:

  • átlátható logikai blokkokra (értelmezhető részekre) bontjuk,
  • ismételhető funkciókat külön függvényekbe szervezünk,
  • a vezérlés irányát jól követhető logikai szerkezetekkel szabályozzuk,
  • és mindezt úgy tesszük, hogy bármikor vissza tudjunk nyúlni a kódhoz anélkül, hogy újra kelljen megírni az egészet a semmiből.

Függvények: újrafelhasználás és rendezés

Az egyik legelső lépés, amit megtettem, az volt, hogy elkezdtem saját függvényeket írni. Korábban minden logika bent volt a loop()-ban – most viszont logikai egységeket emeltem ki külön eljárásokba.

Például ahelyett, hogy így írnám:

1
2
3
4
5
if (digitalRead(buttonPin) == HIGH) {
  digitalWrite(ledPin, HIGH);
  delay(500);
  digitalWrite(ledPin, LOW);
}

Létrehozok egy önálló függvényt:

1
2
3
4
5
6
7
void blinkLedOnButtonPress() {
  if (digitalRead(buttonPin) == HIGH) {
    digitalWrite(ledPin, HIGH);
    delay(500);
    digitalWrite(ledPin, LOW);
  }
}

És a loop()-ba már csak ennyi kerül:

1
2
3
void loop() {
  blinkLedOnButtonPress();
}

Ez nem tűnik nagy változásnak, de a hatása drámai: a loop() immár a fő vezérlési ciklusként átláthatóbbá válik, míg a részletek el vannak rejtve – pontosabban, külön egységként rendszerezve. Ezen túlmenően, ha három különböző LED-et akarok ugyanígy vezérelni, akkor nem háromszor írom le ugyanazt, hanem a függvényt paraméterezem:

1
2
3
4
5
void blinkLed(int pin, int duration) {
  digitalWrite(pin, HIGH);
  delay(duration);
  digitalWrite(pin, LOW);
}

Ezután:

1
2
3
blinkLed(10, 300);
blinkLed(11, 500);
blinkLed(12, 700);

Ezzel egyszerre csökken a kódsorok száma, nő az olvashatóság, és csökken a hibalehetőség.

Változók láthatósága: lokális kontra globális

Kezdőként minden változót globálisan deklaráltam – ott a fájl tetején, a setup() előtt. Ez egyszerűnek tűnt, mert így bárhol elérhettem őket. Csakhogy amikor sok változóm lett, hamar káoszba torkollott az egész: nem tudtam, hogy melyik értéket mikor és hol írta felül egy másik logika. A strukturált megközelítés itt is egyszerű elvet követ: minden változó a lehető legszűkebb láthatósággal szerepeljen. Ha egy értéket csak egy függvény használ, akkor deklaráljuk azon belül.

Például:

1
2
3
4
void loop() {
  int temperature = analogRead(A0);
  Serial.println(temperature);
}

Ebben az esetben a temperature változó csak a loop()-on belül él – nem tudja „összekeverni” más logikai blokkokkal.

Természetesen, ha több függvénynek is szüksége van egy adott értékre, akkor lehet használni osztályszintű vagy static típusú változókat – de csak akkor, ha ez valóban indokolt. A cél: minimalizálni az oldalsó hatásokat.

Kontrollszerkezetek – egyszerűen és következetesen

Egy másik nagy tanulság számomra az volt, hogy a vezérlési szerkezetekkel való bánásmód is része a struktúrának. Kezdőként sokszor elkövettem azt a hibát, hogy egy switch-case helyett if-ek tömegét írtam egymás alá.

Egy jól tagolt programban világos, mikor kell:

  • if–else – egyszerű logikai elágazásra
  • switch–case – egyértelmű többértékes döntésre (pl. menüválasztás)
  • while, for, do–while – ismétlődő logikákra

Például egy szenzorállapot-kezelés sokkal jobban működik switch–case segítségével:

1
2
3
4
5
6
7
8
9
10
11
switch (systemState) {
  case IDLE:
    // várakozás
    break;
  case READ_SENSOR:
    // szenzorolvasás
    break;
  case DISPLAY_DATA:
    // kijelzés
    break;
}

Ez az elrendezés nem csak esztétikai értelemben jobb – logikailag is értelmezhetőbb.

Kommentek: miért írok a gépnek emberek helyett?

Kezdetben úgy gondoltam, a kommentelés csak „extra”: ha valami nagyon bonyolult, majd odaírok egy megjegyzést. Később rájöttem: a kommentek nem a számítógépnek, hanem azoknak, akik a kódot olvassák –  köztük saját magunknak szólnak;  magamnak, jövőbeli önmagamnak, vagy annak, aki a kódolvasásra és megértésre vetemedik.

De nem mindegy, hogyan kommentelünk. A jó komment nem a kód nyilvánvaló tartalmát ismétli, hanem a háttér-összefüggéseket világítja meg.

Rossz:

1
2
// kapcsolja a LED-et
digitalWrite(ledPin, HIGH);

Jó:

1
2
3
4
// visszajelzés: ha a gomb meg lett nyomva, világít a LED 500 ms-ig
digitalWrite(ledPin, HIGH);
delay(500);
digitalWrite(ledPin, LOW);

A jó komment kontextust ad, nem „fordítja” a kódot.

Az „egy funkció – egy blokk” szabály

Az egyik legfontosabb felismerés számomra az volt, hogy minden függvénynek egyértelmű feladata kell, hogy legyen. Ha egy függvény egyszerre olvas bemenetet, dolgozza fel az adatot, vezérel kimenetet és ír kijelzőre, akkor az valójában nem egy, hanem négy különálló funkciót valósít meg – és sosem lesz újrahasznosítható.

A strukturált programozás egyik alaptétele az SRP – Single Responsibility Principle: egy egységnek csak egyetlen dolga legyen.

Ez nemcsak olvashatóságot eredményez, hanem újrafelhasználhatóságot is biztosít. A függvényeim lassan új eszköztárrá váltak – nem egyszer használt kódrészletek voltak, hanem újra és újra alkalmazható építőelemek.

Négy panelből álló illusztráció, amely bemutatja a programozási stílusok fejlődését a spagetti kódtól a strukturált programozásig.
A kódkáosztól a rendezett struktúráig – a programozás fejlődése.

IV. Gyakorlati példák – Egy projekt kétféleképpen

Probléma: a delay()-alapú vezérlés korlátai

Az Arduino platformon a delay() parancs azt jelenti, hogy a mikrokontroller semmilyen más utasítást nem hajt végre az adott időtartam alatt – ez blokkoló várakozás. Miközben a delay(500) utasítás végrehajtásra kerül, az Arduino nem figyel bemenetet, nem olvas szenzort, nem frissít kijelzőt.

Ezzel a problémával minden kezdő Arduino-fejlesztő hamar találkozik:

  • Nyomógombok „nem reagálnak időben”
  • Kijelző „lefagy”, vagy csak másodpercekkel később frissül
  • Szenzoradatok csak szaggatottan jelennek meg
  • Több esemény nem tud egyszerre „megtörténni”

Ezeket az időzítési hibákat nem a hardver, hanem a programlogika okozza. A delay() egyszerű, de időkritikus környezetekben megbízhatatlanná teszi a működést.

Ezért fontos áttérni a nem-blokkoló időkezelésre, amelynek alapja a beépített millis() függvény.

millis() – az Arduino beépített időmérője

A millis() egy beépített függvény, amely az Arduino bekapcsolása óta eltelt időt adja vissza ezredmásodpercben (ms). A nagy különbség a delay()-hez képest az, hogy nem állítja meg a program futását.

Használatával „időbélyeget” tudunk rögzíteni egy esemény bekövetkezésekor, majd később ellenőrizni, hogy eltelt-e egy bizonyos időtartam.

Strukturált, millis()-alapú kód – átgondolt, moduláris vezérlés

Az alábbi program egy új, strukturált és nem-blokkoló megközelítést mutat:

Cél:

  • A nyomógomb lenyomására a LED világítson 500 ms-ig, miközben a kijelzőn megjelenik a „LED BE” felirat.
  • Ezután automatikusan kapcsoljon ki, és írja ki: „LED KI”
  • Mindez blokkolás nélkül, azaz a loop() közben újra végrehajtható műveletekkel

Végleges program:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#include <Adafruit_GFX.h>;
#include <Adafruit_SSD1306.h>
 
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_RESET -1
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
 
const int ledPin = 13;
const int buttonPin = 2;
 
bool ledState = false;
unsigned long ledOnTime = 0;
const unsigned long ledDuration = 500;
 
void setup() {
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  setupDisplay();
}
 
void loop() {
  handleButtonPress();
  handleLedTiming();
}
 
void setupDisplay() {
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  display.setTextSize(1);
  display.setTextColor(SSD1306_WHITE);
  display.setCursor(0, 0);
  display.print("Indulas...");
  display.display();
  delay(1000);
}
 
void handleButtonPress() {
  if (digitalRead(buttonPin) == HIGH && !ledState) {
    ledState = true;
    digitalWrite(ledPin, HIGH);
    ledOnTime = millis(); // rögzítjük, mikor kapcsolt be
    showMessage("LED BE");
  }
}
 
void handleLedTiming() {
  if (ledState && (millis() - ledOnTime >= ledDuration)) {
    ledState = false;
    digitalWrite(ledPin, LOW);
    showMessage("LED KI");
  }
}
 
void showMessage(String message) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print(message);
  display.display();
}

Műszaki elemzés – mitől jobb ez?

Nem-blokkoló működés

A loop() szabadon futhat, nincs semmilyen delay() vagy más időzítő, ami megakasztaná a folyamatot. A LED bekapcsolása után a program tovább ellenőrzi a nyomógombot vagy más bemeneteket is.

Moduláris logika

A külön függvények felelnek a következőkért:

  • a gomb figyeléséért (handleButtonPress())
  • a LED időzítéséért (handleLedTiming())
  • az OLED kijelző frissítéséért (showMessage())

Ez a szétválasztás teszi lehetővé a kód karbantartását és bővítését.

Állapotvezérelt vezérlés

A ledState változóval nyomon követjük, hogy a LED éppen be vagy ki van kapcsolva. Ez az egyszerű állapotgép-alapú gondolkodás már önmagában hasznos módszer a logika átláthatóbbá tételére, hiszen különválasztja az indítás és a leállítás kezelését.

Precíz időkezelés

A millis() használata nemcsak megbízhatóbb, hanem pontosabb időzítést is tesz lehetővé, mivel az időzítés nem csúszik el a delay() vagy egyéb feldolgozási idők miatt.

Egy programozó figyeli az Arduino millis() függvény idővonalát világító izzókkal.
millis() – az időzítés mestere Arduino-n.

Ez a megközelítés – nem-blokkoló, időbélyegeken alapuló és logikailag jól tagolt – minden komolyabb Arduino projekt alapja, főként akkor, ha egyszerre több érzékelőt, kijelzőt, kommunikációs modult (pl. WiFi, Bluetooth) vagy más perifériát kezelünk párhuzamosan.

V. Gondolkodásmód-váltás – Programozás mint építés

A fordulópont: nem kódot írok, hanem rendszert építek

Egy ideig úgy éreztem, hogy a kódírás olyan, mint egy végeláthatatlan jegyzetfüzet: beírok egy sor új logikát, ellenőrzöm, hogy megy-e, majd jöhet a következő. A logika organikusan „nőtt” – de nem épült. Nem volt terve, nem volt kerete, nem volt szerkezete.

A változást az hozta, amikor először egy hónap elteltével visszanyitottam egy saját projektemet, és fogalmam sem volt, mi mit csinál. Akkor értettem meg: ha úgy kódolok, mint aki épít, akkor később is tudom, mit miért tettem – nem csak a működést, hanem a szerkezetet is értem. Ez volt az első lépés egy rendszerszemlélet felé.

Tervezés papíron – egyszerűen, gyorsan, céltudatosan

Az első új rutin, amit bevezettem, meglepően egyszerű volt: rajzolni kezdtem. Nem bonyolult UML diagramokat vagy mikrokontrolleres adatlapokat – csak egy papírt vettem elő, és felvázoltam:

  • milyen szenzorok, eszközök lesznek a projektben,
  • milyen események történhetnek (pl. gombnyomás, időzítés, értékhatár),
  • ezekre hogyan reagáljon a rendszer.

Ez a fajta kézi skicc nem csak világosabbá tette a célt, hanem elválasztotta a hardvert a szoftverlogikától. Nem azért írok kódot, hogy kipróbáljam, működik-e egy LED – hanem azért, hogy értelmesen válaszoljon egy eseményre.

Kommentálás menet közben – nem „extra”, hanem művelet

Korábban azt hittem, hogy kommentálni „csak a végén kell”, ha marad idő. Ma már tudom, hogy a kommentelés nem kiegészítés – hanem része a kódírásnak. Ahogy írom a sorokat, rögtön leírom mellé, hogy miért írom azt a sort. Ez nem az olvasónak szól – ez nekem szól, későbbre.

Ráadásul nem csak funkcionális kommenteket írok, hanem szerkezeti megjegyzéseket is:

1
2
3
4
5
// Állapot: LED bekapcsolva, várakozás következik
if (ledState && millis() - ledOnTime >= ledDuration) {
  // LED kikapcsolása és kijelző frissítése
  turnLedOff();
}

Ezek nem fordítják le a kódot, hanem segítenek a kód szándékát megérteni.

Változók és függvények elnevezése – név = szándék

Korábban simán írtam ilyen változókat: a, b, c, vagy flag, temp, counter2. Ezekkel még a működést is nehéz volt követni, nemhogy a céljukat.

Ma már igyekszem úgy elnevezni változókat és függvényeket, hogy az elnevezés maga is leíró értékű legyen. Például:

  • buttonPin helyett startButtonPin
  • state helyett ledIsOn
  • update() helyett refreshDisplayStatus()

A jó név nem hosszú, hanem beszédes – és ezzel csökkenti a kommentelési igényt is.

Egy szenzorokkal felszerelt, kerekeken guruló Arduino-alapú robot látható egy műhelyszerű környezetben.
Ultrahangos robotfigyelő: amikor az Arduino életre kel

DRY – Don’t Repeat Yourself: ne ismételj kódot

A strukturált gondolkodás egyik alapszabálya a kódismétlés elkerülése. Eleinte ezt úgy értettem, hogy „ne másoljam be kétszer ugyanazt a sort” – de ma már tudom: ha két logika hasonló, akkor absztrahálható egy közös függvénybe.

Például:

1
2
3
4
5
6
7
8
9
10
11
12
// rossz megoldás:
display.clearDisplay();
display.setCursor(0, 0);
display.print("Üzenet");
display.display();
 
...
 
display.clearDisplay();
display.setCursor(0, 0);
display.print("Másik üzenet");
display.display();

Helyette:

1
2
3
4
5
6
void showMessage(String message) {
  display.clearDisplay();
  display.setCursor(0, 0);
  display.print(message);
  display.display();
}

Ez nemcsak rövidebb, hanem biztonságosabb is: ha változik a kijelzőformátum (pl. betűméret), csak egy helyen kell módosítani.

Tesztelés mint szokás – nem utólagos ellenőrzés

A Serial.print() a kezdők egyik legfontosabb „debugger eszköze” – és ezzel semmi gond nincs. Csakhogy én sokáig későn kezdtem el használni. Ma már minden logikához előre beépítem az ellenőrzést.

Például:

1
2
Serial.print("LED állapot: ");
Serial.println(ledState ? "BE" : "KI");

Ez nemcsak hibakeresésnél jön jól – hanem tanulás közben is: látom, mit csinál a rendszer belül, nem csak azt, amit a LED mutat.

Kód mentése verziókkal – egyszerűen, biztonságosan

Egy másik tanulság, amit fájdalmas úton tanultam meg: mindig ments verziókat. Nem kell Git-et használni (bár az sem árt), de már az is óriási előrelépés, ha fájlnévenként mentem pl:

  • led_test_v1.ino
  • led_test_v2_hozzadva_gomb.ino
  • led_test_v3_oled_verzio.ino

Így bármikor vissza tudok térni egy működő állapothoz – és nem kell félnem a változtatásoktól.

IDE választás: Arduino IDE vagy PlatformIO?

Sokan megmaradnak az Arduino IDE-nél – és ez teljesen érthető. Egyszerű, gyors, kevés beállítást igényel. Ugyanakkor ha valaki komolyabb, moduláris projekteket épít, akkor érdemes megfontolni a PlatformIO használatát (pl. VSCode-ban).

A fő előnyök:

  • Több fájl, könyvtár, projektkezelés
  • Kódírás közbeni javaslatok (autocomplete)
  • Beépített verziókezelés támogatás
  • Részletesebb hibajelzés, build-log

Az áttérés nem kötelező, de strukturált programozáshoz ideális eszköz lehet.

VI. Haladó szint – Moduláris programozás Arduino környezetben

A pont, ahol egy fájl már nem elég

Ahogy fejlődtem, elérkeztem egy ponthoz, ahol a main.ino fájl kezdett túlságosan hosszúra nyúlni. Bár függvényekkel dolgoztam, egy-egy projekt hamar elérte a 300–400 sort. A loop() ugyan letisztult maradt, de a kiegészítő logikák – szenzorkezelés, kijelzőkezelés, állapotlogika – egymás alatt sorakoztak, és kezdett minden túlzsúfolttá válni.

Ez volt az a pont, ahol először szétbontottam a kódomat külön fájlokra. Először még kézzel, utána már az IDE támogatásával. Ezzel egy új korszak kezdődött…

Több fájl, több logika – egy cél

Az Arduino IDE lehetővé teszi, hogy egy projektben több .ino vagy .h/.cpp fájl legyen. Ezek nem külön sketch-ek, hanem a fő program részei – egybe fordulnak a fő fájl tartalmával, ám logikailag szétválaszthatók.

Például:

  • main.ino: a setup() és loop() tartalma, a fő vezérlés
  • display.h/cpp: az OLED kijelző kezelését végző funkciók
  • button.h/cpp: a nyomógomb logikáját kezelő egység
  • states.h: az állapotgép enumerációi, leírásai

Ez a szétválasztás nemcsak esztétikai kérdés, hanem szakmai előrelépés is. Ez a struktúra többféle szempontból is előnyös, hiszen lehetővé válik, hogy:

  • több fejlesztő dolgozzon párhuzamosan egy kódon
  • újrahasznosítható „kódelemek” keletkezzenek
  • könnyebben dokumentálhatóvá váljon a rendszer

Egyszerű állapotgép – strukturált eseménykezelés

A következő nagy lépés az volt, amikor felfedeztem az állapotgépek erejét. Az Arduino világban ez még nem „klasszikus” FSM (Finite State Machine) értelemben vett architektúra – például hiányzik belőle az állapotátmeneteket leíró táblázat vagy eseménykezelő struktúra –, de az alapelvek már itt is jól alkalmazhatók.

Példa: három állapotú LED-vezérlés

Tegyük fel, hogy egy gombbal háromféle LED-állapotot szeretnék váltogatni:

  • KI
  • BE
  • Villogás

A loop() helyett ezt gondolkodásmódot alkalmazom:

1
2
3
4
5
6
7
enum LedState {
  OFF,
  ON,
  BLINK
};
 
LedState currentState = OFF;

Majd loop()-ban:

1
2
3
4
void loop() {
  updateButtonState();
  updateLedBehavior();
}

A updateButtonState() figyeli a gombot és váltja az állapotot:

1
2
3
4
5
6
7
8
9
void updateButtonState() {
  if (digitalRead(buttonPin) == HIGH && !buttonPreviouslyPressed) {
    currentState = static_cast<LedState>((currentState + 1) % 3);
    buttonPreviouslyPressed = true;
  }
  if (digitalRead(buttonPin) == LOW) {
    buttonPreviouslyPressed = false;
  }
}

Az updateLedBehavior() pedig a vezérlést végzi:

1
2
3
4
5
6
7
8
9
10
11
12
13
void updateLedBehavior() {
  switch (currentState) {
    case OFF:
      digitalWrite(ledPin, LOW);
      break;
    case ON:
      digitalWrite(ledPin, HIGH);
      break;
    case BLINK:
      handleBlinking(); // külön logika millis()-alapú villogáshoz
      break;
  }
}

Ez az architektúra lehetővé teszi, hogy az egyes állapotok viselkedését külön logikai blokkban kezeljem – így nem kell if-erdőket írni, és új állapotokat is könnyedén hozzá tudok adni.

Saját függvénykönyvtár – a „kis library-k” ereje

A következő logikus lépés az volt, hogy elkezdtem a saját eszközeimet úgy kialakítani, hogy könyvtárként újra felhasználhatók legyenek (saját library). Ez eleinte csak sima .h/.cpp fájlok formájában történt, de később elkezdtem szabványos Arduino library struktúrát alkalmazni:

  • MyDisplayLib/
    • MyDisplayLib.h
    • MyDisplayLib.cpp
    • keywords.txt

Ezeket be tudtam emelni más projektekbe is, nem kellett újraírni az OLED kezelő funkciókat vagy a nyomógomb stabilizálását szolgáló logikát.

A könyvtárhasználat egyik hatalmas előnye: a saját kódod is dokumentálható és olvashatóvá válik – neked is.

Eseményvezérelt gondolkodás: a valódi valós idejűség felé

A legnagyobb szemléleti ugrás számomra az volt, amikor megértettem, hogy a loop() valójában nem a ciklusom, hanem a valós idejű eseményfigyelőm. A jól struktúrált Arduino-kód nem csupán sorban végrehajtja a dolgokat, hanem reagál eseményekre:

  • gombnyomás
  • idő elteltével bekövetkező esemény (millis())
  • szenzor értékváltozás
  • külső bemeneti változás (pl. soros port, WiFi csomag stb.)

Ez a gondolkodás tette lehetővé, hogy az Arduino projektek ne csak „szimuláljanak” valamit, hanem valós rendszerré váljanak, amelyek időzítése megbízható, gyorsan és stabilan reagálnak.

Speciális fejlesztési minták

Az alábbi minták hasznos segédeszközökké váltak számomra:

  • State machine sablon: külön .cpp/.h fájlban kezelhető, skálázható struktúra
  • Non-blocking időkezelő osztály: millis() alapú időzítésekre
  • Debouncer osztály: stabil nyomógomb figyeléshez
  • Ticker-like struktúra: időzített függvényhívásokhoz (akár 3-4 millis „ütemezés” párhuzamosan)

Tipp: Ezeket közösségi fórumokon vagy GitHubon is megtalálod, de a saját verziód mindig jobban illeszkedik a logikádhoz – érdemes megírni.

VII. Záró gondolatok – Nem lettem programozó, csak jobban értem

A legfontosabb felismerésem: a kód én vagyok

Sokan gondolják – én is így voltam ezzel – hogy a „programozás” egy külön szakma, egy zárt világ, ahová be kell kerülni, vagy meg kell tanulni. Arduinóval kezdeni sokunknak viszont nem szakmai döntés, hanem kíváncsiság: „vajon meg tudom-e csinálni, hogy villogjon egy LED?” És az ember megcsinálja. Működik. Aztán bővül – új ötletek jönnek, új kérdések merülnek fel.

De egy ponton túl nem az a kérdés, hogy „működik-e”, hanem hogy hogyan. Hogy miként épül fel a logika, hogyan lehet bővíteni, visszafejteni, átalakítani. És ott már nem elég, ha „csak írok egy kis kódot”.

Ez volt számomra a fordulópont: amikor rájöttem, hogy a kód nem csak utasítások egymás utánja – hanem a saját gondolkodásom lenyomata. Ha rendezetlen vagy kapkodó vagyok, a kódom is az lesz. Ha átgondolt, lépésenkénti rendszerben dolgozom, akkor a kód is „beszélni” fog.

Illusztráció a spagetti-kód és a strukturált programozás közötti különbségről Arduino témában.
Spagetti vagy rendszer? – Kódolás rendben, Arduino segítségével

A strukturált gondolkodás túlmutat a képernyőn

Azóta, hogy áttértem a strukturált programozási elvekre, nemcsak a kódjaim változtak meg – hanem az, ahogy a problémákat megközelítem. Már nem az az első gondolatom, hogy „hogy tudnám ezt gyorsan megoldani”, hanem hogy hogyan lehet ezt hosszú távon kezelhető módon kialakítani.

Ez a szemlélet kihatott más területekre is:

  • dokumentáció: mindig írok hozzá
  • verziókezelés: nem félek menteni, sőt, verziózok
  • hibaelhárítás: mindig logikusan, a teljes képből kiindulva lépésenként haladok
  • időkezelés: millis()-alapú logikában gondolkodom, nem delay()-ben
  • eseménykezelés: állapotokban, nem feltételblokkokban

És ezek nem „trükkök” – hanem szokások, amelyeket magamnak építettem ki, tapasztalati úton.

„De hát én nem vagyok programozó…”

A mondat, amit a legtöbbet mondtam (és még most is gyakran): „nem vagyok programozó”. És ez nem hamis szerénység – tényleg nem vagyok az. Nem tanultam hivatalosan, nincs informatikai végzettségem. Mégis, ma már olyan projekteket tudok létrehozni, amelyeket egy éve elképzelni sem tudtam.

Mert nem arról van szó, hogy „programozó vagyok-e”, hanem hogy értem-e azt a rendszert, amit működésre akarok bírni. És ez tanulható, sőt: lépésről lépésre, minden új kódnál tanulja is az ember.

Minden új projekt egy új lehetőség a tanulásra

A strukturált kódolás nem cél, hanem eszköz – olyan eszköz, ami minden új projektnél segít jobban gondolkodni. Nem kell tökéletesnek lenned. Nem kell mindent elsőre jól csinálni. De ha már egyszer megérezted, milyen, amikor a kódod magától is érthető, nem akarsz máshogy dolgozni.

Ma már minden új projektet így kezdek:

  • egy vázlat papíron
  • egy üres loop() struktúra
  • egy állapotváltozó és időbélyeg
  • egy funkciók szerint elrendezett mappa vagy fájlszerkezet

És ha egy hiba jön, nem pánikolok – hanem újra végigjárom a logikát. Mert az én logikám van ott, nem egy kölcsönkért példakód.

Te is elindulhatsz ezen az úton!

Ha most kezdesz Arduinózni, és úgy érzed, túl sok az új fogalom, a millió library, a furcsa hibaüzenetek – ne aggódj. Ez teljesen természetes. De tudd, hogy nem a „haladók” kiváltsága strukturáltan dolgozni. Ez nem rang, hanem hozzáállás kérdése.

Ahogy egy LED is akkor világít, ha az áramkör zár, a kódod is akkor „világít”, ha összefüggő rendszerként gondolsz rá – nem csak parancsok listájaként.

Te mit gondolsz?

Írd meg a tapasztalataidat – mit tanultál a saját hibáidból, és hogyan fejlődtél?
Oszd meg velünk: hogyan építed a saját rendszered? Szívesen olvasnám a véleményed a saját kódszervezési megoldásaidról, jó gyakorlatokról – és persze a kihívásokról is!

 

Források:

  • Arduino telepítése step-by-step [TavIR]
  • Olvashatatlan kód / karbantarthatósági problémák [Wikipedia]
  • Arduino references – Structure [Arduino]
  • setup() [Arduino]
  • loop() [Arduino]
  • Példaprogramok [Arduino]

Post navigation

Előző Érettségi: összevont magyar, matematika és irodalom érettségi tételkidolgozás
Következő Sensor Shield V5: prototípusépítés egyszerűen és hibamentesen

Kapcsolódó anyagok

A digitális idő paradoxonja: az óraátállítás árnyoldalai Ködös kertben analóg és digitális óra, köztük egy végtelen jelet formázó fényív, alatta automata locsoló rendszer – az őszi óraátállítás kettőzött időpontját szimbolizálva.
  • Cikk
  • Mélyvíz
  • Tippek

A digitális idő paradoxonja: az óraátállítás árnyoldalai

2025.10.23.
Teker Ed, te tekered? – Az enkóder Illusztrált forgó enkóder modul Arduino fejlesztőkörnyezetben, számítógéppel és elektronikai munkapaddal. Oktatási és DIY elektronikai célokra.
  • Cikk
  • Gyorstippek

Teker Ed, te tekered? – Az enkóder

2025.08.23.
DS1302 trükkök: RAM, írásvédelem, burst mód és csepptöltés (trickle charge) DS1302 RTC modul egy Arduino fejlesztőasztalon, háttérben laptop és prototípus panelek – Arduino DS1302 valós idejű óra interfész bemutató.
  • Cikk
  • Gyorstippek

DS1302 trükkök: RAM, írásvédelem, burst mód és csepptöltés (trickle charge)

2025.08.20.

Hírlevél

Hogy az újdonságokról első kézből értesülj:
→ Feliratkozás a Hírlevélre

Ingyenes tanfolyam

60 nap alatt Arduino - az ingyenes tanfolyam
→ Kattints ide és iratkozz fel!
60 nap alatt Arduino

Szeretnél egy lépéssel a többiek előtt járni?

Ne hagyd ki a legújabb tanfolyamokat, amik még csak most bontogatják szárnyaikat.

Legyél te az első! Tanfolyamok

Alkatrész-tár

→ TavIR WebShop
→ Tanulókészletek

Témakörök

  • Cikk (49)
  • Hír (35)
  • Könyv (34)
    • Egyszerű elektronika tippek (18)
    • ESP8266/ESP32 (1)
    • Mélyvíz (8)
    • Mit ne használjunk Arduino projektekben? (6)
  • Tippek (59)
    • Gyorstippek (20)
    • Tippek-trükkök (AVR) (21)
    • Tippek-trükkök (ESP8266/ESP32) (5)

TavIR WebShop

→ Tovább a TavIR WebShopba
4 csatornás kétirányú jelszintillesztő modul (digitális vonalakhoz, MOSFET)
4 csatornás kétirányú jelszintillesztő modul (digitális vonalakhoz, MOSFET)

Univerzális, 4 csatornás kétirányú jelszintillesztő modul, amely megbízható módon biztosítja a digitális [...]

Mérleg súlymérő cella (500g)
Mérleg súlymérő cella (500g)

A 500 g-os mérleg súlymérő cella egy kis méretű, mégis meglepően pontos terhelésérzékelő, [...]

USB-A - USB-A galvanikus leválasztó (1500V, isolátor, USB 2.0 izolátor, hi-speed/480Mbps)
USB-A - USB-A galvanikus leválasztó (1500V, isolátor, USB 2.0 izolátor, hi-speed/480Mbps)

Az USB-A - USB-A leválasztó a PC védelmét szolgálja, a statikus kisülés [...]

Arduino UNO R4 WiFi (ABX00087) - az eredeti, fejlett Wi‑Fi és Bluetooth funkcionalitású fejlesztőpanel
Arduino UNO R4 WiFi (ABX00087) - az eredeti, fejlett Wi‑Fi és Bluetooth funkcionalitású fejlesztőpanel

Az Arduino UNO R4 WiFi (ABX00087) egy 32‑bites fejlesztőpanel, amely beépített Wi‑Fi és Bluetooth modullal [...]

XKC‑Y25‑T12V érintésmentes folyadékszint‑érzékelő modul, kapacitív működéssel (5–12 V DC)
XKC‑Y25‑T12V érintésmentes folyadékszint‑érzékelő modul, kapacitív működéssel (5–12 V DC)

Az XKC‑Y25‑T12V egy érintkezés nélküli, kapacitív elven működő folyadékszint‑érzékelő, mely ideális zárt, [...]

LiPo akku (902040, 3.7V, 1000mAh)
LiPo akku (902040, 3.7V, 1000mAh)

Ez a 902040 típusú lítium-polimer (LiPo) akkumulátor kompakt megoldást kínál olyan hordozható [...]

12V digitális termosztát modul - beépíthető, tokos kivitelű hőmérséklet-szabályozó (W1209WK/W1209)
12V digitális termosztát modul - beépíthető, tokos kivitelű hőmérséklet-szabályozó (W1209WK/W1209)

A W1209WK digitális termosztát egy kompakt, intelligens hőmérséklet-szabályozó modul 12 V DC [...]

VEML6040 I2C RGBW színmérő modul (IIC)
VEML6040 I2C RGBW színmérő modul (IIC)

A VEML6040 I2C RGBW színmérő modul egy nagy pontosságú, négysávos (R–G–B–W) fényérzékelő, [...]

Elektromágneses lövedék gyorsító (DIY Coil Gun) készlet – Electromagnetic Gun DIY Kit
Elektromágneses lövedék gyorsító (DIY Coil Gun) készlet – Electromagnetic Gun DIY Kit

Ez az Elektromágneses lövedék-gyorsító DIY Készlet (más néven coil gun kit) olyan [...]

USB-A - USB-A galvanikus leválasztó (CH318T, 1500V, USB 2.0 izolátor, full speed (480Mbps), 400mA)
USB-A - USB-A galvanikus leválasztó (CH318T, 1500V, USB 2.0 izolátor, full speed (480Mbps), 400mA)

A CH318T alapú USB 2.0 nagysebességű galvanikus leválasztó modul célja, hogy biztonságos [...]

Akril tok ESP32‑S3 4,3 hüvelykes 800×480 kijelzős fejlesztőpanelhez – LVGL HMI kompatibilis
Akril tok ESP32‑S3 4,3 hüvelykes 800×480 kijelzős fejlesztőpanelhez – LVGL HMI kompatibilis

Ez az akrilház (plexi tok) kifejezetten az ESP32‑S3 alapú, 4,3 hüvelykes, 800×480 [...]

LM35D / LM35DZ lineáris, analóghőmérséklet‑érzékelő modul
LM35D / LM35DZ lineáris, analóghőmérséklet‑érzékelő modul

Ez az LM35D / LM35DZ típusra épülő hőmérséklet‑érzékelő modul egyszerű, megbízható és [...]

Fórum

  • Ami máshova nem besorolható... :: Re: Melyik humanoid robot gyártó lesz a piacvezető 2030-ban?
  • Ami máshova nem besorolható... :: Melyik humanoid robot gyártó lesz a piacvezető 2030-ban?
  • Bascom-AVR nyelvű programozás (AVR programozásának lehetőségei) :: Re: DC servo motor szabalyzo
  • Tovább a TavIR Fórumra...

Címkék

alappanel Arduino Arduino nap Arduino nap 2023 art atmel AVR billentyűzet biztosíték darlington dióda eeprom egyszerű elektronika elem ellenállás ESP Espressif Systems flash Forrasztás ft232 fusebit hang hőmérő i2c i2clcd infravörös ISP JTAG kijelző LCD lm35 megvilágítás microchip MOSFET motor pcb páratartalom Relé RTC telepítés tmp36 tranzisztor Uno Zener óra

Archívum

  • 2025. október (3)
  • 2025. augusztus (3)
  • 2025. július (7)
  • 2025. június (4)
  • 2025. május (6)
  • 2025. április (5)
  • 2025. március (4)
  • 2025. február (1)
  • 2025. január (6)
  • 2024. december (5)
  • 2024. november (5)
  • 2024. október (6)
  • 2024. szeptember (5)
  • 2024. augusztus (4)
  • 2024. július (3)
  • 2024. június (1)
  • 2024. május (3)
  • 2024. március (1)
  • 2024. február (2)
  • 2024. január (1)
  • 2023. december (3)
  • 2023. szeptember (2)
  • 2023. augusztus (6)
  • 2023. július (2)
  • 2023. június (1)
  • 2023. május (1)
  • 2023. április (10)
  • 2023. február (1)
  • 2022. szeptember (2)
  • 2022. július (1)
  • 2022. május (6)
  • 2022. április (1)
  • 2022. március (2)
  • 2022. január (2)
  • 2021. december (1)
  • 2021. november (4)
  • 2021. október (2)
  • 2021. szeptember (1)
  • 2021. július (1)
  • 2021. május (2)
  • 2021. április (1)
  • 2021. március (2)
  • 2020. szeptember (1)

Eddig nem olvasott...

A digitális idő paradoxonja: az óraátállítás árnyoldalai Ködös kertben analóg és digitális óra, köztük egy végtelen jelet formázó fényív, alatta automata locsoló rendszer – az őszi óraátállítás kettőzött időpontját szimbolizálva.
  • Cikk
  • Mélyvíz
  • Tippek

A digitális idő paradoxonja: az óraátállítás árnyoldalai

2025.10.23.
Qualcomm-Arduino: amikor a nyílt hardver találkozik az ipari óriással Közelkép egy Arduino UNO Q mikrokontroller panelről, amelyen jól látható a Qualcomm Dragonwing logó és a nyomtatott áramkörök részletei. AI-alapú beágyazott rendszerekhez és prototípusfejlesztéshez ideális.
  • Hír

Qualcomm-Arduino: amikor a nyílt hardver találkozik az ipari óriással

2025.10.08.
Arduino UNO Q – Az új korszak kezdete: Linux és valós idejű vezérlés egy lapon Egy futurisztikus megvilágítású Arduino UNO Q fejlesztőlap, középpontban egy Qualcomm QRB2210 chip, kék alaplapon mikrokontrolleres és IoT-alkalmazásokhoz optimalizált alkatrészekkel. AI és IoT fejlesztésekhez készült hardver.
  • Hír

Arduino UNO Q – Az új korszak kezdete: Linux és valós idejű vezérlés egy lapon

2025.10.07.
Teker Ed, te tekered? – Az enkóder Illusztrált forgó enkóder modul Arduino fejlesztőkörnyezetben, számítógéppel és elektronikai munkapaddal. Oktatási és DIY elektronikai célokra.
  • Cikk
  • Gyorstippek

Teker Ed, te tekered? – Az enkóder

2025.08.23.

Információk

Cégadatok-impresszum | Használati feltételek
Adatvédelmi irányelvek | Kapcsolat

Elérhetőség

Ügyfélszolgálat: +36 (20) 99-23-781
E-mail: avr (kukac)tavir (pont) hu
Iroda/telephely: 1181 Budapest, Szélmalom utca 13.
Copyright © TavIR Minden jog fenntartva | DarkNews by AF themes.
TavIR
Manage your privacy

To provide the best experiences, we and our partners use technologies like cookies to store and/or access device information. Consenting to these technologies will allow us and our partners to process personal data such as browsing behavior or unique IDs on this site and show (non-) personalized ads. Not consenting or withdrawing consent, may adversely affect certain features and functions.

Click below to consent to the above or make granular choices. Your choices will be applied to this site only. You can change your settings at any time, including withdrawing your consent, by using the toggles on the Cookie Policy, or by clicking on the manage consent button at the bottom of the screen.

Funkcionális Always active
A technikai tárolás vagy hozzáférés szigorúan szükséges az előfizető vagy felhasználó által kifejezetten kért konkrét szolgáltatás használatának lehetővé tételének jogos céljához, vagy kizárólag a közlés elektronikus hírközlő hálózaton keresztüli továbbításának céljához.
Beállítások
A technikai tárolás vagy hozzáférés a jogos célból szükséges, hogy olyan beállításokat tároljunk, amelyeket az előfizető vagy a felhasználó nem kért.
Statisztika
Kizárólag statisztikai célokra használt technikai tároló vagy hozzáférés. The technical storage or access that is used exclusively for anonymous statistical purposes. Without a subpoena, voluntary compliance on the part of your Internet Service Provider, or additional records from a third party, information stored or retrieved for this purpose alone cannot usually be used to identify you.
Marketing
A technikai tárolás vagy hozzáférés felhasználói profilok létrehozásához szükséges hirdetések küldéséhez, illetve a felhasználó nyomon követéséhez egy vagy több weboldalon hasonló marketingcélokból.
Statistics

Marketing

Features
Always active

Always active
Manage options Manage services Manage {vendor_count} vendors Read more about these purposes
Manage options
{title} {title} {title}