Assalamualaikum, jumpa lagi di tutorial triyonos.com. Alhamdulillah saya telah kembali menyelesaikan tutorial pemrograman lainnya mengenai Arduino dan LED Strip WS2812. Pada tutorial kali ini saya akan membuat alat simulasi lampu sein kanan, sein kiri dan lampu stop pada sepeda motor. Ketiga lampu tersebut dikendalikan melalui tiga buah push button yang dihubungkan ke pin-pin interrupt di Arduino Uno.

Di papan microcontroller Arduino Uno, tersedia 20 pin untuk Pin Change Interrupts, dan dibagi menjadi tiga port yaitu Port B, Port C dan Port D seperti pada gambar berikut:

pin change interrupt arduino uno

Pada pembahasan di tutorial ini, saya akan menggunakan pin D2, D3 dan D4 yang ada di port D sebagai pin-pin interrupt.

pin change interrupt arduino uno

Sedangkan tabel untuk Pin Change Mask-nya adalah sebagai berikut:

pin change interrupt arduino uno

Sehingga untuk meregistrasikan Pin D2, D3 dan D4 sebagai pin-pin interrupt maka di bagian void Setup() pada program .ino-nya adalah sebagai berikut:

pin change interrupt arduino uno

Pada alat simulasi lampu sein ini, pin D2 dihubungkan dengan button sein kiri, pin D3 dihubungkan dengan button sein kanan dan pin D4 dihubungkan dengan button stop.

Cara kerja alat simulasi ini adalah sebagai berikut:

  • Jika button sein kiri ditekan sekali maka lampu LED Kuning 1 akan menyala blinking sekaligus animasi pattern1 LED Strip WS2812 akan running, jika ditekan sekali lagi maka lampu LED Kuning 1 akan mati dan animasi LED Strip akan mati juga.
  • Jika button sein kanan ditekan sekali maka lampu LED Kuning 2 akan menyala blinking sekaligus animasi pattern2 LED Strip WS2812 akan running, jika ditekan sekali lagi maka lampu LED Kuning 2 akan mati dan animasi LED Strip akan mati juga.
  • Jika button stop ditekan sekali maka lampu LED Merah akan ON sekaligus animasi pattern3 LED Strip WS2812 akan running, jika ditekan sekali lagi maka lampu LED Merah akan OFF dan animasi LED Strip akan mati juga.

Terdapat 3 pattern animasi dasar yang akan digunakan pada tutorial ini, yaitu:

  1. nyala mati lampu LED strip dari ujung ke pangkal (ke arah kiri)
  2. nyala mati lampu LED strip dari pangkal ke ujung (ke arah kanan)
  3. fade in - fade out LED strip

simulasi lampu sein motor

1. Bill of Materials

1. Arduino Uno

arduino uno

2. Kabel power Arduino

kabel data micro usb

3. LED Strip WS2812 5V (16 leds)

ws2812 led strip 5volt

4. Breadboard

Breadboard

5. Kabel Jumper Male to Male

kabel jumper male to male

6. Resistor 330 Ohm (3 pcs)

resistor 330 ohm

7. Push Button (3 pcs)

push button

8. Lampu LED (3 pcs)

lampu led

2. Wiring Diagrams

Wiring Diagrams

3. Assembling

Button, resistor, LED dan kabel jumper untuk grounding.

assembling button resistor led

Kabel jumper yang akan terhubung ke pin Arduino Uno.

assembling button resistor led

Kabel jumper ke pin Arduino Uno 5V, GND, D2, D3, D4, D11, D12 dan D13.

assembling button resistor led

LED Strip WS2812 terhubung ke 5V, GND dan pin D8.

assembling WS2812 led strip

