ESP32: senzor svetlosti i svetleći prsten (WS2812)

Lekcija 17 od 28 · Arduino i ESP32

U lekciji o merenju osvetljenja ESP32 je palio jednu LED diodu kada padne mrak. Sada umesto nje koristimo svetleći prsten sa 12 RGB dioda (WS2812, poznat i kao NeoPixel). Svaka dioda na prstenu može da dobije svoju boju, a sve se upravljaju preko samo jednog pina. Pravimo noćno svetlo koje pali više dioda što je mračnije.

Gotova vežba: ESP32, LDR modul i svetleći prsten
Gotova vežba: u mraku prsten svetli

Kako radi svetleći prsten

  • Svaka dioda u sebi ima tri male LED diode (crvenu, zelenu i plavu) i mali čip koji pamti boju.
  • ESP32 šalje niz podataka na ulaz DIN (IN). Prva dioda uzme svoju boju, a ostatak prosledi sledećoj – kao kad se poruka prenosi niz red.
  • Boja se zadaje sa tri broja od 0 do 255: Color(crvena, zelena, plava). Na primer Color(255, 0, 0) je crvena, a Color(255, 255, 255) bela.
  • Pri punoj jačini jedna dioda troši do 60 mA – 12 dioda skoro 0,75 A. Zato jačinu smanjujemo naredbom setBrightness().

Povezivanje

Šema povezivanja svetlećeg prstena sa ESP32
Šema povezivanja svetlećeg prstena sa ESP32
DeoPriključakESP32
svetleći prstenPWR (5V/VCC)3V3 (za 12 dioda pri maloj jačini) ili 5V (VIN)
svetleći prstenGNDGND
svetleći prstenIN (DIN)GPIO4
LDR modulVCC3V3
LDR modulGNDGND
LDR modulAO (analogni izlaz)GPIO34
Savet: ako prsten napajaš sa 5 V, a signal sa ESP32 je 3,3 V, prsten obično radi, ali ponekad prva dioda „pogreši“ boju. Pomaže otpornik od 330 Ω na žici DIN i kondenzator od 470–1000 µF između PWR i GND prstena.
ESP32 i LDR modul na eksperimentalnoj ploči
ESP32 i LDR modul na eksperimentalnoj ploči

Korak 1: test prstena

U Arduino IDE-u instaliraj biblioteku Adafruit NeoPixel (Sketch → Include Library → Manage Libraries). Prvi program samo proverava da li prsten radi – diode se pale redom u tri boje:

// ESP32 – test svetlećeg prstena (WS2812 / NeoPixel)
// Biblioteka: Adafruit NeoPixel (Library Manager)
#include <Adafruit_NeoPixel.h>

const int PRSTEN_PIN = 4;       // DIN (IN) prstena na GPIO4
const int BROJ_LED = 12;        // broj dioda na prstenu (12, 16 ili 24)

Adafruit_NeoPixel prsten(BROJ_LED, PRSTEN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  prsten.begin();
  prsten.setBrightness(40);     // 0–255; mala jačina štedi struju (i oči)
}

void loop() {
  // diode se pale jedna po jedna – crveno, zeleno, plavo
  uint32_t boje[3] = { prsten.Color(255, 0, 0), prsten.Color(0, 255, 0), prsten.Color(0, 0, 255) };
  for (int b = 0; b < 3; b++) {
    for (int i = 0; i < BROJ_LED; i++) {
      prsten.setPixelColor(i, boje[b]);
      prsten.show();            // tek show() šalje boje prstenu
      delay(60);
    }
  }
  prsten.clear();
  prsten.show();
  delay(300);
}

Važno: setPixelColor() samo pamti boju u memoriji ESP32. Prsten se promeni tek kada pozovemo show().

Korak 2: noćno svetlo

Sada čitamo LDR senzor i od broja koji vrati analogRead() računamo koliko dioda treba da svetli. Kod većine LDR modula vrednost raste kada je mračnije; ako je kod tebe obrnuto, zameni vrednosti SVETLO i MRAK.

