Cum citești cod Arduino fără să te pierzi
Acum că ai flashed blink-ul, hai să-l înțelegem linie cu linie. setup, loop, #include, tipuri de numere, millis() — și ce înseamnă mesajul de eroare când ai uitat un `;`.
Ce înveți
- Diferența dintre setup() și loop() — și de ce e importantă
- Ce face #include și de ce-l pui sus
- Tipuri de numere: int, bool, unsigned long, const int — când folosești fiecare
- Cum funcționează millis() și de ce-i mai bun decât delay()
Acum că ai flashed blink-ul (din lecția 06), hai să-l înțelegem linie cu linie. După lecția asta, când te uiți la orice cod Arduino n-o să mai pară magie — o să știi unde să te uiți primul.
Anatomia unui sketch Arduino
Codul Arduino are mereu 3 secțiuni, în ordinea asta:
// 1. Include-uri și constante (sus, înainte de orice)
#include <WiFi.h>
const int LED = 2;
// 2. void setup() — rulează O SINGURĂ DATĂ la pornire/reset
void setup() {
Serial.begin(115200);
pinMode(LED, OUTPUT);
}
// 3. void loop() — rulează LA NESFÂRȘIT, cât ESP32-ul e pornit
void loop() {
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
delay(500);
}
Ține minte: setup() se cheamă o dată. loop() se reia mereu, automat,
de mii de ori pe secundă. Tot ce trebuie să rămână constant (pinMode, Serial.begin,
WiFi.begin) → setup(). Tot ce trebuie să se întâmple iar și iar (citește buton,
clipește LED) → loop().
#include — bibliotecile
#include <WiFi.h> zice „adu funcțiile din biblioteca WiFi în programul meu”.
Fără #include, dacă scrii WiFi.begin(...), compilatorul nu știe ce-i WiFi
și aruncă eroare 'WiFi' was not declared in this scope.
Bibliotecile vin în 3 feluri:
- Built-in în ESP32 —
<WiFi.h>,<esp_sleep.h>,<EEPROM.h> - Instalate din Library Manager —
<Adafruit_SSD1306.h>pentru OLED,<Adafruit_NeoPixel.h>pentru WS2812 - Locale în folder cu sketch-ul —
<config.h>scris de tine
Tipuri de numere — care când
int contor = 5; // de la -2 miliarde la +2 miliarde
bool gata = false; // doar true sau false
unsigned long timp = millis(); // doar pozitiv, până la 4 miliarde
const int PIN_LED = 2; // CONST = nu se mai schimbă niciodată
int— numere obișnuite. Întreg. Pozitiv sau negativ. „Câți pietoni am numărat: int.”bool— adevărat/fals. „Sirena e activă: bool. Butonul e apăsat: bool.”unsigned long— numere mari pozitive. Folosit aproape exclusiv cumillis(). „Câte milisecunde de la pornire: unsigned long, pentru căintse umple după 32 secunde și începe iar de la −2 miliarde.”const int PIN_LED = 2;— declari o dată, folosești în tot codul. Dacă vrei să muți LED-ul de pe pin 2 pe pin 4, schimbi într-un singur loc. Mereu cu MAJUSCULE ca să se vadă că-i constantă.
millis() — secretul timpului fără blocaj
delay(1000) zice „stai aici 1 secundă, nu face nimic altceva”. Asta-i OK
pentru blink simplu, dar e CATASTROFĂ pentru VIA. Dacă semaforul „doarme”
500ms cu delay(), nu poate primi mesajul de ambulanță în acel timp.
millis() rezolvă problema. Returnează câte milisecunde au trecut de când
s-a pornit placa.
unsigned long ultima_clipire = 0;
const unsigned long INTERVAL = 500; // 500ms
void loop() {
if (millis() - ultima_clipire >= INTERVAL) {
// au trecut 500ms — toggle LED
digitalWrite(LED, !digitalRead(LED));
ultima_clipire = millis(); // resetez cronometrul
}
// … aici poți citi butoane, primi mesaje, fără să blocheze nimic
}
Mecanismul: salvezi „momentul ultimei acțiuni”, verifici la fiecare loop dacă a trecut suficient timp. Dacă da → faci acțiunea + resetezi salvarea.
Funcții — apel cu argumente
digitalWrite(2, HIGH) cheamă funcția digitalWrite cu 2 argumente: pinul
și valoarea. Ordinea contează. Nu poți zice digitalWrite(HIGH, 2) — e
greșit.
digitalWrite(pin, valoare); // (int, int) — pune valoarea pe pin
delay(ms); // (int) — așteaptă ms milisecunde
Serial.println(text); // (string) — printează cu \n la final
pinMode(pin, INPUT_PULLUP); // (int, int) — pune pinul ca intrare cu pull-up
Când vezi o funcție necunoscută, întreabă-te:
- Câte argumente?
- Ce tip e fiecare?
- Ce returnează? (
int?bool?void= nimic?)
Documentația răspunde la toate trei.
Comentarii — nu se execută
// Asta-i comentariu pe O SINGURĂ linie
/* Asta-i comentariu pe
MAI MULTE linii */
Compilatorul ignoră comentariile. Folosește-le să-ți amintești de ce ai scris ceva. Nu ce (codul deja zice ce), ci de ce.
Exemplu bun: // 50ms = anti-debounce. Sub 50ms butonul „bate" și se înregistrează apăsări duble.
Exemplu inutil: // setez pinul 2 ca ieșire. Codul deja zice asta — nu adaugi info.
Erori frecvente și cum le citești
Când compilatorul îți aruncă o eroare, citește prima linie și numărul liniei.
| Eroare | Ce înseamnă | Cum repari |
|---|---|---|
expected ';' before '}' | Ai uitat ; undeva înainte de } | Te uiți la ultimele instrucțiuni înainte de acolada închisă |
'XYZ' was not declared in this scope | Folosești ceva ce compilatorul nu cunoaște | Lipsă #include? Greșit numele? Litera mare/mică? |
expected primary-expression before ')' | Argumente lipsesc dintr-o funcție | Vezi funcție( ) cu paranteză goală sau virgule fără valori |
redefinition of 'X' | Ai declarat de două ori același nume | Caută int X și const int X — păstrează unul singur |
Regula de aur: când vezi roșu, nu intra în panică. Compilatorul îți
spune linia + ce nu i-a plăcut. 90% din erori sunt ; lipsă, parantezi
neînchise, sau litere greșite.
Test pe cod necunoscut
Uite o linie din lecția 08 (car-tag):
WiFi.scanNetworks(true, true, false, 100, 1);
Citește-o așa:
WiFi— obiectul (cunoscut din#include <WiFi.h>).scanNetworks— funcția lui(true, true, false, 100, 1)— 5 argumente
5 argumente fără nume — magie. Soluție: în lecția 08 pun wrapper cu nume vorbitor:
const bool ASYNC = true;
const bool SHOW_HIDDEN = true;
WiFi.scanNetworks(ASYNC, SHOW_HIDDEN, false, 100, 1);
// ^ ^ ^
// passive timeout canal
Acum citești și înțelegi din nume.
Recapitulare
setup()o dată.loop()mereu.#includesus, ca să aduci biblioteci.- Tipuri:
int(numere),bool(da/nu),unsigned long(timp),const(nu se schimbă). millis()>delay()când vrei lucruri în paralel.- Funcții = nume + paranteze cu argumente în ordinea specifică.
- Erori roșii — citește prima linie + numărul liniei. Nu panica.
Acum mergi la lecția 07-esp32-pini ca să vezi unde pui firele pe ESP32 când ai înțeles cum se scrie codul care le mișcă.
După lecția asta, poți
- Citești orice sketch Arduino linie-cu-linie fără să te pierzi
- Recunoști structuri comune: setup(), loop(), state machine, debouncing
- Înțelegi de ce millis() e mai bun decât delay() pentru cod care răspunde rapid
- Identifici tipurile corecte (int / unsigned long / const int) pentru fiecare scop
- Cum citești mesajele de eroare ca să le repari fără să intri în panică