Guia d'Aprenentatge: Programació Arduino Pas a Pas

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.

Projecte 1: Controlar la Brillantor d'un LED amb Botons

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
}
    

Explicació Pas a Pas


Projecte 2: Creant un Cicle de Colors en un LED RGB

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;
}
    

Explicació Pas a Pas

Aprofundint: Com funciona la màgia del HSV a RGB?

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).

Els tres components del HSV

Desglossant la funció matemàtica pas a pas

Així és com la nostra funció hsvToRgb converteix aquests valors fàcils d'entendre als valors elèctrics (0-255) que necessita l'Arduino:

  1. Calcular el Croma (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.
  2. Calcular el valor intermedi (x):
    float x = c * (1 - abs(fmod(h / 60.0, 2) - 1));
    Aquesta és la fórmula més complexa. El cercle cromàtic es divideix en 6 porcions de 60 graus. Mentre gires la roda, sempre hi ha un color principal (que estarà al màxim, igual a 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.
  3. Ajust de lluminositat (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.
  4. El gran bloc if / else if: Aquí mirem en quin "tros" de 60 graus del cercle ens trobem.
    • Si h < 60 (entre Vermell i Groc): El vermell és el màxim (c), el verd va pujant (x) i el blau està apagat (0).
    • Si h < 120 (entre Groc i Verd): El verd és el màxim (c), el vermell va baixant (x) i el blau apagat.
    • Això es repeteix cobrint tot l'espectre fins tornar al vermell.
  5. La conversió final a Arduino:
    r = (r1 + m) * 255;
    Finalment, agafem el color base calculat (r1, g1, b1), li sumem l'ajust de lluminositat (m), i ho multipliquem tot per 255. Per què? Perquè els nostres càlculs anaven de 0.0 a 1.0, però la funció analogWrite() de l'Arduino necessita un número sencer entre 0 (apagat) i 255 (màxima potència).