// ESP32 – noćno svetlo: što je mračnije, to više dioda svetli
#include <Adafruit_NeoPixel.h>

const int LDR_PIN = 34;         // AO izlaz LDR modula (ADC1)
const int PRSTEN_PIN = 4;
const int BROJ_LED = 12;

// kalibracija: pročitaj vrednosti u Serial Monitoru i upiši svoje
const int SVETLO = 800;         // vrednost kada je svetlo u sobi
const int MRAK   = 3500;        // vrednost kada je senzor pokriven rukom

Adafruit_NeoPixel prsten(BROJ_LED, PRSTEN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  Serial.begin(115200);
  prsten.begin();
  prsten.setBrightness(60);
}

void loop() {
  int ldr = analogRead(LDR_PIN);              // kod većine modula: veći broj = manje svetla
  int upaljeno = map(ldr, SVETLO, MRAK, 0, BROJ_LED);
  upaljeno = constrain(upaljeno, 0, BROJ_LED);

  for (int i = 0; i < BROJ_LED; i++) {
    if (i < upaljeno) {
      prsten.setPixelColor(i, prsten.Color(255, 160, 40));   // toplo belo
    } else {
      prsten.setPixelColor(i, 0);                            // ugašeno
    }
  }
  prsten.show();

  Serial.print("LDR: ");
  Serial.print(ldr);
  Serial.print("  upaljeno dioda: ");
  Serial.println(upaljeno);
  delay(100);
}

Kalibracija

  1. Pokreni program i otvori Serial Monitor (115200).
  2. Zapiši vrednost LDR pri svetlu u sobi – to je SVETLO.
  3. Pokrij senzor rukom i zapiši vrednost – to je MRAK.
  4. Upiši te brojeve u program i pošalji ga ponovo.

map() može da da broj manji od 0 ili veći od 12 (ako je svetlije nego pri kalibraciji), zato posle njega stoji constrain().

Zadaci za vežbu

  1. Promeni boju noćnog svetla u plavu ili zelenu.
  2. Neka prsten trepće crveno kada je potpuno mračno (sve diode bi trebalo da svetle).
  3. Napravi „disanje“ prstena: jačina se polako menja od 10 do 150 i nazad.
  4. Boja neka zavisi od osvetljenja: žuta na svetlu, plava u mraku, a između – prelaz.
Rešenje: boja zavisi od osvetljenja
// Zadatak – boja zavisi od osvetljenja: plavo u mraku, žuto na svetlu
#include <Adafruit_NeoPixel.h>

const int LDR_PIN = 34;
const int PRSTEN_PIN = 4;
const int BROJ_LED = 12;

Adafruit_NeoPixel prsten(BROJ_LED, PRSTEN_PIN, NEO_GRB + NEO_KHZ800);

void setup() {
  prsten.begin();
  prsten.setBrightness(50);
}

void loop() {
  int ldr = constrain(analogRead(LDR_PIN), 0, 4095);
  int t = map(ldr, 0, 4095, 0, 255);          // 0 = svetlo, 255 = mrak
  // mešamo žutu (255, 200, 0) i plavu (0, 0, 255) srazmerno vrednosti t
  int r = map(t, 0, 255, 255, 0);
  int g = map(t, 0, 255, 200, 0);
  int b = map(t, 0, 255, 0, 255);
  prsten.fill(prsten.Color(r, g, b));
  prsten.show();
  delay(50);
}

Proveri znanje

Otvori kviz

Kviz: senzor svetlosti i svetleći prsten

1. Preko koliko signalnih pinova ESP32 upravlja svim diodama prstena?




2. Šta mora da se pozove da bi prsten prikazao nove boje posle setPixelColor()?




3. Koju boju daje Color(0, 0, 255)?




4. Zašto posle map() stoji constrain()?