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:
Pada pembahasan di tutorial ini, saya akan menggunakan pin D2, D3 dan D4 yang ada di port D sebagai pin-pin interrupt.
Sedangkan tabel untuk Pin Change Mask-nya adalah sebagai berikut:
Sehingga untuk meregistrasikan Pin D2, D3 dan D4 sebagai pin-pin interrupt maka di bagian void Setup() pada program .ino-nya adalah sebagai berikut:
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:
- nyala mati lampu LED strip dari ujung ke pangkal (ke arah kiri)
- nyala mati lampu LED strip dari pangkal ke ujung (ke arah kanan)
- fade in - fade out LED strip
1. Bill of Materials
1. Arduino Uno
2. Kabel power Arduino
3. LED Strip WS2812 5V (16 leds)
4. Breadboard
5. Kabel Jumper Male to Male
6. Resistor 330 Ohm (3 pcs)
7. Push Button (3 pcs)
8. Lampu LED (3 pcs)
2. Wiring Diagrams
3. Assembling
Button, resistor, LED dan kabel jumper untuk grounding.
Kabel jumper yang akan terhubung ke pin Arduino Uno.
Kabel jumper ke pin Arduino Uno 5V, GND, D2, D3, D4, D11, D12 dan D13.
LED Strip WS2812 terhubung ke 5V, GND dan pin D8.
4. Mainkan Kodingannya
- Colokkan Arduino ke PC atau Laptop
-
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
-
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(); } }