Udělal jsem experimentální prototyp světelného meče s WS2812 a Arduinem. Obrázek je s Arduinem Mini Pro, ale daleko pohodlnější na ladění je Arduino Nano, které jsem použil. Zapojení je velmi jednoduché. Tlačítko na pinu 3 je na volbu efektů. Gyroskop/akcelerometr MPU6050 je laciná krásná hračka a zajišťuje rozsvícení "meče" při pohybu.
Kód: Vybrat vše
// Version 1.08
// Tested with Arduino IDE v.1.8.19 and Arduino core v.1.8.6
// 11/2022 Pavel Janko, www.fancon.cz
// Nezbytne knihovny
#include <Adafruit_NeoPixel.h> // version 1.10.6
#include <Adafruit_MPU6050.h> // version 2.2.4
#include <Adafruit_Sensor.h> // Adafruit Unified Sensor version 1.1.6
#include <Wire.h>
const uint8_t WS2812_PIN = 17; // Vystupni pin Arduina pro data LED pasku WS2812
const uint8_t ButtonPin = 3; // Vstupni pin Arduina pro tlacitko
const uint8_t StringPixelsNum = 29; // Pocet pouzitých LED v pasku WS2812
const int TasPeriod = 8; // Rychlost rozsviceni jednotlivych LED mece v milisekundach
const int UntasPeriodConst = 15; // Rychlost zhaseni jednotlivych LED mece v milisekundach
const int ShotPeriod = 20; // Rychlost beziciho kratkeho paprsku
int UntasPeriod = UntasPeriodConst;
//********************************************************************************
unsigned long TasTime;
unsigned long UntasTime;
unsigned long ShotTime;
bool tas = false;
bool untas = false;
int16_t Counter01 = 0;
uint8_t Func = 2;
uint8_t Rcolor = 128;
uint8_t Gcolor = 0;
uint8_t Bcolor = 0;
// data pro vytvareni duhy
const byte ForFill[] PROGMEM = {128, 0, 0, 120, 0, 0, 110, 10, 0, 100, 20, 0, 90, 30, 0, 80, 40, 0, 70, 50, 0,
60, 60, 0, 50, 70, 0, 40, 80, 0, 30, 90, 0, 20, 100, 0, 10, 110, 0, 0, 120, 0,
0, 128, 0, 0, 120, 0, 0, 110, 10, 0, 100, 20, 0, 90, 30, 0, 80, 40, 0, 70, 50, 0, 60, 60,
0, 50, 70, 0, 40, 80, 0, 30, 90, 00, 20, 100, 0, 10, 110, 0, 0, 120, 0, 0, 128
};
// inicializace procesu gyroskopu a LED pasku
Adafruit_MPU6050 mpu;
Adafruit_NeoPixel pixels(StringPixelsNum, WS2812_PIN);
void setup() {
//Serial.begin(115200);
//Nastav I2C na 400 000Hz
Wire.setClock(400000);
// start procesu gyroskopu a LED pasku
mpu.begin();
pixels.begin();
//Nastavení V/V pinu
pinMode(ButtonPin, INPUT_PULLUP);
pinMode(WS2812_PIN, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT);
// zablikani LED na Arduinu na zacatku programu
for (int i = 0; i < 10; i++) {
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
delay(50);
}
//****************************************************
// Blokace svitu LED pri kompilaci
// sviti jen slabe cervena
// pixels.clear();
// pixels.setPixelColor(0, pixels.Color(8, 0, 0));
// pixels.show();
// while (digitalRead(ButtonPin)) {}
//****************************************************
// rozsvícení prvni cervene LED v pasku
pixels.clear();
pixels.setPixelColor(0, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.show();
// Nastavení rozsahu MPU6050, viz zalozka MPU6050 deklarace
mpu.setAccelerometerRange(MPU6050_RANGE_2_G);
mpu.setGyroRange(MPU6050_RANGE_250_DEG);
mpu.setFilterBandwidth(MPU6050_BAND_5_HZ);
}
void loop() {
sensors_event_t a, g, temp;
mpu.getEvent(&a, &g, &temp);
// Kontrola tlacitka a prepinani barev a funkci
if (!digitalRead(ButtonPin)) {
delay(50);
if (!digitalRead(ButtonPin)) {
Counter01 = 0;
// zakaz rozsviceni mece
tas = false;
// nastaveni barvy mece
Func++;
if (Func > 9)Func = 1;
if (Func == 1) {
Rcolor = 128;
Gcolor = 0;
Bcolor = 0;
}
if (Func == 2) {
Rcolor = 0;
Gcolor = 128;
Bcolor = 0;
}
if (Func == 3) {
Rcolor = 0;
Gcolor = 0;
Bcolor = 128;
}
if (Func == 4) {
Rcolor = 64;
Gcolor = 64;
Bcolor = 0;
}
if (Func == 5) {
Rcolor = 64;
Gcolor = 0;
Bcolor = 64;
}
if (Func == 6) {
Rcolor = 0;
Gcolor = 64;
Bcolor = 64;
}
// duha
if (Func == 7) {
Rcolor = 32;
Gcolor = 32;
Bcolor = 32;
}
if (Func == 8) {
Rcolor = 64;
Gcolor = 64;
Bcolor = 0;
}
if (Func == 9) {
Rcolor = 8;
Gcolor = 8;
Bcolor = 8;
}
// rozsvit jednu LED dane barvy pro informaci o zvolene funkci
while (!digitalRead(ButtonPin)) {}
pixels.clear();
pixels.setPixelColor(0, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.show();
}
}
if (Func > 0 && Func < 7) {
// Cteni dvou os gyroskopu pro aktivaci rozsvícení LED
if ((abs(g.gyro.x) > 1.0 || abs(g.gyro.z) > 1.0) && !tas) {
tas = true; // povol rozsviceni LED
untas = false; // blokuj zhaseni LED
}
// Rozsvit mec
if (((millis() - TasPeriod) > TasTime) && tas) {
TasTime = millis();
if (Counter01 < (StringPixelsNum)) {
pixels.setPixelColor(Counter01, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.show();
Counter01++;
}
// když jsou vsechny LED rozsviceny
if (Counter01 >= StringPixelsNum) {
tas = false; // blokuj rozsviceni LED
untas = true;// povol zhaseni LED
UntasPeriod = 250; // nastav prodlevu pred zhasenim LED
UntasTime = millis();
}
}
// zhasni mec
if (((millis() - UntasPeriod) > UntasTime) && untas) {
UntasPeriod = UntasPeriodConst;
UntasTime = millis();
Counter01--;
if (Counter01 >= 0) {
pixels.setPixelColor(Counter01, pixels.Color(0, 0, 0));
pixels.show();
}
// když je vše zhasnuto, zakaz zhaseni
if (Counter01 <= 0) {
untas = false; // blokuj zhaseni LED
Counter01 = 0;
}
}
}
if (Func == 7) {
// Cteni dvou os gyroskopu pro aktivaci rozsvícení LED
if ((abs(g.gyro.x) > 1.0 || abs(g.gyro.z) > 1.0) && !tas) {
tas = true; // povol rozsviceni LED
untas = false; // blokuj zhaseni LED
}
// Rozsvit duhu
if (((millis() - TasPeriod) > TasTime) && tas) {
TasTime = millis();
if (Counter01 < (StringPixelsNum)) {
pixels.setPixelColor(Counter01, pixels.Color(pgm_read_byte_near(ForFill + Counter01 * 3),
pgm_read_byte_near(ForFill + Counter01 * 3 + 1),
pgm_read_byte_near(ForFill + Counter01 * 3 + 2)));
pixels.show();
Counter01++;
}
// když jsou vsechny LED rozsviceny
if (Counter01 >= StringPixelsNum) {
tas = false; // blokuj rozsviceni LED
untas = true;// povol zhaseni LED
UntasPeriod = 250; // nastav prodlevu pred zhasenim LED
UntasTime = millis();
}
}
// zhasni duhu
if (((millis() - UntasPeriod) > UntasTime) && untas) {
UntasPeriod = UntasPeriodConst;
UntasTime = millis();
Counter01--;
if (Counter01 >= 0) {
pixels.setPixelColor(Counter01, pixels.Color(0, 0, 0));
pixels.show();
}
// když je vše zhasnuto, zakaz zhaseni
if (Counter01 <= 0) {
untas = false; // blokuj zhaseni LED
Counter01 = 0;
}
}
}
// bezici paprsek
if (Func == 8) {
if (((millis() - ShotPeriod) > ShotTime)) {
ShotTime = millis();
if (Counter01 < (StringPixelsNum)) {
pixels.clear();
pixels.setPixelColor(Counter01, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.setPixelColor(Counter01 + 1, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.setPixelColor(Counter01 + 2, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.setPixelColor(Counter01 + 3, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.setPixelColor(Counter01 + 4, pixels.Color(Rcolor, Gcolor, Bcolor));
pixels.setPixelColor(Counter01 + 5, pixels.Color(0, 0, 0));
pixels.setPixelColor(Counter01 + 6, pixels.Color(0, 0, 0));
pixels.setPixelColor(Counter01 + 7, pixels.Color(0, 0, 0));
pixels.setPixelColor(Counter01 + 8, pixels.Color(0, 0, 0));
pixels.setPixelColor(Counter01 + 9, pixels.Color(0, 0, 0));
pixels.show();
Counter01++;
}
else Counter01 = 0;
}
}
// bezici duha
if (Func == 9) {
if (((millis() - ShotPeriod) > ShotTime)) {
ShotTime = millis();
Counter01++;
if (Counter01 >= StringPixelsNum )Counter01 = 0;
for (uint8_t i = 0; i < StringPixelsNum; i++) {
pixels.setPixelColor(i, pixels.Color(pgm_read_byte_near(ForFill + Counter01 * 3),
pgm_read_byte_near(ForFill + Counter01 * 3 + 1),
pgm_read_byte_near(ForFill + Counter01 * 3 + 2)));
Counter01++;
if (Counter01 >= StringPixelsNum )Counter01 = 0;
}
pixels.show();
}
}
}
Přikládám také orientační tabulku spotřeby.