RGB laboratorija: napravi svoju boju

Napravi RGB mikser u kojem taster bira crveni, zeleni ili plavi kanal, a jedan potenciometar podešava njegov intenzitet. Nauči povezivanje zajedničke katode i anode.

Prvi koraci sa ESP32 i ArduinomPočetni nivo90 min

Ciljevi učenja

  • Prepoznati RGB diode sa zajedničkom katodom i zajedničkom anodom.
  • Povezati R, G i B na odvojene PWM izlaze preko tri zasebna otpornika.
  • Koristiti taster sa debounce obradom za izbor kanala.
  • Čuvati tri intenziteta u nizu i mijenjati samo izabrani kanal.
  • Objasniti trenutno preuzimanje položaja potenciometra pri izboru kanala.
  • Sastaviti i provjeriti magenta i cijan kombinacije.

Prije početka

Završeni kursevi 02, 03 i 05: LED i otpornik, INPUT_PULLUP i debounce, analogno očitavanje i PWM.

Referentna postavka

Ploča u Arduino IDE-u
ESP32 Dev Module
Arduino-ESP32
3.3.12
Serial Monitor
115200 baud

Ovo je referentni profil, a ne identifikacija ploče sa fotografije. Za ESP32-C3/S2/S3 ili drugačije označenu ploču treba prilagoditi GPIO i provjeriti šemu prije spajanja.

Šta ćemo napraviti

Napravićemo malu laboratoriju boja sa RGB LED diodom, jednim potenciometrom i tasterom. Taster bira crveni, zeleni ili plavi kanal, a potenciometar podešava izabranu boju. Druge dvije vrijednosti ostaju sačuvane u radnoj memoriji dok ih ponovo ne izabereš. Rezultat je boja nastala njihovim zajedničkim svjetlom.

Šta ćeš naučiti

  • Razlikovati zajedničku katodu i zajedničku anodu RGB diode.
  • Povezati tri LED kanala sa zasebnim otpornicima.
  • Upravljati trima vrijednostima pomoću jednog potenciometra.
  • Koristiti taster za kružni izbor kanala R, G i B.
  • Objasniti razliku između zadate svjetline i električnog PWM izlaza.

Predznanje

Završi kurseve 02, 03 i 05. Potrebno je da razumiješ polaritet LED, otpornik, INPUT_PULLUP, uklanjanje odbijanja kontakta i skaliranje analognog očitavanja. Koristimo klasični ESP32/ESP32-WROOM-32 i njegove oznake GPIO; ova šema nije namijenjena pločama C3, S2 ili S3 bez posebnog prilagođavanja.

Potrebna oprema

KomponentaKoličinaSpecifikacija i napomene
ESP32 razvojna ploča sa klasičnim ESP32-WROOM-32 modulom1GPIO nazivi moraju odgovarati referentnom profilu; fizički položaj izvoda provjeriti na ploči.
USB kabl za podatke i napajanje1Priključak prilagoditi ploči; komplet na slici navodi Micro-USB.
Eksperimentalna ploča1Komplet navodi 830 kontaktnih tačaka. Provjeriti eventualni prekid naponskih vodova.
RGB LED sa četiri izvoda1R, G, B i zajednički izvod COM. Podržane su odvojene šeme za zajedničku katodu ili anodu; redoslijed nogica nije pretpostavljen.
Otpornik 220 Ω3Po jedan otpornik za svaku LED granu; 220 Ω iz kompleta.
Potenciometar 10 kΩ1Dva krajnja izvoda i klizač W; raspored utvrditi prema stvarnoj komponenti.
Trenutni taster1Koristiti par priključaka koji se spaja pritiskom; ista strana četvoronožnog tastera može već biti spojena.
Spojni kablovi10M-M ili F-M prema priključcima ploče.

Okvirna količina; odabrati M-M/F-M prema ploči.

RGB LED sa četiri izvoda nije isto što i adresabilni RGB modul. Za ovu vježbu treba nam zajednički izvod i tri zasebna izvoda boja. Pripremi tri otpornika od 220 Ω: svaki kanal mora imati svoj otpornik.

Kako nastaje boja

RGB kućište sadrži crveni, zeleni i plavi svjetlosni element. Njihov intenzitet zadajemo brojevima od 0 do 255. Zajednički doprinos crvene i zelene daje žućkasto svjetlo; crvena i plava daju magentu, a zelena i plava cijan. Tačan izgled zavisi od diode i odnosa intenziteta njenih kanala.

Kod zajedničke katode zajednički izvod ide na GND, pa veća PWM uključenost znači više svjetla. Kod zajedničke anode zajednički izvod ide na 3V3: kanal svijetli kada njegov izlaz povlači struju prema GND. Zato program za tu varijantu računa izlaz kao 255 minus zadati intenzitet.

