Initial commit: D1 Mini Blinkin LED Driver Emulator for FTC
This commit is contained in:
commit
dca4c4cb26
12 changed files with 2155 additions and 0 deletions
89
.gitignore
vendored
Normal file
89
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
# PlatformIO
|
||||
.pio
|
||||
.pioenvs
|
||||
.piolibdeps
|
||||
.clang_complete
|
||||
.gcc-flags.json
|
||||
|
||||
# VSCode
|
||||
.vscode/*
|
||||
!.vscode/extensions.json
|
||||
.vscode/.browse.c_cpp.db*
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
|
||||
# IDE - IntelliJ
|
||||
.idea/
|
||||
*.iml
|
||||
*.iws
|
||||
*.ipr
|
||||
|
||||
# IDE - CLion
|
||||
cmake-build-*/
|
||||
|
||||
# OS generated files
|
||||
.DS_Store
|
||||
.DS_Store?
|
||||
._*
|
||||
.Spotlight-V100
|
||||
.Trashes
|
||||
ehthumbs.db
|
||||
Thumbs.db
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# Build artifacts
|
||||
*.bin
|
||||
*.elf
|
||||
*.hex
|
||||
*.map
|
||||
*.lst
|
||||
*.su
|
||||
*.o
|
||||
*.a
|
||||
*.lib
|
||||
*.ko
|
||||
*.so
|
||||
*.so.*
|
||||
*.dll
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
||||
|
||||
# Logs and databases
|
||||
*.log
|
||||
*.sql
|
||||
*.sqlite
|
||||
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.pyc
|
||||
|
||||
# Node
|
||||
node_modules/
|
||||
|
||||
# Archives
|
||||
*.7z
|
||||
*.dmg
|
||||
*.gz
|
||||
*.iso
|
||||
*.jar
|
||||
*.rar
|
||||
*.tar
|
||||
*.zip
|
||||
|
||||
# Backup files
|
||||
*.bak
|
||||
*.backup
|
||||
*.old
|
||||
*.orig
|
||||
*.tmp
|
||||
|
||||
# Project specific
|
||||
/build/
|
||||
/dist/
|
||||
/output/
|
||||
10
.vscode/extensions.json
vendored
Normal file
10
.vscode/extensions.json
vendored
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
// See http://go.microsoft.com/fwlink/?LinkId=827846
|
||||
// for the documentation about the extensions.json format
|
||||
"recommendations": [
|
||||
"platformio.platformio-ide"
|
||||
],
|
||||
"unwantedRecommendations": [
|
||||
"ms-vscode.cpptools-extension-pack"
|
||||
]
|
||||
}
|
||||
224
INSTALLATION_GUIDE.md
Normal file
224
INSTALLATION_GUIDE.md
Normal file
|
|
@ -0,0 +1,224 @@
|
|||
# Installation Guide - D1 Mini Blinkin Emulator
|
||||
|
||||
## Two Ways to Install
|
||||
|
||||
### Option 1: PlatformIO (Recommended for VS Code Users)
|
||||
|
||||
#### Step 1: Install PlatformIO
|
||||
1. Open VS Code
|
||||
2. Go to Extensions (Ctrl+Shift+X)
|
||||
3. Search for "PlatformIO IDE"
|
||||
4. Click Install
|
||||
5. Restart VS Code
|
||||
|
||||
#### Step 2: Open the Project
|
||||
1. File → Open Folder
|
||||
2. Select `KrakenKodersAllianceLights` folder
|
||||
3. PlatformIO will auto-detect the project
|
||||
|
||||
#### Step 3: Install Libraries
|
||||
The libraries should install automatically when you build. If not:
|
||||
|
||||
**Method A: Through PlatformIO Home**
|
||||
1. Click PlatformIO icon in sidebar
|
||||
2. Open "PIO Home" → Libraries
|
||||
3. Search for "Adafruit NeoPixel"
|
||||
4. Click "Add to Project"
|
||||
5. Select your project
|
||||
|
||||
**Method B: Manual Command**
|
||||
1. Open PlatformIO Terminal (bottom toolbar)
|
||||
2. Run: `pio lib install "Adafruit NeoPixel"`
|
||||
|
||||
#### Step 4: Configure Your Settings
|
||||
Edit `src/D1Mini_Blinkin_Ready.ino`:
|
||||
```cpp
|
||||
#define NUM_LEDS 60 // Your LED count
|
||||
#define BRIGHTNESS 100 // 0-255
|
||||
```
|
||||
|
||||
#### Step 5: Build and Upload
|
||||
1. Connect D1 Mini via USB
|
||||
2. Click checkmark (✓) to build
|
||||
3. Click arrow (→) to upload
|
||||
|
||||
### Option 2: Arduino IDE (Simpler for Beginners)
|
||||
|
||||
#### Step 1: Install Arduino IDE
|
||||
Download from: https://www.arduino.cc/en/software
|
||||
|
||||
#### Step 2: Add ESP8266 Board Support
|
||||
1. Open Arduino IDE
|
||||
2. File → Preferences
|
||||
3. In "Additional Board Manager URLs" add:
|
||||
```
|
||||
http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
```
|
||||
4. Click OK
|
||||
5. Tools → Board → Board Manager
|
||||
6. Search "ESP8266"
|
||||
7. Install "ESP8266 by ESP8266 Community"
|
||||
|
||||
#### Step 3: Install NeoPixel Library
|
||||
1. Tools → Manage Libraries
|
||||
2. Search "Adafruit NeoPixel"
|
||||
3. Click Install
|
||||
4. Also install any dependencies it asks for
|
||||
|
||||
#### Step 4: Open the Sketch
|
||||
1. File → Open
|
||||
2. Navigate to `D1Mini_Blinkin_Arduino.ino`
|
||||
|
||||
#### Step 5: Configure Board Settings
|
||||
Tools menu:
|
||||
- Board: "LOLIN(WEMOS) D1 R2 & mini"
|
||||
- Upload Speed: 921600
|
||||
- CPU Frequency: 80 MHz
|
||||
- Flash Size: 4MB (FS:2MB OTA:~1019KB)
|
||||
- Port: Select your COM port (appears when D1 Mini connected)
|
||||
|
||||
#### Step 6: Configure Your LEDs
|
||||
Edit these lines in the code:
|
||||
```cpp
|
||||
#define NUM_LEDS 60 // Your LED count
|
||||
#define BRIGHTNESS 100 // 0-255
|
||||
```
|
||||
|
||||
#### Step 7: Upload
|
||||
1. Connect D1 Mini via USB
|
||||
2. Click Upload button (→)
|
||||
3. Wait for "Done uploading"
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### PlatformIO Issues
|
||||
|
||||
**"Adafruit_NeoPixel.h not found"**
|
||||
- Ensure platformio.ini contains:
|
||||
```ini
|
||||
lib_deps =
|
||||
adafruit/Adafruit NeoPixel@^1.11.0
|
||||
```
|
||||
- Clean and rebuild: PlatformIO → Clean, then Build
|
||||
|
||||
**"Platform not installed"**
|
||||
- Terminal: `pio platform install espressif8266`
|
||||
|
||||
**Wrong COM Port**
|
||||
- Add to platformio.ini:
|
||||
```ini
|
||||
upload_port = COM3 ; Change to your port
|
||||
monitor_port = COM3
|
||||
```
|
||||
|
||||
### Arduino IDE Issues
|
||||
|
||||
**"Board not found"**
|
||||
- Ensure ESP8266 package is installed
|
||||
- Restart Arduino IDE
|
||||
- Select correct board from Tools → Board menu
|
||||
|
||||
**"Port not showing"**
|
||||
- Install CH340 drivers: https://sparks.gogo.co.nz/ch340.html
|
||||
- Try different USB cable (data cable, not charge-only)
|
||||
- Windows: Check Device Manager for COM port
|
||||
|
||||
**"Upload failed"**
|
||||
- Hold FLASH button on D1 Mini while uploading starts
|
||||
- Release after upload begins
|
||||
- Try slower upload speed (115200)
|
||||
|
||||
### General Issues
|
||||
|
||||
**LEDs not working after upload**
|
||||
- Check wiring (D4 → LED Data)
|
||||
- Verify LED strip has power
|
||||
- Test with Serial Monitor for debug output
|
||||
- Check voltage divider if using servo port
|
||||
|
||||
**Wrong colors or flickering**
|
||||
- Some LED strips are RGB instead of GRB
|
||||
- Change in code:
|
||||
```cpp
|
||||
// From:
|
||||
Adafruit_NeoPixel strip(NUM_LEDS, LED_DATA_PIN, NEO_GRB + NEO_KHZ800);
|
||||
// To:
|
||||
Adafruit_NeoPixel strip(NUM_LEDS, LED_DATA_PIN, NEO_RGB + NEO_KHZ800);
|
||||
```
|
||||
|
||||
## Testing Your Installation
|
||||
|
||||
### Serial Monitor Test
|
||||
1. Open Serial Monitor (115200 baud)
|
||||
2. Should see:
|
||||
```
|
||||
D1 Mini Blinkin Emulator
|
||||
Kraken Koders FTC Team
|
||||
LEDs: 60
|
||||
Ready!
|
||||
```
|
||||
|
||||
### LED Test
|
||||
1. LEDs should show green sweep on startup
|
||||
2. Without PWM input, LEDs turn off
|
||||
3. With PWM input, patterns change
|
||||
|
||||
### Simple Blink Test
|
||||
Upload this minimal test first:
|
||||
```cpp
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#define PIN 2 // D4
|
||||
#define NUMPIXELS 10
|
||||
|
||||
Adafruit_NeoPixel pixels(NUMPIXELS, PIN, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
void setup() {
|
||||
pixels.begin();
|
||||
pixels.setBrightness(50);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
pixels.clear();
|
||||
pixels.setPixelColor(0, pixels.Color(255, 0, 0));
|
||||
pixels.show();
|
||||
delay(500);
|
||||
pixels.clear();
|
||||
pixels.show();
|
||||
delay(500);
|
||||
}
|
||||
```
|
||||
|
||||
## Next Steps
|
||||
|
||||
1. **Build the voltage divider** - See VOLTAGE_DIVIDER_BUILD_GUIDE.md
|
||||
2. **Test with servo tester** - Verify PWM reading
|
||||
3. **Connect to FTC robot** - Configure as servo device
|
||||
4. **Customize patterns** - Add your team colors!
|
||||
|
||||
## Quick Command Reference
|
||||
|
||||
### PlatformIO Commands
|
||||
```bash
|
||||
pio run # Build
|
||||
pio run -t upload # Upload
|
||||
pio run -t clean # Clean
|
||||
pio device monitor # Serial monitor
|
||||
pio lib install "name" # Install library
|
||||
```
|
||||
|
||||
### Arduino IDE Shortcuts
|
||||
- Ctrl+R - Verify/Compile
|
||||
- Ctrl+U - Upload
|
||||
- Ctrl+Shift+M - Serial Monitor
|
||||
- Ctrl+Shift+L - Library Manager
|
||||
|
||||
## Support
|
||||
|
||||
If you're still having issues:
|
||||
1. Check all connections with multimeter
|
||||
2. Try the simple blink test first
|
||||
3. Enable DEBUG_MODE in code for more output
|
||||
4. Verify voltage divider output is 2.5-3.3V
|
||||
5. Test with different USB cable/port
|
||||
|
||||
Remember: The D1 Mini is 3.3V logic - never connect 5V directly to GPIO pins!
|
||||
178
QUICK_FLASH_GUIDE.md
Normal file
178
QUICK_FLASH_GUIDE.md
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
# Quick Flash Guide - D1 Mini Blinkin Emulator
|
||||
|
||||
## What You'll Build
|
||||
A $7 replacement for the $35 REV Blinkin LED Driver that works identically with FTC code!
|
||||
|
||||
## Parts List
|
||||
- **D1 Mini** (ESP8266) - $4
|
||||
- **2.2kΩ resistor** - $0.10
|
||||
- **3.3kΩ resistor** - $0.10
|
||||
- **Servo extension cable** - $2
|
||||
- **WS2812B LED strip** (30-60 LEDs) - $10-15
|
||||
- **Soldering supplies**
|
||||
|
||||
## Step 1: Build the Voltage Divider
|
||||
|
||||
### Why It's Needed
|
||||
- Servo port outputs 5V signals
|
||||
- D1 Mini only handles 3.3V
|
||||
- Without this, you'll fry your D1 Mini!
|
||||
|
||||
### Quick Assembly
|
||||
1. Cut servo cable 6" from female connector
|
||||
2. Strip wires (Red=5V, Black=GND, White=PWM)
|
||||
3. Solder resistors like this:
|
||||
```
|
||||
White wire ──[2.2kΩ]──┬── Wire to D2
|
||||
│
|
||||
[3.3kΩ]
|
||||
│
|
||||
Black wire
|
||||
```
|
||||
4. Heat shrink everything
|
||||
|
||||
## Step 2: Flash the D1 Mini
|
||||
|
||||
### Install Arduino IDE
|
||||
1. Download from [arduino.cc](https://www.arduino.cc/en/software)
|
||||
2. Open Arduino IDE
|
||||
3. File → Preferences → Additional Board URLs:
|
||||
```
|
||||
http://arduino.esp8266.com/stable/package_esp8266com_index.json
|
||||
```
|
||||
4. Tools → Board → Board Manager → Search "ESP8266" → Install
|
||||
|
||||
### Install Library
|
||||
Tools → Manage Libraries → Search "Adafruit NeoPixel" → Install
|
||||
|
||||
### Flash the Code
|
||||
1. Open `D1Mini_Blinkin_Ready.ino`
|
||||
2. **IMPORTANT: Edit line 20-21 for your setup:**
|
||||
```cpp
|
||||
#define NUM_LEDS 60 // Change to your LED count
|
||||
#define BRIGHTNESS 100 // Adjust brightness (0-255)
|
||||
```
|
||||
3. Tools → Board → "LOLIN(WEMOS) D1 R2 & mini"
|
||||
4. Tools → Port → Select your COM port
|
||||
5. Click Upload (→ button)
|
||||
|
||||
## Step 3: Wire Everything
|
||||
|
||||
### Final Connections
|
||||
```
|
||||
Servo Port D1 Mini LED Strip
|
||||
========== ======= =========
|
||||
Red ───────────────→ 5V
|
||||
Black ─────────────→ GND ─────────────→ GND
|
||||
White ─→[Divider]──→ D2
|
||||
D4 ───────────────→ Data In
|
||||
5V ← External Power
|
||||
```
|
||||
|
||||
### Power Notes
|
||||
- < 30 LEDs: Can use servo port power
|
||||
- > 30 LEDs: Need external 5V supply for LEDs
|
||||
|
||||
## Step 4: Test It
|
||||
|
||||
### With Serial Monitor
|
||||
1. Open Tools → Serial Monitor
|
||||
2. Set to 115200 baud
|
||||
3. You should see:
|
||||
```
|
||||
D1 Mini Blinkin Emulator v2.0
|
||||
Kraken Koders FTC Team
|
||||
Ready for PWM signal...
|
||||
```
|
||||
|
||||
### With FTC Robot
|
||||
1. Configure as servo in robot config
|
||||
2. Name it "blinkin"
|
||||
3. Use this test code:
|
||||
```java
|
||||
RevBlinkinLedDriver blinkin = hardwareMap.get(RevBlinkinLedDriver.class, "blinkin");
|
||||
blinkin.setPattern(RevBlinkinLedDriver.BlinkinPattern.RAINBOW_RAINBOW_PALETTE);
|
||||
```
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### LEDs Don't Light
|
||||
- Check D4 → LED data connection
|
||||
- Verify LED strip arrow points away from D1 Mini
|
||||
- Test with simple color first
|
||||
|
||||
### No PWM Reading
|
||||
- Measure voltage divider output (should be ~3V)
|
||||
- Check servo port is powered
|
||||
- Verify resistor values
|
||||
|
||||
### Wrong Colors
|
||||
- Some strips are RGB instead of GRB
|
||||
- Change line in code:
|
||||
```cpp
|
||||
// Change from:
|
||||
Adafruit_NeoPixel strip(NUM_LEDS, LED_DATA_PIN, NEO_GRB + NEO_KHZ800);
|
||||
// To:
|
||||
Adafruit_NeoPixel strip(NUM_LEDS, LED_DATA_PIN, NEO_RGB + NEO_KHZ800);
|
||||
```
|
||||
|
||||
### D1 Mini Keeps Resetting
|
||||
- Too many LEDs for power supply
|
||||
- Reduce brightness or LED count
|
||||
- Add external 5V power
|
||||
|
||||
## Quick Test Without Robot
|
||||
|
||||
Use a servo tester or Arduino to generate PWM:
|
||||
```cpp
|
||||
// Arduino test signal generator
|
||||
void setup() {
|
||||
pinMode(9, OUTPUT);
|
||||
}
|
||||
void loop() {
|
||||
// Sweep through patterns
|
||||
for(int pw = 1000; pw <= 2000; pw += 10) {
|
||||
digitalWrite(9, HIGH);
|
||||
delayMicroseconds(pw);
|
||||
digitalWrite(9, LOW);
|
||||
delay(20);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Pattern Reference
|
||||
|
||||
| PWM (μs) | Pattern |
|
||||
|----------|---------|
|
||||
| 1005-1015 | Rainbow |
|
||||
| 1065 | Confetti |
|
||||
| 1315 | Breath Red |
|
||||
| 1325 | Breath Blue |
|
||||
| 1515 | Solid Red |
|
||||
| 1645 | Solid Blue |
|
||||
| 1595 | Solid Green |
|
||||
| 1675 | Solid White |
|
||||
| 1995 | Off |
|
||||
|
||||
## Success Checklist
|
||||
|
||||
- [ ] Voltage divider outputs 3V (measured)
|
||||
- [ ] D1 Mini powers on
|
||||
- [ ] Serial monitor shows "Ready"
|
||||
- [ ] Green sweep on startup
|
||||
- [ ] Responds to PWM changes
|
||||
- [ ] Works with FTC code
|
||||
|
||||
## Total Cost
|
||||
- D1 Mini: $4
|
||||
- Resistors: $0.20
|
||||
- Cable: $2
|
||||
- **Total: $6.20** (vs $35 for REV Blinkin)
|
||||
|
||||
## Need Help?
|
||||
- Check serial monitor for debug info
|
||||
- Onboard LED blinks = receiving PWM
|
||||
- Green startup = code running
|
||||
- No response = check voltage divider
|
||||
|
||||
**You now have a fully functional Blinkin emulator for 1/5 the price!**
|
||||
209
README.md
Normal file
209
README.md
Normal file
|
|
@ -0,0 +1,209 @@
|
|||
# D1 Mini Blinkin LED Driver Emulator
|
||||
|
||||
This project allows a D1 Mini (ESP8266) to emulate a REV Blinkin LED Driver, enabling control of WS2812B LED strips via PWM signals from an FTC robot's REV Control Hub or Expansion Hub.
|
||||
|
||||
## Features
|
||||
|
||||
- **Full Blinkin Pattern Support**: Emulates 100+ Blinkin patterns including solid colors, animations, and effects
|
||||
- **PWM Signal Input**: Reads standard servo PWM signals (900-2100 microseconds)
|
||||
- **60 LED Support**: Configured for 60 WS2812B LEDs (adjustable in code)
|
||||
- **FastLED Library**: High-performance LED control with color correction
|
||||
- **Debug Mode**: Serial output for troubleshooting PWM values and patterns
|
||||
- **No WiFi**: WiFi disabled to save power and improve performance
|
||||
|
||||
## Hardware Requirements
|
||||
|
||||
- D1 Mini (ESP8266) or compatible board
|
||||
- WS2812B LED strip (60 LEDs default, adjustable)
|
||||
- Voltage divider circuit (5V to 3.3V for PWM input)
|
||||
- 5V power supply capable of 3-4A for 60 LEDs
|
||||
- REV Control Hub or Expansion Hub
|
||||
|
||||
## Wiring Connections
|
||||
|
||||
### PWM Signal Input (from REV Hub Servo Port)
|
||||
**IMPORTANT**: The REV Hub outputs 5V PWM signals. The D1 Mini requires 3.3V input. You MUST use a voltage divider!
|
||||
|
||||
```
|
||||
REV Hub Servo Port | Voltage Divider | D1 Mini
|
||||
-------------------|-----------------|----------
|
||||
Signal (White) | Input → Output | D2 (GPIO4)
|
||||
Power (Red) | - | 5V
|
||||
Ground (Black) | - | GND
|
||||
```
|
||||
|
||||
### Voltage Divider Circuit
|
||||
```
|
||||
REV PWM Signal (5V) ──┬── R1 (2.2kΩ) ──┬── To D1 Mini D2
|
||||
│ │
|
||||
│ R2 (3.3kΩ)
|
||||
│ │
|
||||
GND ───────────────┴── GND
|
||||
```
|
||||
|
||||
### LED Strip Connection
|
||||
```
|
||||
D1 Mini Pin | LED Strip | Description
|
||||
-------------|--------------|-------------
|
||||
D4 (GPIO2) | Data In | LED data signal
|
||||
5V | 5V | Power (use external supply)
|
||||
GND | GND | Ground
|
||||
```
|
||||
|
||||
**Power Note**: For 60 LEDs at full brightness, current draw can reach 3.6A. Use an external 5V power supply, not the REV Hub's servo power.
|
||||
|
||||
## Software Setup
|
||||
|
||||
### Method 1: PlatformIO (Recommended)
|
||||
|
||||
1. Install [Visual Studio Code](https://code.visualstudio.com/)
|
||||
2. Install PlatformIO IDE extension
|
||||
3. Clone this repository
|
||||
4. Open project folder in VS Code
|
||||
5. Connect D1 Mini via USB
|
||||
6. Click PlatformIO: Upload (→) in the bottom toolbar
|
||||
|
||||
### Method 2: Arduino IDE
|
||||
|
||||
1. Install [Arduino IDE](https://www.arduino.cc/en/software)
|
||||
2. Add ESP8266 Board Support:
|
||||
- File → Preferences → Additional Board Manager URLs:
|
||||
- Add: `http://arduino.esp8266.com/stable/package_esp8266com_index.json`
|
||||
- Tools → Board → Board Manager → Search "ESP8266" → Install
|
||||
3. Install FastLED Library:
|
||||
- Tools → Manage Libraries → Search "FastLED" → Install
|
||||
4. Select Board: Tools → Board → "LOLIN(WEMOS) D1 R2 & mini"
|
||||
5. Open `src/main.cpp` and upload
|
||||
|
||||
## FTC Robot Configuration
|
||||
|
||||
### Hardware Configuration
|
||||
1. Connect the voltage divider output to a servo port on the REV Hub
|
||||
2. In the Robot Controller app, configure the servo in your hardware map
|
||||
3. Name it something meaningful like "blinkin" or "ledDriver"
|
||||
|
||||
### Example FTC Java Code
|
||||
|
||||
```java
|
||||
import com.qualcomm.robotcore.hardware.Servo;
|
||||
import com.qualcomm.robotcore.eventloop.opmode.LinearOpMode;
|
||||
|
||||
public class BlinkinExample extends LinearOpMode {
|
||||
private Servo blinkin;
|
||||
|
||||
@Override
|
||||
public void runOpMode() {
|
||||
// Initialize
|
||||
blinkin = hardwareMap.get(Servo.class, "blinkin");
|
||||
|
||||
// Set to solid red (pattern value from Blinkin manual)
|
||||
blinkin.setPosition(0.61); // Solid Red
|
||||
|
||||
waitForStart();
|
||||
|
||||
while (opModeIsActive()) {
|
||||
// Alliance color selection
|
||||
if (gamepad1.x) {
|
||||
blinkin.setPosition(0.87); // Solid Blue
|
||||
} else if (gamepad1.b) {
|
||||
blinkin.setPosition(0.61); // Solid Red
|
||||
} else if (gamepad1.a) {
|
||||
blinkin.setPosition(0.77); // Solid Green
|
||||
} else if (gamepad1.y) {
|
||||
blinkin.setPosition(0.93); // Solid White
|
||||
}
|
||||
|
||||
// Special effects
|
||||
if (gamepad1.left_bumper) {
|
||||
blinkin.setPosition(0.41); // Rainbow
|
||||
}
|
||||
if (gamepad1.right_bumper) {
|
||||
blinkin.setPosition(0.43); // Confetti
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Common Blinkin Pattern Values
|
||||
|
||||
| Pattern | Servo Position | PWM (μs) | Description |
|
||||
|---------|---------------|----------|-------------|
|
||||
| Rainbow | 0.41 | 1005 | Rainbow palette |
|
||||
| Confetti | 0.43 | 1015 | Random colored pixels |
|
||||
| Red Shot | 0.53 | 1065 | Red chase pattern |
|
||||
| Blue Shot | 0.54 | 1075 | Blue chase pattern |
|
||||
| Red | 0.61 | 1505 | Solid red |
|
||||
| Orange | 0.65 | 1535 | Solid orange |
|
||||
| Yellow | 0.69 | 1555 | Solid yellow |
|
||||
| Green | 0.77 | 1595 | Solid green |
|
||||
| Blue | 0.87 | 1645 | Solid blue |
|
||||
| Violet | 0.91 | 1665 | Solid violet |
|
||||
| White | 0.93 | 1675 | Solid white |
|
||||
| Black/Off | 0.99 | 1695 | All LEDs off |
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit these values in `src/main.cpp`:
|
||||
|
||||
```cpp
|
||||
#define NUM_LEDS 60 // Number of LEDs in your strip
|
||||
#define BRIGHTNESS 100 // Brightness (0-255)
|
||||
#define DEBUG_MODE true // Serial debug output
|
||||
```
|
||||
|
||||
## Testing & Debugging
|
||||
|
||||
1. **Serial Monitor**: Connect via USB and open serial monitor at 115200 baud
|
||||
- Shows current PWM value and selected pattern
|
||||
- Displays startup messages and status
|
||||
|
||||
2. **LED Test**: On startup, a green sweep animation indicates the system is ready
|
||||
|
||||
3. **Manual PWM Test**: Use a servo tester to send PWM signals and verify pattern changes
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### LEDs not lighting up
|
||||
- Check 5V power supply (must provide sufficient current)
|
||||
- Verify D4 (GPIO2) is connected to LED data line
|
||||
- Confirm ground connections between all components
|
||||
|
||||
### Wrong patterns displaying
|
||||
- Verify voltage divider is working (PWM signal must be ~3.3V)
|
||||
- Check serial monitor for PWM values (should be 900-2100μs)
|
||||
- Ensure servo position in FTC code is between 0.0 and 1.0
|
||||
|
||||
### Erratic behavior
|
||||
- Add a 1000μF capacitor across LED power lines
|
||||
- Add a 470Ω resistor between D4 and LED data
|
||||
- Ensure all grounds are connected together
|
||||
|
||||
### Pattern doesn't match Blinkin
|
||||
- Some complex patterns may differ slightly from original Blinkin
|
||||
- Adjust PWM thresholds in `pwmToPattern()` function if needed
|
||||
|
||||
## Power Calculations
|
||||
|
||||
- Each WS2812B LED: ~60mA at full white brightness
|
||||
- 60 LEDs × 60mA = 3.6A maximum
|
||||
- With brightness set to 100/255: ~1.4A typical
|
||||
- D1 Mini consumption: ~80mA
|
||||
- **Recommended PSU: 5V 4A minimum**
|
||||
|
||||
## Build Guide Documentation
|
||||
|
||||
Additional documentation is available:
|
||||
- [INSTALLATION_GUIDE.md](INSTALLATION_GUIDE.md) - Detailed setup instructions
|
||||
- [VOLTAGE_DIVIDER_BUILD_GUIDE.md](VOLTAGE_DIVIDER_BUILD_GUIDE.md) - How to build the voltage divider
|
||||
- [VOLTAGE_DIVIDER_ALTERNATIVES.md](VOLTAGE_DIVIDER_ALTERNATIVES.md) - Alternative protection methods
|
||||
- [QUICK_FLASH_GUIDE.md](QUICK_FLASH_GUIDE.md) - Quick programming reference
|
||||
|
||||
## License
|
||||
|
||||
This project is open source and available for FTC teams to use and modify.
|
||||
|
||||
## Credits
|
||||
|
||||
Created for Kraken Koders FTC Team
|
||||
Based on REV Blinkin LED Driver patterns and functionality
|
||||
188
VOLTAGE_DIVIDER_ALTERNATIVES.md
Normal file
188
VOLTAGE_DIVIDER_ALTERNATIVES.md
Normal file
|
|
@ -0,0 +1,188 @@
|
|||
# Voltage Divider Alternatives - Using What You Have
|
||||
|
||||
## Solution 1: Using Only 2.2kΩ Resistors (RECOMMENDED)
|
||||
|
||||
### Option A: Two 2.2kΩ in Series for Bottom Resistor
|
||||
This creates a 2.2kΩ top and 4.4kΩ bottom divider.
|
||||
|
||||
```
|
||||
PWM (5V) ────[2.2kΩ]────┬──── To D1 Mini D2 (3.33V)
|
||||
│
|
||||
[2.2kΩ]
|
||||
│
|
||||
[2.2kΩ]
|
||||
│
|
||||
GND
|
||||
```
|
||||
|
||||
**Output Voltage:** 5V × (4.4kΩ ÷ 6.6kΩ) = **3.33V** ✓ SAFE!
|
||||
|
||||
**How to Build:**
|
||||
1. Solder white wire to first 2.2kΩ resistor
|
||||
2. Connect other end to junction point
|
||||
3. Solder TWO 2.2kΩ resistors in series from junction to ground
|
||||
4. Take output from junction to D1 Mini D2
|
||||
|
||||
### Option B: Equal Divider (Simplest)
|
||||
Uses just two 2.2kΩ resistors for a 50/50 divider.
|
||||
|
||||
```
|
||||
PWM (5V) ────[2.2kΩ]────┬──── To D1 Mini D2 (2.5V)
|
||||
│
|
||||
[2.2kΩ]
|
||||
│
|
||||
GND
|
||||
```
|
||||
|
||||
**Output Voltage:** 5V × (2.2kΩ ÷ 4.4kΩ) = **2.5V** ✓ SAFE!
|
||||
|
||||
**Pros:**
|
||||
- Simplest to build
|
||||
- Only 2 resistors needed
|
||||
- Still safe for D1 Mini
|
||||
|
||||
**Cons:**
|
||||
- Lower voltage might miss some PWM pulses in noisy environments
|
||||
- But should work fine in most cases
|
||||
|
||||
## Solution 2: Common Resistor Combinations
|
||||
|
||||
### If You Have These Resistors:
|
||||
|
||||
| Top Resistor | Bottom Resistor | Output | Safe? | Notes |
|
||||
|--------------|-----------------|--------|-------|-------|
|
||||
| 2.2kΩ | 4.7kΩ | 3.4V | ✓ Yes | Very common resistor |
|
||||
| 2.2kΩ | 2.7kΩ | 2.75V | ✓ Yes | Close to ideal |
|
||||
| 2.2kΩ | 3.9kΩ | 3.2V | ✓ Yes | Good alternative |
|
||||
| 2.2kΩ | 2.2kΩ | 2.5V | ✓ Yes | Equal divider |
|
||||
| 1kΩ | 2.2kΩ | 3.4V | ✓ Yes | If you have 1k |
|
||||
| 1kΩ | 1.5kΩ | 3.0V | ✓ Yes | Perfect output |
|
||||
|
||||
## Solution 3: No Resistors? Emergency Options
|
||||
|
||||
### Use LEDs as Voltage Droppers (NOT RECOMMENDED)
|
||||
```
|
||||
PWM (5V) ──── Red LED ──── To D1 Mini D2 (~3.3V)
|
||||
```
|
||||
- Red LED drops ~1.7V
|
||||
- Output: 5V - 1.7V = 3.3V
|
||||
- **WARNING:** Not reliable, use only for testing!
|
||||
|
||||
### Use Diodes (Better than LEDs)
|
||||
```
|
||||
PWM (5V) ──── 1N4148 ──── 1N4148 ──── To D1 Mini D2 (~3.6V)
|
||||
```
|
||||
- Each silicon diode drops ~0.7V
|
||||
- Two diodes: 5V - 1.4V = 3.6V
|
||||
- **Borderline safe** - D1 Mini can usually handle 3.6V
|
||||
|
||||
## Solution 4: Find Resistors in Old Electronics
|
||||
|
||||
### Where to Look:
|
||||
1. **Old computer power supplies** - Full of resistors
|
||||
2. **Broken LED bulbs** - Often have 1kΩ-10kΩ resistors
|
||||
3. **Old TVs/Monitors** - Tons of resistors
|
||||
4. **Broken phone chargers** - Usually have some resistors
|
||||
5. **Old Arduino/electronics kits** - Check breadboard projects
|
||||
|
||||
### How to Identify Values:
|
||||
Use online resistor color code calculator or multimeter
|
||||
|
||||
## Solution 5: Make Your Own 3kΩ-ish Resistor
|
||||
|
||||
### Parallel/Series Combinations:
|
||||
To get ~3kΩ from 2.2kΩ resistors:
|
||||
|
||||
**Option 1:** 2.2kΩ + 1kΩ in series = 3.2kΩ
|
||||
**Option 2:** 2.2kΩ + 680Ω in series = 2.88kΩ
|
||||
**Option 3:** 2.2kΩ + 820Ω in series = 3.02kΩ
|
||||
|
||||
## Quick Test Your Divider
|
||||
|
||||
### With Multimeter:
|
||||
1. Connect to 5V source (USB charger works)
|
||||
2. Measure voltage at junction
|
||||
3. Should read between 2.5V - 3.3V
|
||||
|
||||
### Test Code for D1 Mini:
|
||||
```cpp
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(D2, INPUT);
|
||||
pinMode(LED_BUILTIN, OUTPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read digital state
|
||||
int state = digitalRead(D2);
|
||||
digitalWrite(LED_BUILTIN, !state);
|
||||
|
||||
// Try to read PWM
|
||||
unsigned long pulse = pulseIn(D2, HIGH, 50000);
|
||||
if (pulse > 0) {
|
||||
Serial.print("SUCCESS! PWM: ");
|
||||
Serial.println(pulse);
|
||||
} else {
|
||||
Serial.println("Waiting for PWM...");
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
```
|
||||
|
||||
## Recommended Build with 2.2kΩ Only
|
||||
|
||||
### Materials:
|
||||
- 3× 2.2kΩ resistors
|
||||
- Servo cable
|
||||
- Small piece of wire
|
||||
|
||||
### Steps:
|
||||
1. **Cut and strip servo cable** (keep female end)
|
||||
2. **Build the divider:**
|
||||
- White wire → 2.2kΩ → Junction
|
||||
- Junction → 2.2kΩ → 2.2kΩ → Black wire
|
||||
- Junction → Wire to D1 Mini D2
|
||||
3. **Connect power:**
|
||||
- Red wire → D1 Mini 5V
|
||||
- Black wire → D1 Mini GND
|
||||
4. **Test it!**
|
||||
|
||||
### Visual Build:
|
||||
```
|
||||
[Servo Cable]
|
||||
|
|
||||
R━━━B━━━W━━━━━[2.2k]━━━━●━━━━> To D1 Mini D2
|
||||
| | |
|
||||
| | [2.2k]━━[2.2k]
|
||||
| | |
|
||||
| └────────────────────┘
|
||||
|
|
||||
└──> To D1 Mini 5V
|
||||
```
|
||||
|
||||
## Why These Work
|
||||
|
||||
The D1 Mini GPIO pins are rated for 3.3V but can tolerate up to 3.6V briefly. Any voltage between 2.5V and 3.3V will work reliably:
|
||||
|
||||
- **2.5V** - Minimum reliable HIGH signal
|
||||
- **3.0V** - Ideal target
|
||||
- **3.3V** - Perfect match
|
||||
- **3.6V** - Maximum safe limit
|
||||
- **5.0V** - WILL DAMAGE THE D1 MINI!
|
||||
|
||||
## Final Tips
|
||||
|
||||
1. **When in doubt, measure!** Use a multimeter if you have one
|
||||
2. **2.5V is better than 5V** - Lower voltage is safe, too high will kill the D1 Mini
|
||||
3. **Test with LED first** - The onboard LED should blink when receiving PWM
|
||||
4. **Use what you have** - Many combinations work, just stay under 3.6V
|
||||
|
||||
## Shopping List (if you need to buy)
|
||||
|
||||
Minimum parts from Amazon/eBay:
|
||||
- **Resistor kit** (~$5-10) - Includes hundreds of values
|
||||
- **2.7kΩ resistor** (5 pack ~$1) - Makes perfect 3V with 2.2kΩ
|
||||
- **3kΩ resistor** (5 pack ~$1) - Close enough to 3.3kΩ
|
||||
- **4.7kΩ resistor** (5 pack ~$1) - Common value, works great
|
||||
|
||||
Any of these will work perfectly with your 2.2kΩ resistor!
|
||||
238
VOLTAGE_DIVIDER_BUILD_GUIDE.md
Normal file
238
VOLTAGE_DIVIDER_BUILD_GUIDE.md
Normal file
|
|
@ -0,0 +1,238 @@
|
|||
# Voltage Divider Build Guide for D1 Mini Servo Port Connection
|
||||
|
||||
## Why You Need a Voltage Divider
|
||||
|
||||
The servo port outputs a 5V PWM signal, but the D1 Mini's GPIO pins can only safely handle 3.3V. Without a voltage divider, you risk damaging your D1 Mini!
|
||||
|
||||
## Required Components
|
||||
|
||||
### For the Voltage Divider:
|
||||
- **1x 2.2kΩ resistor** (Red-Red-Red-Gold color bands)
|
||||
- **1x 3.3kΩ resistor** (Orange-Orange-Red-Gold color bands)
|
||||
- **Alternative:** 2kΩ and 3kΩ resistors also work fine
|
||||
- **Alternative:** 1kΩ and 2kΩ resistors (gives ~3.33V output)
|
||||
|
||||
### Tools & Materials:
|
||||
- Soldering iron and solder
|
||||
- Heat shrink tubing (3mm and 6mm diameter)
|
||||
- Servo extension cable (to cut)
|
||||
- Wire strippers
|
||||
- Multimeter (optional but recommended)
|
||||
|
||||
## How a Voltage Divider Works
|
||||
|
||||
```
|
||||
5V Signal ──────[2.2kΩ]──────┬────── 3.3V Output (to D1 Mini)
|
||||
│
|
||||
[3.3kΩ]
|
||||
│
|
||||
GND
|
||||
```
|
||||
|
||||
The voltage divider reduces 5V to 3.3V using this formula:
|
||||
- Output = 5V × (3.3kΩ ÷ (2.2kΩ + 3.3kΩ))
|
||||
- Output = 5V × (3.3 ÷ 5.5) = 3.0V (safe for D1 Mini)
|
||||
|
||||
## Step-by-Step Assembly Instructions
|
||||
|
||||
### Step 1: Prepare the Servo Cable
|
||||
1. Take a servo extension cable (keep the female end)
|
||||
2. Cut it about 6 inches from the female connector
|
||||
3. Strip the three wires about 1/4 inch:
|
||||
- **Red wire** = 5V power
|
||||
- **Black/Brown wire** = Ground
|
||||
- **White/Orange/Yellow wire** = PWM signal
|
||||
|
||||
### Step 2: Build the Voltage Divider
|
||||
|
||||
#### Method A: Inline Construction (Easiest)
|
||||
```
|
||||
┌─────────────┐
|
||||
PWM Wire (White) ────┤ 2.2kΩ ├──── Junction ──── To D1 Mini D2
|
||||
└─────────────┘ │
|
||||
┌─┴─────────┐
|
||||
│ 3.3kΩ │
|
||||
└───────────┘
|
||||
│
|
||||
GND
|
||||
```
|
||||
|
||||
**Assembly Steps:**
|
||||
1. **Solder the 2.2kΩ resistor to the white wire:**
|
||||
- Tin the white wire with solder
|
||||
- Bend one leg of the 2.2kΩ resistor into a small hook
|
||||
- Hook it around the white wire and solder
|
||||
- Trim excess resistor lead
|
||||
|
||||
2. **Create the junction point:**
|
||||
- Leave about 1/2 inch of the resistor's other leg exposed
|
||||
- This will be your junction point
|
||||
|
||||
3. **Attach the 3.3kΩ resistor:**
|
||||
- Wrap one leg of the 3.3kΩ resistor around the junction
|
||||
- Solder the connection
|
||||
- The other leg of the 3.3kΩ resistor needs to connect to GND
|
||||
|
||||
4. **Add the output wire:**
|
||||
- Cut a 6-inch piece of wire (any thin wire works)
|
||||
- Strip both ends
|
||||
- Solder one end to the junction point
|
||||
- This wire goes to D1 Mini pin D2
|
||||
|
||||
5. **Connect ground:**
|
||||
- Solder the free end of the 3.3kΩ resistor to the black (GND) wire
|
||||
|
||||
6. **Insulate everything:**
|
||||
- Slide heat shrink tubing over each connection
|
||||
- Heat with lighter or heat gun to shrink
|
||||
- Use larger heat shrink to cover the entire assembly
|
||||
|
||||
#### Method B: On a Small Piece of Perfboard (More Robust)
|
||||
```
|
||||
Perfboard Layout (viewed from top):
|
||||
|
||||
●───●───●───●───●
|
||||
│ │ │ │ │
|
||||
A B C D E
|
||||
|
||||
A: PWM input (white wire)
|
||||
B: 2.2kΩ resistor start
|
||||
C: Junction (2.2kΩ end, 3.3kΩ start, output wire)
|
||||
D: 3.3kΩ resistor end
|
||||
E: Ground connection
|
||||
```
|
||||
|
||||
1. Cut a small piece of perfboard (5 holes × 3 holes)
|
||||
2. Insert resistors through holes
|
||||
3. Solder on the bottom and connect traces
|
||||
4. Add wires for input/output/ground
|
||||
5. Cover with hot glue for protection
|
||||
|
||||
### Step 3: Complete D1 Mini Connections
|
||||
|
||||
Final wiring to D1 Mini:
|
||||
```
|
||||
Servo Connector Voltage Divider D1 Mini
|
||||
=============== =============== =======
|
||||
Red (5V) ────────────────────────────────────── 5V
|
||||
Black (GND) ─────┬───────────────────────────── GND
|
||||
│
|
||||
White (PWM) ────[2.2kΩ]────┬─────────────────── D2
|
||||
│
|
||||
[3.3kΩ]
|
||||
│
|
||||
GND
|
||||
|
||||
D1 Mini D4 ──────────────────────────────────── LED Strip Data
|
||||
```
|
||||
|
||||
## Testing Your Voltage Divider
|
||||
|
||||
### With a Multimeter:
|
||||
1. Connect servo connector to a servo tester or Control Hub
|
||||
2. Set multimeter to DC voltage mode
|
||||
3. Measure between the divider output and ground
|
||||
4. You should see ~3V when PWM is high, 0V when low
|
||||
|
||||
### Quick Test Code:
|
||||
Upload this to your D1 Mini to test PWM reading:
|
||||
|
||||
```cpp
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
pinMode(D2, INPUT);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long pwm = pulseIn(D2, HIGH, 50000);
|
||||
if (pwm > 0) {
|
||||
Serial.print("PWM: ");
|
||||
Serial.print(pwm);
|
||||
Serial.println(" microseconds");
|
||||
}
|
||||
delay(100);
|
||||
}
|
||||
```
|
||||
|
||||
## Common Issues and Solutions
|
||||
|
||||
### Problem: No PWM reading
|
||||
- Check voltage divider connections with multimeter
|
||||
- Verify resistor values (use multimeter to measure)
|
||||
- Ensure good solder joints
|
||||
- Check that servo port is powered and configured
|
||||
|
||||
### Problem: Erratic readings
|
||||
- Add a 100nF ceramic capacitor from D2 to GND
|
||||
- Check for loose connections
|
||||
- Keep wires short (under 12 inches)
|
||||
|
||||
### Problem: D1 Mini resets/restarts
|
||||
- Insufficient power - add external 5V for LEDs
|
||||
- Check for shorts in wiring
|
||||
- Voltage spike - add 1000µF capacitor on power rails
|
||||
|
||||
## Alternative Resistor Values
|
||||
|
||||
If you don't have 2.2kΩ and 3.3kΩ resistors:
|
||||
|
||||
| R1 (top) | R2 (bottom) | Output Voltage | Safe? |
|
||||
|----------|-------------|----------------|-------|
|
||||
| 2.2kΩ | 3.3kΩ | 3.0V | ✓ Yes |
|
||||
| 2kΩ | 3kΩ | 3.0V | ✓ Yes |
|
||||
| 1kΩ | 2kΩ | 3.33V | ✓ Yes |
|
||||
| 10kΩ | 15kΩ | 3.0V | ✓ Yes |
|
||||
| 4.7kΩ | 6.8kΩ | 2.96V | ✓ Yes |
|
||||
| 1kΩ | 1kΩ | 2.5V | ✓ Yes (but low) |
|
||||
|
||||
## Pro Tips
|
||||
|
||||
1. **Use 1/4 watt resistors** - They're easier to work with
|
||||
2. **Color code your wires** - Makes troubleshooting easier
|
||||
3. **Test before connecting** - Always verify voltage levels
|
||||
4. **Make it modular** - Use connectors so you can disconnect for testing
|
||||
5. **Document your build** - Take photos for future reference
|
||||
|
||||
## Safety First!
|
||||
|
||||
⚠️ **NEVER** connect 5V directly to D1 Mini GPIO pins!
|
||||
⚠️ **ALWAYS** test with a multimeter before connecting
|
||||
⚠️ **DOUBLE CHECK** resistor values before soldering
|
||||
|
||||
## Quick Reference Resistor Color Codes
|
||||
|
||||
**2.2kΩ (2,200Ω):**
|
||||
- Red (2)
|
||||
- Red (2)
|
||||
- Red (×100)
|
||||
- Gold (±5% tolerance)
|
||||
|
||||
**3.3kΩ (3,300Ω):**
|
||||
- Orange (3)
|
||||
- Orange (3)
|
||||
- Red (×100)
|
||||
- Gold (±5% tolerance)
|
||||
|
||||
## Building Without Soldering (Temporary Testing)
|
||||
|
||||
For testing, you can use:
|
||||
1. **Breadboard** - Insert components for testing
|
||||
2. **Twist and tape** - Temporary but unreliable
|
||||
3. **Wire nuts** - Better than twisting
|
||||
4. **WAGO connectors** - Professional temporary connections
|
||||
|
||||
**Note:** For competition use, always solder connections!
|
||||
|
||||
## Final Assembly Checklist
|
||||
|
||||
- [ ] Voltage divider outputs 3.0-3.3V when tested
|
||||
- [ ] All connections are soldered
|
||||
- [ ] Heat shrink applied to all exposed connections
|
||||
- [ ] No shorts between power and ground
|
||||
- [ ] Servo cable connects firmly
|
||||
- [ ] D1 Mini powers on when connected
|
||||
- [ ] PWM test code shows readings 900-2100 microseconds
|
||||
- [ ] LED strip connected with proper power
|
||||
- [ ] Everything secured and won't come loose
|
||||
|
||||
Once complete, your D1 Mini is ready to emulate a REV Blinkin LED Driver!
|
||||
37
include/README
Normal file
37
include/README
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
This directory is intended for project header files.
|
||||
|
||||
A header file is a file containing C declarations and macro definitions
|
||||
to be shared between several project source files. You request the use of a
|
||||
header file in your project source file (C, C++, etc) located in `src` folder
|
||||
by including it, with the C preprocessing directive `#include'.
|
||||
|
||||
```src/main.c
|
||||
|
||||
#include "header.h"
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
```
|
||||
|
||||
Including a header file produces the same results as copying the header file
|
||||
into each source file that needs it. Such copying would be time-consuming
|
||||
and error-prone. With a header file, the related declarations appear
|
||||
in only one place. If they need to be changed, they can be changed in one
|
||||
place, and programs that include the header file will automatically use the
|
||||
new version when next recompiled. The header file eliminates the labor of
|
||||
finding and changing all the copies as well as the risk that a failure to
|
||||
find one copy will result in inconsistencies within a program.
|
||||
|
||||
In C, the convention is to give header files names that end with `.h'.
|
||||
|
||||
Read more about using header files in official GCC documentation:
|
||||
|
||||
* Include Syntax
|
||||
* Include Operation
|
||||
* Once-Only Headers
|
||||
* Computed Includes
|
||||
|
||||
https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html
|
||||
46
lib/README
Normal file
46
lib/README
Normal file
|
|
@ -0,0 +1,46 @@
|
|||
|
||||
This directory is intended for project specific (private) libraries.
|
||||
PlatformIO will compile them to static libraries and link into the executable file.
|
||||
|
||||
The source code of each library should be placed in a separate directory
|
||||
("lib/your_library_name/[Code]").
|
||||
|
||||
For example, see the structure of the following example libraries `Foo` and `Bar`:
|
||||
|
||||
|--lib
|
||||
| |
|
||||
| |--Bar
|
||||
| | |--docs
|
||||
| | |--examples
|
||||
| | |--src
|
||||
| | |- Bar.c
|
||||
| | |- Bar.h
|
||||
| | |- library.json (optional. for custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
|
||||
| |
|
||||
| |--Foo
|
||||
| | |- Foo.c
|
||||
| | |- Foo.h
|
||||
| |
|
||||
| |- README --> THIS FILE
|
||||
|
|
||||
|- platformio.ini
|
||||
|--src
|
||||
|- main.c
|
||||
|
||||
Example contents of `src/main.c` using Foo and Bar:
|
||||
```
|
||||
#include <Foo.h>
|
||||
#include <Bar.h>
|
||||
|
||||
int main (void)
|
||||
{
|
||||
...
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
The PlatformIO Library Dependency Finder will find automatically dependent
|
||||
libraries by scanning project source files.
|
||||
|
||||
More information about PlatformIO Library Dependency Finder
|
||||
- https://docs.platformio.org/page/librarymanager/ldf.html
|
||||
27
platformio.ini
Normal file
27
platformio.ini
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
; PlatformIO Project Configuration File
|
||||
;
|
||||
; Build options: build flags, source filter
|
||||
; Upload options: custom upload port, speed and extra flags
|
||||
; Library options: dependencies, extra library storages
|
||||
; Advanced options: extra scripting
|
||||
;
|
||||
; Please visit documentation for the other options and examples
|
||||
; https://docs.platformio.org/page/projectconf.html
|
||||
|
||||
[env:d1_mini]
|
||||
platform = espressif8266
|
||||
board = d1_mini
|
||||
framework = arduino
|
||||
upload_speed = 921600
|
||||
monitor_speed = 115200
|
||||
lib_deps =
|
||||
fastled/FastLED@^3.6.0
|
||||
|
||||
; Optional build flags for debugging
|
||||
build_flags =
|
||||
-D DEBUG_ESP_PORT=Serial
|
||||
-D DEBUG_ESP_BAUD=115200
|
||||
|
||||
; If you have multiple D1 Minis connected, uncomment and set specific port
|
||||
; upload_port = COM3
|
||||
; monitor_port = COM3
|
||||
898
src/main.cpp
Normal file
898
src/main.cpp
Normal file
|
|
@ -0,0 +1,898 @@
|
|||
/**
|
||||
* D1 Mini Blinkin LED Controller - Corrected to match REV Blinkin Java Driver
|
||||
*
|
||||
* This version correctly matches the pattern ordering from the Java RevBlinkinLedDriver class
|
||||
*
|
||||
* Hardware connections:
|
||||
* - D2 (GPIO4): PWM input from REV Control Hub servo port
|
||||
* - D4 (GPIO2): LED data output (WS2812B)
|
||||
* - GND: Common ground with Control Hub
|
||||
* - 5V: Power for D1 Mini (can be from USB or external)
|
||||
*
|
||||
* IMPORTANT: The pattern enum order MUST match the Java driver exactly!
|
||||
*/
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <ESP8266WiFi.h>
|
||||
#include <FastLED.h>
|
||||
|
||||
// Configuration
|
||||
#define NUM_LEDS 120 // Number of LEDs in your strip
|
||||
#define BRIGHTNESS 128 // LED brightness (0-255)
|
||||
#define DEBUG_MODE true // Enable serial debugging
|
||||
#define PWM_INPUT_PIN D2 // Pin for PWM input (GPIO4)
|
||||
#define LED_DATA_PIN D4 // Pin for LED data (GPIO2)
|
||||
#define ONBOARD_LED LED_BUILTIN // Onboard LED for status
|
||||
|
||||
// PWM constants
|
||||
#define PWM_MIN 900 // Minimum valid PWM
|
||||
#define PWM_MAX 2100 // Maximum valid PWM
|
||||
#define PWM_TIMEOUT 100000 // Timeout in microseconds (100ms)
|
||||
#define PWM_DEADBAND 5 // Deadband for PWM changes
|
||||
#define PWM_FILTER_SAMPLES 3 // Number of samples for filtering
|
||||
|
||||
// LED strip
|
||||
CRGB leds[NUM_LEDS];
|
||||
|
||||
// Pattern enumeration - MUST MATCH Java RevBlinkinLedDriver enum order EXACTLY!
|
||||
enum Pattern {
|
||||
// Fixed Palette Patterns (0-31)
|
||||
RAINBOW_RAINBOW_PALETTE, // 0
|
||||
RAINBOW_PARTY_PALETTE, // 1
|
||||
RAINBOW_OCEAN_PALETTE, // 2
|
||||
RAINBOW_LAVA_PALETTE, // 3
|
||||
RAINBOW_FOREST_PALETTE, // 4
|
||||
RAINBOW_WITH_GLITTER, // 5
|
||||
CONFETTI, // 6
|
||||
SHOT_RED, // 7
|
||||
SHOT_BLUE, // 8
|
||||
SHOT_WHITE, // 9
|
||||
SINELON_RAINBOW_PALETTE, // 10
|
||||
SINELON_PARTY_PALETTE, // 11
|
||||
SINELON_OCEAN_PALETTE, // 12
|
||||
SINELON_LAVA_PALETTE, // 13
|
||||
SINELON_FOREST_PALETTE, // 14
|
||||
BEATS_PER_MINUTE_RAINBOW_PALETTE, // 15
|
||||
BEATS_PER_MINUTE_PARTY_PALETTE, // 16
|
||||
BEATS_PER_MINUTE_OCEAN_PALETTE, // 17
|
||||
BEATS_PER_MINUTE_LAVA_PALETTE, // 18
|
||||
BEATS_PER_MINUTE_FOREST_PALETTE, // 19
|
||||
FIRE_MEDIUM, // 20
|
||||
FIRE_LARGE, // 21
|
||||
TWINKLES_RAINBOW_PALETTE, // 22
|
||||
TWINKLES_PARTY_PALETTE, // 23
|
||||
TWINKLES_OCEAN_PALETTE, // 24
|
||||
TWINKLES_LAVA_PALETTE, // 25
|
||||
TWINKLES_FOREST_PALETTE, // 26
|
||||
COLOR_WAVES_RAINBOW_PALETTE, // 27
|
||||
COLOR_WAVES_PARTY_PALETTE, // 28
|
||||
COLOR_WAVES_OCEAN_PALETTE, // 29
|
||||
COLOR_WAVES_LAVA_PALETTE, // 30
|
||||
COLOR_WAVES_FOREST_PALETTE, // 31
|
||||
LARSON_SCANNER_RED, // 32
|
||||
LARSON_SCANNER_GRAY, // 33
|
||||
LIGHT_CHASE_RED, // 34
|
||||
LIGHT_CHASE_BLUE, // 35
|
||||
LIGHT_CHASE_GRAY, // 36
|
||||
HEARTBEAT_RED, // 37
|
||||
HEARTBEAT_BLUE, // 38
|
||||
HEARTBEAT_WHITE, // 39
|
||||
HEARTBEAT_GRAY, // 40
|
||||
BREATH_RED, // 41
|
||||
BREATH_BLUE, // 42
|
||||
BREATH_GRAY, // 43
|
||||
STROBE_RED, // 44
|
||||
STROBE_BLUE, // 45
|
||||
STROBE_GOLD, // 46
|
||||
STROBE_WHITE, // 47
|
||||
|
||||
// CP1: Color 1 Patterns (48-57)
|
||||
CP1_END_TO_END_BLEND_TO_BLACK, // 48
|
||||
CP1_LARSON_SCANNER, // 49
|
||||
CP1_LIGHT_CHASE, // 50
|
||||
CP1_HEARTBEAT_SLOW, // 51
|
||||
CP1_HEARTBEAT_MEDIUM, // 52
|
||||
CP1_HEARTBEAT_FAST, // 53
|
||||
CP1_BREATH_SLOW, // 54
|
||||
CP1_BREATH_FAST, // 55
|
||||
CP1_SHOT, // 56
|
||||
CP1_STROBE, // 57
|
||||
|
||||
// CP2: Color 2 Patterns (58-67)
|
||||
CP2_END_TO_END_BLEND_TO_BLACK, // 58
|
||||
CP2_LARSON_SCANNER, // 59
|
||||
CP2_LIGHT_CHASE, // 60
|
||||
CP2_HEARTBEAT_SLOW, // 61
|
||||
CP2_HEARTBEAT_MEDIUM, // 62
|
||||
CP2_HEARTBEAT_FAST, // 63
|
||||
CP2_BREATH_SLOW, // 64
|
||||
CP2_BREATH_FAST, // 65
|
||||
CP2_SHOT, // 66
|
||||
CP2_STROBE, // 67
|
||||
|
||||
// CP1_2: Color 1 and 2 Patterns (68-77)
|
||||
CP1_2_SPARKLE_1_ON_2, // 68
|
||||
CP1_2_SPARKLE_2_ON_1, // 69
|
||||
CP1_2_COLOR_GRADIENT, // 70
|
||||
CP1_2_BEATS_PER_MINUTE, // 71
|
||||
CP1_2_END_TO_END_BLEND_1_TO_2, // 72
|
||||
CP1_2_END_TO_END_BLEND, // 73
|
||||
CP1_2_NO_BLENDING, // 74
|
||||
CP1_2_TWINKLES, // 75
|
||||
CP1_2_COLOR_WAVES, // 76
|
||||
CP1_2_SINELON, // 77
|
||||
|
||||
// Solid Colors (78-99)
|
||||
HOT_PINK, // 78
|
||||
DARK_RED, // 79
|
||||
RED, // 80
|
||||
RED_ORANGE, // 81
|
||||
ORANGE, // 82
|
||||
GOLD, // 83
|
||||
YELLOW, // 84
|
||||
LAWN_GREEN, // 85
|
||||
LIME, // 86
|
||||
DARK_GREEN, // 87
|
||||
GREEN, // 88
|
||||
BLUE_GREEN, // 89
|
||||
AQUA, // 90
|
||||
SKY_BLUE, // 91
|
||||
DARK_BLUE, // 92
|
||||
BLUE, // 93
|
||||
BLUE_VIOLET, // 94
|
||||
VIOLET, // 95
|
||||
WHITE, // 96
|
||||
GRAY, // 97
|
||||
DARK_GRAY, // 98
|
||||
BLACK // 99
|
||||
};
|
||||
|
||||
// Custom color palette support
|
||||
CRGB customColor1 = CRGB::Red;
|
||||
CRGB customColor2 = CRGB::Blue;
|
||||
|
||||
// Global variables
|
||||
Pattern currentPattern = BLACK;
|
||||
Pattern lastPattern = BLACK;
|
||||
unsigned long lastPWM = 0;
|
||||
unsigned long lastPatternChange = 0;
|
||||
unsigned long lastPWMReceived = 0;
|
||||
bool isActive = false;
|
||||
uint8_t gHue = 0; // For rainbow effects
|
||||
|
||||
// PWM filtering buffer
|
||||
unsigned long pwmBuffer[PWM_FILTER_SAMPLES];
|
||||
int pwmBufferIndex = 0;
|
||||
|
||||
void setup() {
|
||||
// Initialize serial for debugging
|
||||
if (DEBUG_MODE) {
|
||||
Serial.begin(115200);
|
||||
Serial.println("\n\nD1 Mini Blinkin LED Controller - Corrected Version");
|
||||
Serial.println("Pattern order matches Java RevBlinkinLedDriver");
|
||||
Serial.println("Using D2 for PWM input (GPIO4)");
|
||||
Serial.println("Using D4 for LED output (GPIO2)");
|
||||
Serial.println("Waiting for PWM signal...");
|
||||
}
|
||||
|
||||
// Disable WiFi to save power
|
||||
WiFi.mode(WIFI_OFF);
|
||||
WiFi.forceSleepBegin();
|
||||
|
||||
// Initialize pins
|
||||
pinMode(PWM_INPUT_PIN, INPUT);
|
||||
pinMode(ONBOARD_LED, OUTPUT);
|
||||
digitalWrite(ONBOARD_LED, HIGH); // LED off (inverted on D1 Mini)
|
||||
|
||||
// Initialize LED strip
|
||||
FastLED.addLeds<WS2812B, LED_DATA_PIN, GRB>(leds, NUM_LEDS);
|
||||
FastLED.setBrightness(BRIGHTNESS);
|
||||
FastLED.clear();
|
||||
FastLED.show();
|
||||
|
||||
// Initialize PWM buffer
|
||||
for (int i = 0; i < PWM_FILTER_SAMPLES; i++) {
|
||||
pwmBuffer[i] = 0;
|
||||
}
|
||||
|
||||
// Show startup animation
|
||||
startupAnimation();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
// Read PWM with filtering
|
||||
unsigned long pwm = readPWMFiltered();
|
||||
|
||||
// Check if we have a valid PWM signal
|
||||
if (pwm > 0) {
|
||||
lastPWMReceived = millis();
|
||||
isActive = true;
|
||||
digitalWrite(ONBOARD_LED, LOW); // LED on
|
||||
|
||||
// Convert PWM to pattern
|
||||
int newPattern = pwmToPattern(pwm);
|
||||
|
||||
// Check if pattern changed (with deadband)
|
||||
if (newPattern != currentPattern && abs((int)(pwm - lastPWM)) > PWM_DEADBAND) {
|
||||
lastPattern = currentPattern;
|
||||
currentPattern = (Pattern)newPattern;
|
||||
lastPatternChange = millis();
|
||||
lastPWM = pwm;
|
||||
|
||||
if (DEBUG_MODE) {
|
||||
Serial.print("Pattern: ");
|
||||
Serial.print(getPatternName(currentPattern));
|
||||
Serial.print(" (#");
|
||||
Serial.print(newPattern);
|
||||
Serial.print(", PWM: ");
|
||||
Serial.print(pwm);
|
||||
Serial.println(" us)");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// No PWM signal - check for timeout
|
||||
if (millis() - lastPWMReceived > 500) { // 500ms timeout
|
||||
isActive = false;
|
||||
digitalWrite(ONBOARD_LED, HIGH); // LED off
|
||||
currentPattern = BLACK;
|
||||
}
|
||||
}
|
||||
|
||||
// Update LED pattern
|
||||
updatePattern(currentPattern);
|
||||
|
||||
// Periodic status update
|
||||
static unsigned long lastStatus = 0;
|
||||
if (DEBUG_MODE && millis() - lastStatus > 1000) {
|
||||
lastStatus = millis();
|
||||
Serial.print("Status: ");
|
||||
Serial.print(isActive ? "Active" : "Inactive");
|
||||
Serial.print(" | PWM: ");
|
||||
Serial.print(lastPWM);
|
||||
Serial.print(" | Pattern: ");
|
||||
Serial.println(getPatternName(currentPattern));
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long readPWMFiltered() {
|
||||
// Read PWM pulse width with filtering
|
||||
unsigned long pulse = pulseIn(PWM_INPUT_PIN, HIGH, PWM_TIMEOUT);
|
||||
|
||||
// Filter out invalid readings
|
||||
if (pulse < PWM_MIN || pulse > PWM_MAX) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Add to filter buffer
|
||||
pwmBuffer[pwmBufferIndex] = pulse;
|
||||
pwmBufferIndex = (pwmBufferIndex + 1) % PWM_FILTER_SAMPLES;
|
||||
|
||||
// Calculate average
|
||||
unsigned long sum = 0;
|
||||
int validSamples = 0;
|
||||
for (int i = 0; i < PWM_FILTER_SAMPLES; i++) {
|
||||
if (pwmBuffer[i] > 0) {
|
||||
sum += pwmBuffer[i];
|
||||
validSamples++;
|
||||
}
|
||||
}
|
||||
|
||||
if (validSamples > 0) {
|
||||
return sum / validSamples;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pwmToPattern(unsigned long pwm) {
|
||||
// Based on Java driver calculation:
|
||||
// BASE_SERVO_POSITION = 0.2525 (505 * 0.0005)
|
||||
// PATTERN_OFFSET = 10
|
||||
// PWM = 1005 + (pattern_number * 10) microseconds
|
||||
|
||||
// Valid PWM range check
|
||||
if (pwm < 1000 || pwm > 2000) {
|
||||
return BLACK; // Default to BLACK for invalid PWM
|
||||
}
|
||||
|
||||
// Calculate pattern number from PWM
|
||||
// Pattern 0 should be at 1005μs, Pattern 1 at 1015μs, etc.
|
||||
int patternNumber = (pwm - 1005) / 10;
|
||||
|
||||
// Add rounding for values in between
|
||||
if ((pwm - 1005) % 10 >= 5) {
|
||||
patternNumber++;
|
||||
}
|
||||
|
||||
// Clamp to valid pattern range (0-99)
|
||||
if (patternNumber < 0) patternNumber = 0;
|
||||
if (patternNumber > 99) patternNumber = 99;
|
||||
|
||||
if (DEBUG_MODE && pwm != lastPWM) {
|
||||
Serial.print("PWM decode: ");
|
||||
Serial.print(pwm);
|
||||
Serial.print("us -> Pattern #");
|
||||
Serial.println(patternNumber);
|
||||
}
|
||||
|
||||
return patternNumber;
|
||||
}
|
||||
|
||||
void updatePattern(Pattern pattern) {
|
||||
static unsigned long lastUpdate = 0;
|
||||
unsigned long currentMillis = millis();
|
||||
|
||||
// Update animations at 60 FPS
|
||||
if (currentMillis - lastUpdate < 16) return;
|
||||
lastUpdate = currentMillis;
|
||||
|
||||
switch(pattern) {
|
||||
// Fixed Palette Patterns
|
||||
case RAINBOW_RAINBOW_PALETTE: rainbowCycle(); break;
|
||||
case RAINBOW_PARTY_PALETTE: partyMode(); break;
|
||||
case RAINBOW_OCEAN_PALETTE: oceanWave(); break;
|
||||
case RAINBOW_LAVA_PALETTE: lavaFlow(); break;
|
||||
case RAINBOW_FOREST_PALETTE: forestBreeze(); break;
|
||||
case RAINBOW_WITH_GLITTER: rainbowWithGlitter(); break;
|
||||
case CONFETTI: confetti(); break;
|
||||
case SHOT_RED: shot(CRGB::Red); break;
|
||||
case SHOT_BLUE: shot(CRGB::Blue); break;
|
||||
case SHOT_WHITE: shot(CRGB::White); break;
|
||||
case SINELON_RAINBOW_PALETTE: sinelon(RainbowColors_p); break;
|
||||
case SINELON_PARTY_PALETTE: sinelon(PartyColors_p); break;
|
||||
case SINELON_OCEAN_PALETTE: sinelon(OceanColors_p); break;
|
||||
case SINELON_LAVA_PALETTE: sinelon(LavaColors_p); break;
|
||||
case SINELON_FOREST_PALETTE: sinelon(ForestColors_p); break;
|
||||
case BEATS_PER_MINUTE_RAINBOW_PALETTE: bpm(RainbowColors_p); break;
|
||||
case BEATS_PER_MINUTE_PARTY_PALETTE: bpm(PartyColors_p); break;
|
||||
case BEATS_PER_MINUTE_OCEAN_PALETTE: bpm(OceanColors_p); break;
|
||||
case BEATS_PER_MINUTE_LAVA_PALETTE: bpm(LavaColors_p); break;
|
||||
case BEATS_PER_MINUTE_FOREST_PALETTE: bpm(ForestColors_p); break;
|
||||
case FIRE_MEDIUM: fire(55); break;
|
||||
case FIRE_LARGE: fire(120); break;
|
||||
case TWINKLES_RAINBOW_PALETTE: twinkles(RainbowColors_p); break;
|
||||
case TWINKLES_PARTY_PALETTE: twinkles(PartyColors_p); break;
|
||||
case TWINKLES_OCEAN_PALETTE: twinkles(OceanColors_p); break;
|
||||
case TWINKLES_LAVA_PALETTE: twinkles(LavaColors_p); break;
|
||||
case TWINKLES_FOREST_PALETTE: twinkles(ForestColors_p); break;
|
||||
case COLOR_WAVES_RAINBOW_PALETTE: colorWaves(RainbowColors_p); break;
|
||||
case COLOR_WAVES_PARTY_PALETTE: colorWaves(PartyColors_p); break;
|
||||
case COLOR_WAVES_OCEAN_PALETTE: colorWaves(OceanColors_p); break;
|
||||
case COLOR_WAVES_LAVA_PALETTE: colorWaves(LavaColors_p); break;
|
||||
case COLOR_WAVES_FOREST_PALETTE: colorWaves(ForestColors_p); break;
|
||||
case LARSON_SCANNER_RED: larsonScanner(CRGB::Red); break;
|
||||
case LARSON_SCANNER_GRAY: larsonScanner(CRGB::Gray); break;
|
||||
case LIGHT_CHASE_RED: lightChase(CRGB::Red); break;
|
||||
case LIGHT_CHASE_BLUE: lightChase(CRGB::Blue); break;
|
||||
case LIGHT_CHASE_GRAY: lightChase(CRGB::Gray); break;
|
||||
case HEARTBEAT_RED: heartbeat(CRGB::Red); break;
|
||||
case HEARTBEAT_BLUE: heartbeat(CRGB::Blue); break;
|
||||
case HEARTBEAT_WHITE: heartbeat(CRGB::White); break;
|
||||
case HEARTBEAT_GRAY: heartbeat(CRGB::Gray); break;
|
||||
case BREATH_RED: breathe(CRGB::Red); break;
|
||||
case BREATH_BLUE: breathe(CRGB::Blue); break;
|
||||
case BREATH_GRAY: breathe(CRGB::Gray); break;
|
||||
case STROBE_RED: strobe(CRGB::Red); break;
|
||||
case STROBE_BLUE: strobe(CRGB::Blue); break;
|
||||
case STROBE_GOLD: strobe(CRGB::Gold); break;
|
||||
case STROBE_WHITE: strobe(CRGB::White); break;
|
||||
|
||||
// CP1 Patterns (use customColor1)
|
||||
case CP1_END_TO_END_BLEND_TO_BLACK: endToEndBlendToBlack(customColor1); break;
|
||||
case CP1_LARSON_SCANNER: larsonScanner(customColor1); break;
|
||||
case CP1_LIGHT_CHASE: lightChase(customColor1); break;
|
||||
case CP1_HEARTBEAT_SLOW: heartbeatSlow(customColor1); break;
|
||||
case CP1_HEARTBEAT_MEDIUM: heartbeat(customColor1); break;
|
||||
case CP1_HEARTBEAT_FAST: heartbeatFast(customColor1); break;
|
||||
case CP1_BREATH_SLOW: breatheSlow(customColor1); break;
|
||||
case CP1_BREATH_FAST: breatheFast(customColor1); break;
|
||||
case CP1_SHOT: shot(customColor1); break;
|
||||
case CP1_STROBE: strobe(customColor1); break;
|
||||
|
||||
// CP2 Patterns (use customColor2)
|
||||
case CP2_END_TO_END_BLEND_TO_BLACK: endToEndBlendToBlack(customColor2); break;
|
||||
case CP2_LARSON_SCANNER: larsonScanner(customColor2); break;
|
||||
case CP2_LIGHT_CHASE: lightChase(customColor2); break;
|
||||
case CP2_HEARTBEAT_SLOW: heartbeatSlow(customColor2); break;
|
||||
case CP2_HEARTBEAT_MEDIUM: heartbeat(customColor2); break;
|
||||
case CP2_HEARTBEAT_FAST: heartbeatFast(customColor2); break;
|
||||
case CP2_BREATH_SLOW: breatheSlow(customColor2); break;
|
||||
case CP2_BREATH_FAST: breatheFast(customColor2); break;
|
||||
case CP2_SHOT: shot(customColor2); break;
|
||||
case CP2_STROBE: strobe(customColor2); break;
|
||||
|
||||
// CP1_2 Patterns (use both colors)
|
||||
case CP1_2_SPARKLE_1_ON_2: sparkle(customColor1, customColor2); break;
|
||||
case CP1_2_SPARKLE_2_ON_1: sparkle(customColor2, customColor1); break;
|
||||
case CP1_2_COLOR_GRADIENT: colorGradient(customColor1, customColor2); break;
|
||||
case CP1_2_BEATS_PER_MINUTE: bpmTwoColor(customColor1, customColor2); break;
|
||||
case CP1_2_END_TO_END_BLEND_1_TO_2: endToEndBlend(customColor1, customColor2); break;
|
||||
case CP1_2_END_TO_END_BLEND: endToEndBlend(customColor1, customColor2); break;
|
||||
case CP1_2_NO_BLENDING: noBlending(customColor1, customColor2); break;
|
||||
case CP1_2_TWINKLES: twinklesTwoColor(customColor1, customColor2); break;
|
||||
case CP1_2_COLOR_WAVES: colorWavesTwoColor(customColor1, customColor2); break;
|
||||
case CP1_2_SINELON: sinelonTwoColor(customColor1, customColor2); break;
|
||||
|
||||
// Solid Colors
|
||||
case HOT_PINK: setAll(CRGB::HotPink); break;
|
||||
case DARK_RED: setAll(CRGB::DarkRed); break;
|
||||
case RED: setAll(CRGB::Red); break;
|
||||
case RED_ORANGE: setAll(CRGB::OrangeRed); break;
|
||||
case ORANGE: setAll(CRGB::Orange); break;
|
||||
case GOLD: setAll(CRGB::Gold); break;
|
||||
case YELLOW: setAll(CRGB::Yellow); break;
|
||||
case LAWN_GREEN: setAll(CRGB::LawnGreen); break;
|
||||
case LIME: setAll(CRGB::Lime); break;
|
||||
case DARK_GREEN: setAll(CRGB::DarkGreen); break;
|
||||
case GREEN: setAll(CRGB::Green); break;
|
||||
case BLUE_GREEN: setAll(CRGB(0, 128, 128)); break;
|
||||
case AQUA: setAll(CRGB::Aqua); break;
|
||||
case SKY_BLUE: setAll(CRGB::SkyBlue); break;
|
||||
case DARK_BLUE: setAll(CRGB::DarkBlue); break;
|
||||
case BLUE: setAll(CRGB::Blue); break;
|
||||
case BLUE_VIOLET: setAll(CRGB::BlueViolet); break;
|
||||
case VIOLET: setAll(CRGB::Violet); break;
|
||||
case WHITE: setAll(CRGB::White); break;
|
||||
case GRAY: setAll(CRGB::Gray); break;
|
||||
case DARK_GRAY: setAll(CRGB::DarkGray); break;
|
||||
case BLACK: setAll(CRGB::Black); break;
|
||||
|
||||
default: setAll(CRGB::Black); break;
|
||||
}
|
||||
|
||||
FastLED.show();
|
||||
}
|
||||
|
||||
// Pattern implementation functions
|
||||
void setAll(CRGB color) {
|
||||
fill_solid(leds, NUM_LEDS, color);
|
||||
}
|
||||
|
||||
void rainbowCycle() {
|
||||
fill_rainbow(leds, NUM_LEDS, gHue, 7);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void rainbowWithGlitter() {
|
||||
rainbowCycle();
|
||||
if(random8() < 80) {
|
||||
leds[random16(NUM_LEDS)] += CRGB::White;
|
||||
}
|
||||
}
|
||||
|
||||
void partyMode() {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 10);
|
||||
int pos = random16(NUM_LEDS);
|
||||
leds[pos] += CHSV(gHue + random8(64), 200, 255);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void oceanWave() {
|
||||
fill_palette(leds, NUM_LEDS, gHue, 9, OceanColors_p, 255, LINEARBLEND);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void lavaFlow() {
|
||||
fill_palette(leds, NUM_LEDS, gHue, 9, LavaColors_p, 255, LINEARBLEND);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void forestBreeze() {
|
||||
fill_palette(leds, NUM_LEDS, gHue, 9, ForestColors_p, 255, LINEARBLEND);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void confetti() {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 10);
|
||||
int pos = random16(NUM_LEDS);
|
||||
leds[pos] += CHSV(gHue + random8(64), 200, 255);
|
||||
}
|
||||
|
||||
void shot(CRGB color) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 10);
|
||||
static int pos = 0;
|
||||
leds[pos] = color;
|
||||
pos = (pos + 1) % NUM_LEDS;
|
||||
}
|
||||
|
||||
void sinelon(CRGBPalette16 palette) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 20);
|
||||
int pos = beatsin16(13, 0, NUM_LEDS - 1);
|
||||
leds[pos] += ColorFromPalette(palette, gHue, 192);
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void bpm(CRGBPalette16 palette) {
|
||||
uint8_t BeatsPerMinute = 62;
|
||||
uint8_t beat = beatsin8(BeatsPerMinute, 64, 255);
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
leds[i] = ColorFromPalette(palette, gHue+(i*2), beat-gHue+(i*10));
|
||||
}
|
||||
gHue++;
|
||||
}
|
||||
|
||||
void fire(int cooling) {
|
||||
static byte heat[NUM_LEDS];
|
||||
|
||||
// Cool down
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
heat[i] = qsub8(heat[i], random8(0, ((cooling * 10) / NUM_LEDS) + 2));
|
||||
}
|
||||
|
||||
// Heat drift
|
||||
for(int k = NUM_LEDS - 1; k >= 2; k--) {
|
||||
heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
|
||||
}
|
||||
|
||||
// Ignite
|
||||
if(random8() < 120) {
|
||||
int y = random8(7);
|
||||
heat[y] = qadd8(heat[y], random8(160, 255));
|
||||
}
|
||||
|
||||
// Convert to LED colors
|
||||
for(int j = 0; j < NUM_LEDS; j++) {
|
||||
CRGB color = HeatColor(heat[j]);
|
||||
leds[j] = color;
|
||||
}
|
||||
}
|
||||
|
||||
void twinkles(CRGBPalette16 palette) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 80);
|
||||
if(random8() < 80) {
|
||||
leds[random16(NUM_LEDS)] = ColorFromPalette(palette, random8(), 255);
|
||||
}
|
||||
}
|
||||
|
||||
void colorWaves(CRGBPalette16 palette) {
|
||||
static uint16_t sPseudotime = 0;
|
||||
static uint16_t sLastMillis = 0;
|
||||
static uint16_t sHue16 = 0;
|
||||
|
||||
uint8_t brightdepth = beatsin88(341, 96, 224);
|
||||
uint16_t brightnessthetainc16 = beatsin88(203, (25 * 256), (40 * 256));
|
||||
uint8_t msmultiplier = beatsin88(147, 23, 60);
|
||||
|
||||
uint16_t hue16 = sHue16;
|
||||
uint16_t hueinc16 = beatsin88(113, 1, 3000);
|
||||
|
||||
uint16_t ms = millis();
|
||||
uint16_t deltams = ms - sLastMillis;
|
||||
sLastMillis = ms;
|
||||
sPseudotime += deltams * msmultiplier;
|
||||
sHue16 += deltams * beatsin88(400, 5, 9);
|
||||
uint16_t brightnesstheta16 = sPseudotime;
|
||||
|
||||
for(uint16_t i = 0; i < NUM_LEDS; i++) {
|
||||
hue16 += hueinc16;
|
||||
uint8_t hue8 = hue16 / 256;
|
||||
|
||||
brightnesstheta16 += brightnessthetainc16;
|
||||
uint16_t b16 = sin16(brightnesstheta16) + 32768;
|
||||
|
||||
uint16_t bri16 = (uint32_t)((uint32_t)b16 * (uint32_t)b16) / 65536;
|
||||
uint8_t bri8 = (uint32_t)(((uint32_t)bri16) * brightdepth) / 65536;
|
||||
bri8 += (255 - brightdepth);
|
||||
|
||||
leds[i] = ColorFromPalette(palette, hue8, bri8);
|
||||
}
|
||||
}
|
||||
|
||||
void larsonScanner(CRGB color) {
|
||||
static int pos = 0;
|
||||
static int dir = 1;
|
||||
|
||||
fadeToBlackBy(leds, NUM_LEDS, 50);
|
||||
leds[pos] = color;
|
||||
|
||||
pos += dir;
|
||||
if(pos <= 0 || pos >= NUM_LEDS - 1) dir = -dir;
|
||||
}
|
||||
|
||||
void lightChase(CRGB color) {
|
||||
static int pos = 0;
|
||||
|
||||
fadeToBlackBy(leds, NUM_LEDS, 90);
|
||||
for(int i = 0; i < NUM_LEDS; i += 3) {
|
||||
leds[(i + pos) % NUM_LEDS] = color;
|
||||
}
|
||||
pos = (pos + 1) % 3;
|
||||
}
|
||||
|
||||
void heartbeat(CRGB color) {
|
||||
static uint8_t BeatsPerMinute = 62;
|
||||
uint8_t beat = beatsin8(BeatsPerMinute, 0, 255);
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
leds[i] = color;
|
||||
leds[i].fadeLightBy(255 - beat);
|
||||
}
|
||||
}
|
||||
|
||||
void heartbeatSlow(CRGB color) {
|
||||
static uint8_t BeatsPerMinute = 40;
|
||||
uint8_t beat = beatsin8(BeatsPerMinute, 0, 255);
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
leds[i] = color;
|
||||
leds[i].fadeLightBy(255 - beat);
|
||||
}
|
||||
}
|
||||
|
||||
void heartbeatFast(CRGB color) {
|
||||
static uint8_t BeatsPerMinute = 100;
|
||||
uint8_t beat = beatsin8(BeatsPerMinute, 0, 255);
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
leds[i] = color;
|
||||
leds[i].fadeLightBy(255 - beat);
|
||||
}
|
||||
}
|
||||
|
||||
void breathe(CRGB color) {
|
||||
uint8_t brightness = beatsin8(12, 50, 255);
|
||||
fill_solid(leds, NUM_LEDS, color);
|
||||
FastLED.setBrightness(scale8(BRIGHTNESS, brightness));
|
||||
}
|
||||
|
||||
void breatheSlow(CRGB color) {
|
||||
uint8_t brightness = beatsin8(8, 50, 255);
|
||||
fill_solid(leds, NUM_LEDS, color);
|
||||
FastLED.setBrightness(scale8(BRIGHTNESS, brightness));
|
||||
}
|
||||
|
||||
void breatheFast(CRGB color) {
|
||||
uint8_t brightness = beatsin8(20, 50, 255);
|
||||
fill_solid(leds, NUM_LEDS, color);
|
||||
FastLED.setBrightness(scale8(BRIGHTNESS, brightness));
|
||||
}
|
||||
|
||||
void strobe(CRGB color) {
|
||||
static unsigned long lastStrobe = 0;
|
||||
static bool on = false;
|
||||
|
||||
if(millis() - lastStrobe > 50) {
|
||||
on = !on;
|
||||
lastStrobe = millis();
|
||||
fill_solid(leds, NUM_LEDS, on ? color : CRGB::Black);
|
||||
}
|
||||
}
|
||||
|
||||
void endToEndBlendToBlack(CRGB color) {
|
||||
static uint8_t pos = 0;
|
||||
|
||||
fadeToBlackBy(leds, NUM_LEDS, 10);
|
||||
|
||||
// Create gradient from color to black
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
uint8_t brightness = 255 - (abs(i - pos) * 8);
|
||||
if(brightness > 0) {
|
||||
leds[i] = color;
|
||||
leds[i].fadeLightBy(255 - brightness);
|
||||
}
|
||||
}
|
||||
|
||||
pos = (pos + 1) % NUM_LEDS;
|
||||
}
|
||||
|
||||
void sparkle(CRGB sparkleColor, CRGB baseColor) {
|
||||
fill_solid(leds, NUM_LEDS, baseColor);
|
||||
|
||||
if(random8() < 80) {
|
||||
leds[random16(NUM_LEDS)] = sparkleColor;
|
||||
}
|
||||
}
|
||||
|
||||
void colorGradient(CRGB color1, CRGB color2) {
|
||||
fill_gradient_RGB(leds, 0, color1, NUM_LEDS-1, color2);
|
||||
}
|
||||
|
||||
void bpmTwoColor(CRGB color1, CRGB color2) {
|
||||
uint8_t BeatsPerMinute = 62;
|
||||
uint8_t beat = beatsin8(BeatsPerMinute, 0, 255);
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
if(i % 2 == 0) {
|
||||
leds[i] = color1;
|
||||
leds[i].fadeLightBy(255 - beat);
|
||||
} else {
|
||||
leds[i] = color2;
|
||||
leds[i].fadeLightBy(beat);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void endToEndBlend(CRGB color1, CRGB color2) {
|
||||
static uint8_t pos = 0;
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
uint8_t blend = (i + pos) * 255 / NUM_LEDS;
|
||||
leds[i] = blend_CRGB(color1, color2, blend);
|
||||
}
|
||||
|
||||
pos = (pos + 1) % NUM_LEDS;
|
||||
}
|
||||
|
||||
void noBlending(CRGB color1, CRGB color2) {
|
||||
// Split the strip in half
|
||||
for(int i = 0; i < NUM_LEDS/2; i++) {
|
||||
leds[i] = color1;
|
||||
}
|
||||
for(int i = NUM_LEDS/2; i < NUM_LEDS; i++) {
|
||||
leds[i] = color2;
|
||||
}
|
||||
}
|
||||
|
||||
void twinklesTwoColor(CRGB color1, CRGB color2) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 80);
|
||||
|
||||
if(random8() < 80) {
|
||||
int pos = random16(NUM_LEDS);
|
||||
leds[pos] = (random8() < 128) ? color1 : color2;
|
||||
}
|
||||
}
|
||||
|
||||
void colorWavesTwoColor(CRGB color1, CRGB color2) {
|
||||
static uint8_t hue = 0;
|
||||
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
uint8_t brightness = sin8(hue + (i * 10));
|
||||
uint8_t blend = sin8(hue + (i * 5));
|
||||
CRGB color = blend_CRGB(color1, color2, blend);
|
||||
leds[i] = color;
|
||||
leds[i].fadeLightBy(255 - brightness);
|
||||
}
|
||||
|
||||
hue++;
|
||||
}
|
||||
|
||||
void sinelonTwoColor(CRGB color1, CRGB color2) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 20);
|
||||
|
||||
int pos1 = beatsin16(13, 0, NUM_LEDS - 1);
|
||||
int pos2 = beatsin16(11, 0, NUM_LEDS - 1);
|
||||
|
||||
leds[pos1] += color1;
|
||||
leds[pos2] += color2;
|
||||
}
|
||||
|
||||
// Helper function for blending colors
|
||||
CRGB blend_CRGB(CRGB color1, CRGB color2, uint8_t blend) {
|
||||
return CRGB(
|
||||
((color1.r * (255 - blend)) + (color2.r * blend)) / 255,
|
||||
((color1.g * (255 - blend)) + (color2.g * blend)) / 255,
|
||||
((color1.b * (255 - blend)) + (color2.b * blend)) / 255
|
||||
);
|
||||
}
|
||||
|
||||
void startupAnimation() {
|
||||
// Quick rainbow sweep
|
||||
for(int i = 0; i < NUM_LEDS; i++) {
|
||||
leds[i] = CHSV(i * 255 / NUM_LEDS, 255, 255);
|
||||
FastLED.show();
|
||||
delay(10);
|
||||
}
|
||||
|
||||
// Fade to black
|
||||
for(int i = 0; i < 50; i++) {
|
||||
fadeToBlackBy(leds, NUM_LEDS, 10);
|
||||
FastLED.show();
|
||||
delay(20);
|
||||
}
|
||||
}
|
||||
|
||||
String getPatternName(Pattern pattern) {
|
||||
switch(pattern) {
|
||||
// Fixed Palette Patterns
|
||||
case RAINBOW_RAINBOW_PALETTE: return "RAINBOW_RAINBOW_PALETTE";
|
||||
case RAINBOW_PARTY_PALETTE: return "RAINBOW_PARTY_PALETTE";
|
||||
case RAINBOW_OCEAN_PALETTE: return "RAINBOW_OCEAN_PALETTE";
|
||||
case RAINBOW_LAVA_PALETTE: return "RAINBOW_LAVA_PALETTE";
|
||||
case RAINBOW_FOREST_PALETTE: return "RAINBOW_FOREST_PALETTE";
|
||||
case RAINBOW_WITH_GLITTER: return "RAINBOW_WITH_GLITTER";
|
||||
case CONFETTI: return "CONFETTI";
|
||||
case SHOT_RED: return "SHOT_RED";
|
||||
case SHOT_BLUE: return "SHOT_BLUE";
|
||||
case SHOT_WHITE: return "SHOT_WHITE";
|
||||
case SINELON_RAINBOW_PALETTE: return "SINELON_RAINBOW_PALETTE";
|
||||
case SINELON_PARTY_PALETTE: return "SINELON_PARTY_PALETTE";
|
||||
case SINELON_OCEAN_PALETTE: return "SINELON_OCEAN_PALETTE";
|
||||
case SINELON_LAVA_PALETTE: return "SINELON_LAVA_PALETTE";
|
||||
case SINELON_FOREST_PALETTE: return "SINELON_FOREST_PALETTE";
|
||||
case BEATS_PER_MINUTE_RAINBOW_PALETTE: return "BPM_RAINBOW_PALETTE";
|
||||
case BEATS_PER_MINUTE_PARTY_PALETTE: return "BPM_PARTY_PALETTE";
|
||||
case BEATS_PER_MINUTE_OCEAN_PALETTE: return "BPM_OCEAN_PALETTE";
|
||||
case BEATS_PER_MINUTE_LAVA_PALETTE: return "BPM_LAVA_PALETTE";
|
||||
case BEATS_PER_MINUTE_FOREST_PALETTE: return "BPM_FOREST_PALETTE";
|
||||
case FIRE_MEDIUM: return "FIRE_MEDIUM";
|
||||
case FIRE_LARGE: return "FIRE_LARGE";
|
||||
case TWINKLES_RAINBOW_PALETTE: return "TWINKLES_RAINBOW_PALETTE";
|
||||
case TWINKLES_PARTY_PALETTE: return "TWINKLES_PARTY_PALETTE";
|
||||
case TWINKLES_OCEAN_PALETTE: return "TWINKLES_OCEAN_PALETTE";
|
||||
case TWINKLES_LAVA_PALETTE: return "TWINKLES_LAVA_PALETTE";
|
||||
case TWINKLES_FOREST_PALETTE: return "TWINKLES_FOREST_PALETTE";
|
||||
case COLOR_WAVES_RAINBOW_PALETTE: return "COLOR_WAVES_RAINBOW_PALETTE";
|
||||
case COLOR_WAVES_PARTY_PALETTE: return "COLOR_WAVES_PARTY_PALETTE";
|
||||
case COLOR_WAVES_OCEAN_PALETTE: return "COLOR_WAVES_OCEAN_PALETTE";
|
||||
case COLOR_WAVES_LAVA_PALETTE: return "COLOR_WAVES_LAVA_PALETTE";
|
||||
case COLOR_WAVES_FOREST_PALETTE: return "COLOR_WAVES_FOREST_PALETTE";
|
||||
case LARSON_SCANNER_RED: return "LARSON_SCANNER_RED";
|
||||
case LARSON_SCANNER_GRAY: return "LARSON_SCANNER_GRAY";
|
||||
case LIGHT_CHASE_RED: return "LIGHT_CHASE_RED";
|
||||
case LIGHT_CHASE_BLUE: return "LIGHT_CHASE_BLUE";
|
||||
case LIGHT_CHASE_GRAY: return "LIGHT_CHASE_GRAY";
|
||||
case HEARTBEAT_RED: return "HEARTBEAT_RED";
|
||||
case HEARTBEAT_BLUE: return "HEARTBEAT_BLUE";
|
||||
case HEARTBEAT_WHITE: return "HEARTBEAT_WHITE";
|
||||
case HEARTBEAT_GRAY: return "HEARTBEAT_GRAY";
|
||||
case BREATH_RED: return "BREATH_RED";
|
||||
case BREATH_BLUE: return "BREATH_BLUE";
|
||||
case BREATH_GRAY: return "BREATH_GRAY";
|
||||
case STROBE_RED: return "STROBE_RED";
|
||||
case STROBE_BLUE: return "STROBE_BLUE";
|
||||
case STROBE_GOLD: return "STROBE_GOLD";
|
||||
case STROBE_WHITE: return "STROBE_WHITE";
|
||||
|
||||
// CP1 Patterns
|
||||
case CP1_END_TO_END_BLEND_TO_BLACK: return "CP1_END_TO_END_BLEND_TO_BLACK";
|
||||
case CP1_LARSON_SCANNER: return "CP1_LARSON_SCANNER";
|
||||
case CP1_LIGHT_CHASE: return "CP1_LIGHT_CHASE";
|
||||
case CP1_HEARTBEAT_SLOW: return "CP1_HEARTBEAT_SLOW";
|
||||
case CP1_HEARTBEAT_MEDIUM: return "CP1_HEARTBEAT_MEDIUM";
|
||||
case CP1_HEARTBEAT_FAST: return "CP1_HEARTBEAT_FAST";
|
||||
case CP1_BREATH_SLOW: return "CP1_BREATH_SLOW";
|
||||
case CP1_BREATH_FAST: return "CP1_BREATH_FAST";
|
||||
case CP1_SHOT: return "CP1_SHOT";
|
||||
case CP1_STROBE: return "CP1_STROBE";
|
||||
|
||||
// CP2 Patterns
|
||||
case CP2_END_TO_END_BLEND_TO_BLACK: return "CP2_END_TO_END_BLEND_TO_BLACK";
|
||||
case CP2_LARSON_SCANNER: return "CP2_LARSON_SCANNER";
|
||||
case CP2_LIGHT_CHASE: return "CP2_LIGHT_CHASE";
|
||||
case CP2_HEARTBEAT_SLOW: return "CP2_HEARTBEAT_SLOW";
|
||||
case CP2_HEARTBEAT_MEDIUM: return "CP2_HEARTBEAT_MEDIUM";
|
||||
case CP2_HEARTBEAT_FAST: return "CP2_HEARTBEAT_FAST";
|
||||
case CP2_BREATH_SLOW: return "CP2_BREATH_SLOW";
|
||||
case CP2_BREATH_FAST: return "CP2_BREATH_FAST";
|
||||
case CP2_SHOT: return "CP2_SHOT";
|
||||
case CP2_STROBE: return "CP2_STROBE";
|
||||
|
||||
// CP1_2 Patterns
|
||||
case CP1_2_SPARKLE_1_ON_2: return "CP1_2_SPARKLE_1_ON_2";
|
||||
case CP1_2_SPARKLE_2_ON_1: return "CP1_2_SPARKLE_2_ON_1";
|
||||
case CP1_2_COLOR_GRADIENT: return "CP1_2_COLOR_GRADIENT";
|
||||
case CP1_2_BEATS_PER_MINUTE: return "CP1_2_BEATS_PER_MINUTE";
|
||||
case CP1_2_END_TO_END_BLEND_1_TO_2: return "CP1_2_END_TO_END_BLEND_1_TO_2";
|
||||
case CP1_2_END_TO_END_BLEND: return "CP1_2_END_TO_END_BLEND";
|
||||
case CP1_2_NO_BLENDING: return "CP1_2_NO_BLENDING";
|
||||
case CP1_2_TWINKLES: return "CP1_2_TWINKLES";
|
||||
case CP1_2_COLOR_WAVES: return "CP1_2_COLOR_WAVES";
|
||||
case CP1_2_SINELON: return "CP1_2_SINELON";
|
||||
|
||||
// Solid Colors
|
||||
case HOT_PINK: return "HOT_PINK";
|
||||
case DARK_RED: return "DARK_RED";
|
||||
case RED: return "RED";
|
||||
case RED_ORANGE: return "RED_ORANGE";
|
||||
case ORANGE: return "ORANGE";
|
||||
case GOLD: return "GOLD";
|
||||
case YELLOW: return "YELLOW";
|
||||
case LAWN_GREEN: return "LAWN_GREEN";
|
||||
case LIME: return "LIME";
|
||||
case DARK_GREEN: return "DARK_GREEN";
|
||||
case GREEN: return "GREEN";
|
||||
case BLUE_GREEN: return "BLUE_GREEN";
|
||||
case AQUA: return "AQUA";
|
||||
case SKY_BLUE: return "SKY_BLUE";
|
||||
case DARK_BLUE: return "DARK_BLUE";
|
||||
case BLUE: return "BLUE";
|
||||
case BLUE_VIOLET: return "BLUE_VIOLET";
|
||||
case VIOLET: return "VIOLET";
|
||||
case WHITE: return "WHITE";
|
||||
case GRAY: return "GRAY";
|
||||
case DARK_GRAY: return "DARK_GRAY";
|
||||
case BLACK: return "BLACK";
|
||||
|
||||
default: return "UNKNOWN";
|
||||
}
|
||||
}
|
||||
11
test/README
Normal file
11
test/README
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
|
||||
This directory is intended for PlatformIO Test Runner and project tests.
|
||||
|
||||
Unit Testing is a software testing method by which individual units of
|
||||
source code, sets of one or more MCU program modules together with associated
|
||||
control data, usage procedures, and operating procedures, are tested to
|
||||
determine whether they are fit for use. Unit testing finds problems early
|
||||
in the development cycle.
|
||||
|
||||
More information about PlatformIO Unit Testing:
|
||||
- https://docs.platformio.org/en/latest/advanced/unit-testing/index.html
|
||||
Loading…
Add table
Add a link
Reference in a new issue