Atelier.

atelier · lecții

Lecția 06 15 min începător 3 întrebări quiz

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 cu millis(). „Câte milisecunde de la pornire: unsigned long, pentru că int se 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:

  1. Câte argumente?
  2. Ce tip e fiecare?
  3. 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.

EroareCe î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 scopeFolosești ceva ce compilatorul nu cunoașteLipsă #include? Greșit numele? Litera mare/mică?
expected primary-expression before ')'Argumente lipsesc dintr-o funcțieVezi funcție( ) cu paranteză goală sau virgule fără valori
redefinition of 'X'Ai declarat de două ori același numeCaută 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

  1. setup() o dată. loop() mereu.
  2. #include sus, ca să aduci biblioteci.
  3. Tipuri: int (numere), bool (da/nu), unsigned long (timp), const (nu se schimbă).
  4. millis() > delay() când vrei lucruri în paralel.
  5. Funcții = nume + paranteze cu argumente în ordinea specifică.
  6. 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ă