Povezivanje i izbor varijante

RGB — zajednička katoda

Osnovna varijanta

Zajednički izvod COM ide na GND. U programu ostaje COMMON_ANODE false. Oznake R/G/B/COM su funkcije, a ne fizički redoslijed nogica.

Potrebna postavka programa: #define COMMON_ANODE false

RGB — zajednička katoda — električne veze navedene u tabeli ispod
RGB — zajednička katodaUvećajSVGPNG
Veze · RGB — zajednička katoda
OdDoOpis veze
ESP32.GPIO25R1.1PWM crvenog kanala.
R1.2RGB1.ROtpornik 220 Ω za crveni kanal.
ESP32.GPIO26R2.1PWM zelenog kanala.
R2.2RGB1.GOtpornik 220 Ω za zeleni kanal.
ESP32.GPIO33R3.1PWM plavog kanala.
R3.2RGB1.BOtpornik 220 Ω za plavi kanal.
RGB1.COMESP32.GNDZajednička katoda; COMMON_ANODE ostaje false.
ESP32.3V3RV1.END_AJedan kraj potenciometra 10 kΩ.
ESP32.GNDRV1.END_BDrugi kraj potenciometra.
RV1.WESP32.GPIO34Klizač prema analognom ulazu ADC1.
ESP32.GPIO27SW1.CONTACT_ADigitalni ulaz sa uključenim INPUT_PULLUP.
SW1.CONTACT_BESP32.GNDOdabrani par kontakata spaja se tek pritiskom.

RGB — zajednička anoda

Alternativna varijanta

COM ide na 3V3. U programu postaviti COMMON_ANODE true. Svaki kanal i dalje ima svoj otpornik 220 Ω.

Potrebna postavka programa: #define COMMON_ANODE true

RGB — zajednička anoda — električne veze navedene u tabeli ispod
RGB — zajednička anodaUvećajSVGPNG
Veze · RGB — zajednička anoda
OdDoOpis veze
ESP32.GPIO25R1.1PWM crvenog kanala.
R1.2RGB1.ROtpornik 220 Ω za crveni kanal.
ESP32.GPIO26R2.1PWM zelenog kanala.
R2.2RGB1.GOtpornik 220 Ω za zeleni kanal.
ESP32.GPIO33R3.1PWM plavog kanala.
R3.2RGB1.BOtpornik 220 Ω za plavi kanal.
RGB1.COMESP32.3V3Zajednička anoda; postaviti COMMON_ANODE true.
ESP32.3V3RV1.END_AJedan kraj potenciometra 10 kΩ.
ESP32.GNDRV1.END_BDrugi kraj potenciometra.
RV1.WESP32.GPIO34Klizač prema analognom ulazu ADC1.
ESP32.GPIO27SW1.CONTACT_ADigitalni ulaz sa uključenim INPUT_PULLUP.
SW1.CONTACT_BESP32.GNDOdabrani par kontakata spaja se tek pritiskom.

Šeme prikazuju električne funkcije izvoda, a ne univerzalan redoslijed nožica. Najprije utvrdi tip diode i izvode R, G, B i zajednički izvod iz dokumentacije konkretnog dijela, njegovih oznaka ili provjerenog ispitivanja dioda. Sama fotografija i dužina nožica nisu dovoljne za pouzdano određivanje svih boja.

  1. Isključi USB. Poveži logički kanal R preko 220 Ω na GPIO25, G preko drugog 220 Ω na GPIO26, a B preko trećeg 220 Ω na GPIO33.
  2. Za zajedničku katodu poveži zajednički izvod sa GND i ostavi #define COMMON_ANODE false.
  3. Za zajedničku anodu izaberi drugu šemu: zajednički izvod poveži sa 3V3 i promijeni postavku u #define COMMON_ANODE true. Primijeni samo varijantu koja odgovara tvojoj diodi.
  4. Krajeve potenciometra poveži na 3V3 i GND, a klizač na GPIO34.
  5. Taster poveži između GPIO27 i GND. Kod četvoronožnog tastera izaberi priključke koji se spajaju tek pritiskom; neki parovi su već interno spojeni.
  6. Provjeri odvojene redove eksperimentalne ploče, tri otpornika i zajedničku masu. Tek tada priključi USB.

Priprema Arduino okruženja

Koristi Arduino IDE 2.x, esp32 by Espressif Systems 3.3.12 i ploču ESP32 Dev Module. Preuzmi Arduino primjer (.zip) i raspakuj ga. Izaberi port, otvori rgb_mixer.ino iz foldera rgb_mixer, provjeri postavku COMMON_ANODE, pa pokreni Verify i Upload. Serial Monitor postavi na 115200 baud. Dodatne biblioteke nisu potrebne. Instalacija paketa

