Aquesta guia desglossa dos programes fonamentals d'Arduino. El primer t'ensenyarà a interactuar amb botons i controlar la intensitat d'un LED. El segon et mostrarà com crear un espectre de colors complet amb un LED RGB mitjançant matemàtiques sorprenentment senzilles i bucles.
Aquest codi et permet augmentar o disminuir la intensitat d'un LED prement dos botons diferents.
// Pins del circuit
const int ledPin = 9; // Pin PWM on està connectat el LED
const int upButton = 2; // Botó per pujar la brillantor
const int downButton = 3; // Botó per baixar la brillantor
// Variables principals
int brightness = 0; // Valor actual de brillantor del LED (0-255)
const int step = 17; // Quantitat que canvia la brillantor per cada clic
// Variables per controlar l'estat anterior dels botons
// Això és necessari per detectar **canvis d'estat** i fer un pas per clic
bool lastUpState = HIGH; // Estat anterior del botó d'augment
bool lastDownState = HIGH; // Estat anterior del botó de decrement
void setup() {
pinMode(ledPin, OUTPUT); // Configura el pin del LED com a sortida
pinMode(upButton, INPUT_PULLUP); // Configura el botó d'augment amb resistència pull-up interna
pinMode(downButton, INPUT_PULLUP);// Configura el botó de decrement amb resistència pull-up interna
// Recorda: INPUT_PULLUP fa que el pin llegeixi HIGH quan el botó no està premut
}
void loop() {
// Llegir l'estat actual dels botons
bool upState = digitalRead(upButton); // HIGH si no premut, LOW si premut
bool downState = digitalRead(downButton);
// --- Detectar front descendente (clic) del botó d'augment ---
// Un “front descendente” és quan el botó passa de HIGH a LOW
// Això garanteix que només es compti un pas per clic, independent del temps que el deixis premut
if (lastUpState == HIGH && upState == LOW) {
brightness += step; // Augmenta la brillantor
if (brightness > 255) // Comprova que no sobrepassi el màxim PWM
brightness = 255;
}
// --- Detectar front descendente del botó de decrement ---
if (lastDownState == HIGH && downState == LOW) {
brightness -= step; // Redueix la brillantor
if (brightness < 0) // Comprova que no sigui inferior a 0
brightness = 0;
}
// Escriure el valor de brillantor al LED
// analogWrite accepta valors de 0 (apagat) a 255 (màxim)
analogWrite(ledPin, brightness);
// Actualitzar els estats anteriors amb els estats actuals
// Això és imprescindible per detectar correctament el proper clic
lastUpState = upState;
lastDownState = downState;
// Petit delay per debounce senzill (evita que el botó “repique” i compti més d'un clic)
delay(20); // 20 ms és suficient per la majoria de botons mecànics
}
const int): Fem servir const (constant) perquè els pins no canviaran mai durant el programa. El LED està al pin 9 perquè aquest pin té un símbol ~ a la placa, el que vol dir que suporta PWM (Pulse Width Modulation - una manera ràpida de fer parpellejar el LED per enganyar l'ull i que sembli més o menys brillant).brightness, step): brightness guardarà la llum actual (comença en 0, que és apagat, i pot arribar fins a 255). step defineix quant saltarem: de 25 en 25 per cada clic.setup(): Aquí configurem els pins.
OUTPUT) perquè hi enviarem energia.INPUT_PULLUP). Aquest és un concepte molt poderós! Això activa una resistència interna invisible de l'Arduino. Fa que el pin doni una senyal ALTA (HIGH) quan no es toca, i quan premem el botó (que està connectat a terra/GND), la senyal baixa a BAIXA (LOW). Per això més endavant busquem el LOW.loop(): Aquest és el cor que s'executa contínuament.
digitalRead() per veure com estan els botons. Si llegeix LOW (botó apretat), entrem dins de la condició if.if (brightness > 255) brightness = 255; impedeix que passem del límit. El mateix amb el 0.delay(200)): Els botons físics reboten elèctricament quan els prems i poden enviar 10 senyals en un milisegon. Posar una petita pausa ("debounce" o antirobots) de 200ms assegura que cada pulsació compta només com una vegada.analogWrite): Al final del bucle, enviem el valor de brillantor calculat al LED per encendre'l o atenuar-lo.Un LED RGB té tres petits LEDs a l'interior: un vermell (Red), un verd (Green) i un blau (Blue). Aquest codi els barreja per crear tot l'espectre de colors girant contínuament.
// Pins RGB (PWM)
const int redPin = 9;
const int greenPin = 10;
const int bluePin = 11;
void setup() {
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
pinMode(bluePin, OUTPUT);
}
void loop() {
for (int hue = 0; hue < 360; hue++) {
int r, g, b;
hsvToRgb(hue, 1.0, 1.0, r, g, b);
setColor(r, g, b);
delay(20);
}
}
// ---------- FUNCIONS ----------
void setColor(int r, int g, int b) {
analogWrite(redPin, r);
analogWrite(greenPin, g);
analogWrite(bluePin, b);
}
void hsvToRgb(float h, float s, float v, int &r, int &g, int &b) {
float c = v * s;
float x = c * (1 - abs(fmod(h / 60.0, 2) - 1));
float m = v - c;
float r1, g1, b1;
if (h < 60) {
r1 = c; g1 = x; b1 = 0;
} else if (h < 120) {
r1 = x; g1 = c; b1 = 0;
} else if (h < 180) {
r1 = 0; g1 = c; b1 = x;
} else if (h < 240) {
r1 = 0; g1 = x; b1 = c;
} else if (h < 300) {
r1 = x; g1 = 0; b1 = c;
} else {
r1 = c; g1 = 0; b1 = x;
}
r = (r1 + m) * 255;
g = (g1 + m) * 255;
b = (b1 + m) * 255;
}
const int): Com pots observar, els pins 9, 10 i 11 tenen capacitats PWM. Els declarem separadament i en el setup() els configurem tots tres com a OUTPUT.for): Dins del `loop()`, hi ha un bucle `for`. Pensa en la roda de colors com en un cercle de 360 graus.
setColor: Les funcions fan que el codi sigui net. En lloc d'escriure els tres `analogWrite` dins del `loop()`, hem creat `setColor`. Quan li passes els 3 valors (vermell, verd, blau), ella mateixa envia l'energia correcta a cada pin.hsvToRgb:
int &r, int &g, int &b a la declaració de la funció, aquest símbol & significa que la funció no està retornant un valor normal, sinó que està modificant directament les caixes de memòria de les variables r, g i b que hem creat prèviament dins del `loop()`. És una drecera excel·lent quan una funció ha de retornar més d'una resposta alhora.El model HSV (Hue, Saturation, Value) és una manera de descriure els colors molt més propera a com els entenem els humans que no pas barrejant percentatges de Vermell, Verd i Blau (RGB).
Així és com la nostra funció hsvToRgb converteix aquests valors fàcils d'entendre als valors elèctrics (0-255) que necessita l'Arduino:
c = v * s):
Això calcula la intensitat real del color base. Si la brillantor (v) o la saturació (s) són baixes, el Croma serà baix.
x):
float x = c * (1 - abs(fmod(h / 60.0, 2) - 1));c) i un color secundari que va pujant i baixant per crear les transicions (com passar del vermell al groc). Aquesta fórmula matemàtica (usant fmod per al residu de la divisió) crea una ona en forma de triangle que fa pujar i baixar suaument aquest segon color.
m = v - c):
Això calcula la quantitat de llum blanca/grisa que cal afegir a tots tres canals (R, G, B) per aconseguir la brillantor total (V) i la saturació (S) desitjades.
if / else if:
Aquí mirem en quin "tros" de 60 graus del cercle ens trobem.
h < 60 (entre Vermell i Groc): El vermell és el màxim (c), el verd va pujant (x) i el blau està apagat (0).h < 120 (entre Groc i Verd): El verd és el màxim (c), el vermell va baixant (x) i el blau apagat.r = (r1 + m) * 255;analogWrite() de l'Arduino necessita un número sencer entre 0 (apagat) i 255 (màxima potència).