4. Mainkan Kodingannya

  • Colokkan Arduino ke PC atau Laptop manage library

  • Buka Arduino IDE dan install library FastLED

    Untuk menginstal library FastLED bisa dilakukan melalui Library Manager di Arduino IDE dengan mengklik Tools Manage Libaries ...

    Di tutorial ini saya menggunakan library FastLED by Daniel Garcia Versi 3.3.2

    manage library

  • Copy Paste code pin_chg_interrupt_ws2812.ino berikut:
    /*
      Multiple Pin Change Interrupt Demo
      pin_chg_interrupt_ws2812.ino
      Demonstrates Pin Change Interrupts with three pins on same port
      Inputs on D2, D3 & D4
      LEDs on D11, D12 and D13
      WS2812 LED Strip (16 leds) on D8
    
      References:
      - Using Arduino Interrupts – Hardware, Pin Change and Timer
        https://dronebotworkshop.com/interrupts/
      - Controlling WS2812B RGB LEDs
        https://akuzechie.blogspot.com/2021/03/controlling-ws2812b-rgb-leds.html
      - Blink Without Delay
        https://www.arduino.cc/en/Tutorial/BuiltInExamples/BlinkWithoutDelay
    */
    
    #include "FastLED.h"
    #define NUM_LEDS 16
    CRGB leds[NUM_LEDS];
    #define PIN 8
    
    boolean exitFunction;
    
    // LEDs and switchs
    const byte ledPin1 = 11;
    const byte ledPin2 = 12;
    const byte ledPin3 = 13;
    
    const byte buttonPin1 = 2;
    const byte buttonPin2 = 3;
    const byte buttonPin3 = 4;
    
    // Booleans for input states
    volatile bool D2_state = LOW;
    volatile bool D3_state = LOW;
    volatile bool D4_state = LOW;
    
    int ledState = LOW;             // ledState used to set the LED
    
    unsigned long previousMillis = 0;        // will store last time LED was updated
    const long interval = 300;           // interval at which to blink (milliseconds)
    
    // delay for button press
    unsigned long delay_press = 400; // in milliseconds
    unsigned long delay_press_last = 0;
    
    void setup() {
      Serial.begin(9600);
      exitFunction = false;
    
      // Set LEDs as outputs
      pinMode(ledPin1, OUTPUT);
      pinMode(ledPin2, OUTPUT);
      pinMode(ledPin3, OUTPUT);
    
      // Set switches as inputs with pullups
      pinMode(buttonPin1, INPUT_PULLUP);
      pinMode(buttonPin2, INPUT_PULLUP);
      pinMode(buttonPin3, INPUT_PULLUP);
    
      FastLED.addLeds<WS2812, PIN, GRB>(leds, NUM_LEDS).setCorrection( TypicalLEDStrip );
    
      // Enable PCIE2 Bit3 = 1 (Port D)
      PCICR |= B00000100;
      // Enable PCINT18, PCINT19, PCINT20 (Pins D2 , D3 , D4)
      PCMSK2 |= B00011100;
      //             \\\\\___PIN D0
      //              \\\\
      //               \\\\___PIN D1
      //                \\\
      //                 \\\___PIN D2 (Enable)
      //                  \\
      //                   \\___PIN D3 (Enable)
      //                    \
      //                     \___PIN D4 (Enable)
    }
    
    void loop() {
      exitFunction = false;
      for (int i=0; i<NUM_LEDS; i++) {
        leds[i] = CRGB::Black;
        FastLED.show();
      }
    
      if (D2_state == HIGH) {
        pattern1();
      } 
    
      if (D3_state == HIGH) {
        pattern2();
      }
    
      if (D4_state == HIGH) {
        pattern3();
      }
    }
    
    void pattern1() {
      while(1)
      {
        if (millis() - previousMillis >= interval) {
          previousMillis = millis();
    
          // if the LED is off turn it on and vice-versa:
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
      
          // set the LED with the ledState of the variable:
          digitalWrite(ledPin1, ledState);
        }
    
        
        for (int j=1; j<=2; j++) {
          for (int i=NUM_LEDS-1; i>=0; i--) {
            if (exitFunction == true) return;
            if (j == 1) {
              leds[i] = CRGB::Orange; delay(40);
              FastLED.show();
            }
            if (j == 2) {
              leds[i] = CRGB::Black; delay(20);
              FastLED.show();
            }
          }
        }
    
      } // end while(1)
    }
    
    void pattern2() {
      while(1)
      {
        if (millis() - previousMillis >= interval) {
          previousMillis = millis();
    
          // if the LED is off turn it on and vice-versa:
          if (ledState == LOW) {
            ledState = HIGH;
          } else {
            ledState = LOW;
          }
      
          // set the LED with the ledState of the variable:
          digitalWrite(ledPin2, ledState);
        }
    
        
        for (int j=1; j<=2; j++) {
          for (int i=0; i<NUM_LEDS; i++) {
            if (exitFunction == true) return;
            if (j == 1) {
              leds[i] = CRGB::Orange; delay(40);
              FastLED.show();
            }
            if (j == 2) {
              leds[i] = CRGB::Black; delay(20);
              FastLED.show();
            }
          }
        }
        
      } // end while(1)
    }
    
    void pattern3() {
      while(1) {
        float r, g, b;
    
        // FADE IN
        for(int i = 0; i <= 255; i++) {
          if (exitFunction == true) return;
          r = (i/256.0)*255;
          g = (i/256.0)*0;
          b = (i/256.0)*0;
          fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
          FastLED.show();
          delay(2);
        }
      
        // FADE OUT
        for(int i = 255; i >= 0; i--) {
          if (exitFunction == true) return;
          r = (i/256.0)*255;
          g = (i/256.0)*0;
          b = (i/256.0)*0;
          fill_solid(leds, NUM_LEDS, CRGB(r, g, b));
          FastLED.show();
          delay(2);
        }
      }
    }
    
    ISR (PCINT2_vect)
    {
      // Port D Interrupt occured
    
      // prevent double execution at button keypress
      if( millis() - delay_press_last > delay_press ){
      
          // Check if this was D2 //////////////////////
          if (digitalRead(buttonPin1) == LOW) {
            digitalWrite(ledPin2, LOW);
            digitalWrite(ledPin3, LOW);
            
            //Pin D2 triggered the ISR on a Falling pulse
            D2_state = !D2_state;
            
            //Set LED 1 to state of D2_state boolean
            digitalWrite(ledPin1, D2_state);
          }
        
          if (D2_state == LOW) {
            exitFunction = true;
          } else {
            D3_state = LOW;
            D4_state = LOW;
          }
          //////////////////////////////////////////////
        
          
          // Check if this was D3 //////////////////////
          if (digitalRead(buttonPin2) == LOW) {
            digitalWrite(ledPin1, LOW);
            digitalWrite(ledPin3, LOW);
            
            //Pin D3 triggered the ISR on a Falling pulse
            D3_state = !D3_state;
            //Set LED 2 to state of D3_state boolean
            digitalWrite(ledPin2, D3_state);
          }
        
          if (D3_state == LOW) {
            exitFunction = true;
          } else {
            D2_state = LOW;
            D4_state = LOW;
          }
          //////////////////////////////////////////////
        
        
          // Check if this was D4 //////////////////////
          if (digitalRead(buttonPin3) == LOW) {
            digitalWrite(ledPin1, LOW);
            digitalWrite(ledPin2, LOW);
            
            //Pin D4 triggered the ISR on a Falling pulse
            D4_state = !D4_state;
            //Set LED 3 to state of D4_state boolean
            digitalWrite(ledPin3, D4_state);
          }
        
          if (D4_state == LOW) {
            exitFunction = true;
          } else {
            D2_state = LOW;
            D3_state = LOW;
          }
          //////////////////////////////////////////////
    
          delay_press_last = millis();
      }
    }
    
    					


Kalau ada pertanyaan silakan comment vidio ini di youtube ya, syaratnya harus subscribe terlebih dahulu 😃