Kompletan program

rgb_mixer.ino Arduino / C++
Preuzmi .ino

#include <Arduino.h>

// Set true ONLY for a common-anode RGB LED wired with its common lead to 3V3.
#ifndef COMMON_ANODE
#define COMMON_ANODE false
#endif

const uint8_t RGB_PINS[3] = {25, 26, 33};
const char* CHANNEL_NAMES[3] = {"R", "G", "B"};
constexpr uint8_t POT_PIN = 34;
constexpr uint8_t BUTTON_PIN = 27;
constexpr uint32_t PWM_FREQUENCY_HZ = 5000;
constexpr uint8_t PWM_RESOLUTION_BITS = 8;
constexpr uint32_t DEBOUNCE_MS = 30;
constexpr uint32_t SAMPLE_INTERVAL_MS = 20;
constexpr uint32_t REPORT_INTERVAL_MS = 200;

uint8_t brightness[3] = {0, 0, 0};
uint8_t selectedChannel = 0;
bool pwmReady = true;
int lastReading = HIGH;
int stableButtonState = HIGH;
uint32_t lastChangeMs = 0;
uint32_t lastSampleMs = 0;
uint32_t lastReportMs = 0;

void writeColors() {
  for (uint8_t channel = 0; channel < 3; channel++) {
    const uint8_t duty = COMMON_ANODE ? 255 - brightness[channel] : brightness[channel];
    ledcWrite(RGB_PINS[channel], duty);
  }
}

void sampleSelectedChannel() {
  const uint16_t rawValue = analogRead(POT_PIN);
  brightness[selectedChannel] = (static_cast<uint32_t>(rawValue) * 255U) / 4095U;
  writeColors();
}

void setup() {
  Serial.begin(115200);
  pinMode(BUTTON_PIN, INPUT_PULLUP);
  pinMode(POT_PIN, INPUT);
  analogReadResolution(12);
  analogSetPinAttenuation(POT_PIN, ADC_11db);

  for (uint8_t channel = 0; channel < 3; channel++) {
    pinMode(RGB_PINS[channel], OUTPUT);
    digitalWrite(RGB_PINS[channel], COMMON_ANODE ? HIGH : LOW);
    if (!ledcAttach(RGB_PINS[channel], PWM_FREQUENCY_HZ, PWM_RESOLUTION_BITS)) {
      pwmReady = false;
    }
  }

  if (!pwmReady) {
    // Leave every channel off if any PWM channel could not be configured.
    for (uint8_t channel = 0; channel < 3; channel++) {
      ledcDetach(RGB_PINS[channel]);
      pinMode(RGB_PINS[channel], OUTPUT);
      digitalWrite(RGB_PINS[channel], COMMON_ANODE ? HIGH : LOW);
    }
    Serial.println("ERROR: RGB PWM setup failed. Check the board and ESP32 core.");
    return;
  }

  writeColors();
  lastReading = digitalRead(BUTTON_PIN);
  stableButtonState = lastReading;
  lastChangeMs = millis();
  lastSampleMs = lastChangeMs;
  lastReportMs = lastChangeMs;
  Serial.println("WB Maker Bridge - Button selects R/G/B; potentiometer sets its value.");
  Serial.println("A newly selected channel immediately uses the current potentiometer position.");
}

void loop() {
  if (!pwmReady) {
    delay(100);
    return;
  }

  const uint32_t now = millis();
  const int reading = digitalRead(BUTTON_PIN);

  if (reading != lastReading) {
    lastReading = reading;
    lastChangeMs = now;
  }

  if (now - lastChangeMs >= DEBOUNCE_MS && reading != stableButtonState) {
    stableButtonState = reading;
    if (stableButtonState == LOW) {
      selectedChannel = (selectedChannel + 1) % 3;
      sampleSelectedChannel();
      lastSampleMs = now;
    }
  }

  if (now - lastSampleMs >= SAMPLE_INTERVAL_MS) {
    lastSampleMs = now;
    sampleSelectedChannel();
  }

  if (now - lastReportMs >= REPORT_INTERVAL_MS) {
    lastReportMs = now;
    Serial.print("Selected: ");
    Serial.print(CHANNEL_NAMES[selectedChannel]);
    Serial.print(" | R: ");
    Serial.print(brightness[0]);
    Serial.print(" | G: ");
    Serial.print(brightness[1]);
    Serial.print(" | B: ");
    Serial.println(brightness[2]);
  }
}

Preuzeti program odgovara prikazanom kodu. Raspored izvoda na konkretnoj RGB diodi potvrdi prije fizičkog isprobavanja.

Kako čitati program

Niz RGB_PINS povezuje boje sa pinovima, a brightness čuva tri intenziteta. Promjenljiva selectedChannel bira koji element niza mijenja potenciometar. Izraz (selectedChannel + 1) % 3 daje redoslijed R → G → B → R.

INPUT_PULLUP omogućava da otpušten taster daje HIGH, a pritisnut LOW. Program prihvata promjenu poslije 30 ms stabilnosti i mijenja kanal samo pri novom pritisku. Držanje tastera ne ponavlja izbor. Espressif: GPIO

Potenciometar se očitava približno svakih 20 ms; 12-bitni broj skalira se u 0–255. Na krajevima hoda moguće je zasićenje ADC-a kao u kursu 05. PWM je 5000 Hz i 8 bita. ledcAttach() i ledcWrite() koriste GPIO pinove prema API-ju 3.x. Espressif: LEDC

Važno ponašanje: nakon prihvaćenog pritiska novi kanal odmah preuzima trenutni položaj potenciometra. Njegova stara vrijednost se zamjenjuje; druga dva kanala ostaju ista. Funkcija writeColors() pretvara sačuvane intenzitete u izlaze, uključujući obrtanje za zajedničku anodu. Ispis na svakih približno 200 ms prikazuje Selected, R, G i B.

Pokretanje i očekivani rezultat

Prije resetovanja postavi potenciometar na minimum. Početne vrijednosti su sve nula, izabran je R, a prvo očitavanje poslije približno 20 ms postavlja njegov intenzitet. Ako potenciometar nije na minimumu, crveni kanal će zato odmah zasvijetliti.

Pojačaj R do maksimuma. Pritisni taster jednom: G odmah preuzima isti položaj i miješa se sa R. Zatim smanji G i posmatraj kako R ostaje sačuvan. Pritisni ponovo za B. Drži taster dvije sekunde i provjeri da se desio samo jedan izbor, pa ga otpusti prije narednog pritiska.

Ciljni intenziteti R/G/BOčekivani doprinos svjetlu
255 / 0 / 0Crveni
0 / 255 / 0Zeleni
0 / 0 / 255Plavi
255 / 255 / 0Žućkasti
255 / 0 / 255Magenta
0 / 255 / 255Cijan

Tabela su zadate kombinacije za eksperiment; ne znači da jedan položaj potenciometra istovremeno postavlja sva tri kanala.

Najčešći problemi

ProblemProvjera i korekcija
Izabrani R svijetli plavoPonovo identifikuj izvode boja i uskladi R/G/B spojeve.
Svjetlina radi obrnuto ili se boje ne gaseUskladi tip diode, zajednički izvod i COMMON_ANODE.
Boja skoči nakon pritiskaTo je predviđeno: novi kanal odmah preuzima trenutni položaj potenciometra.
Taster ne bira kanalProvjeri prekidani par kontakata, GPIO27 i GND.
Jedna boja je veoma slabaProvjeri taj otpornik i spoj; kanali ne moraju imati isti intenzitet pri istom broju.
Greška oko LEDC pozivaProvjeri ploču i ESP32 paket verzije 3.3.12.

Samostalni izazov

Napravi magentu polazeći od resetovanja, uz R i B na maksimumu i G na nuli. Zapiši redoslijed pritisaka i okretanja. Zatim napravi cijan i objasni šta se desilo pri prelasku sa G na B.

Kratka provjera znanja

  1. Zašto jedan otpornik u zajedničkom izvodu nije naš predviđeni spoj?
  2. Šta se mijenja u povezivanju i programu za zajedničku anodu?
  3. Da li vrijednost izabranog kanala ostaje ista kada se ponovo vratiš na njega?

Smjernice za odgovore i rješenje

Zasebni otpornici ograničavaju struju svakog kanala. Za zajedničku anodu zajednički izvod ide na 3V3, a COMMON_ANODE na true; intenzitet 255 tada se pretvara u električni duty 0. Ponovo izabrani kanal odmah preuzima potenciometar.

Za magentu resetuj uređaj sa potenciometrom na maksimumu: R postaje 255. Izaberi G, zatim smanji potenciometar na nulu. Izaberi B i podigni ga na maksimum. Za cijan resetuj sa minimumom: R ostaje 0. Izaberi G i pojačaj ga; izaberi B dok je potenciometar još na maksimumu. B odmah preuzima visoku vrijednost, a G je zadržava. Rezultate potvrdi u Serial Monitoru.

Preuzimanja

Preuzmi Arduino primjer i šemu odgovarajuću svojoj diodi. Provjeru kompajliranja i probu na stvarnoj ploči evidentiraj kao dva odvojena rezultata.

Primarni izvori