Video
# Lab: Police Car Light Effect with TK33 WS2812 RGB LED Bar
## **Objective**
Create a realistic police car light effect using the TK33 WS2812 RGB LED Bar. This lab builds on FastLED knowledge from Lab15 to create alternating red and blue lights with various timing patterns and effects.
## **Required Components**

1. **Lonely Binary UNO R3** - Main Arduino board
2. **TinkerBlock UNO R3 Shield** - Expansion shield that plugs onto the UNO R3
3. **TinkerBlock TK33** - WS2812 RGB LED Bar (5 LEDs)
## **Theory**
### **Police Light Patterns**
- **Alternating Colors**: Red and blue lights flash in sequence
- **Timing Variations**: Different speeds for different emergency situations
- **Pattern Types**:
- **Standard**: Red-blue-red-blue pattern
- **Chase**: Moving light effect across LED bar
- **Strobe**: Quick flashing with fade effects
- **Rotating**: Circular pattern around the LED bar
### **Color Psychology**
- **Red**: Stop, danger, emergency
- **Blue**: Authority, police, emergency services
- **White**: Sometimes used for additional visibility
### **Timing Considerations**
- **Standard Speed**: ~500ms per color (typical police lights)
- **Fast Speed**: ~200ms per color (high urgency)
- **Slow Speed**: ~1000ms per color (low urgency)
- **Strobe Speed**: ~50-100ms per flash (attention-grabbing)
## **Wiring Instructions**
### **TK33 WS2812 RGB LED Bar Pinout**
- **GND** → Arduino GND
- **VCC** → Arduino 5V
- **NC** → No Connection
- **DIN** → Arduino Digital Pin 5 (or any digital pin)
### **Connection Diagram**

## **Basic Police Light Code**
```cpp
#include "FastLED.h"
// Configuration
#define LED_PIN 5 // Digital pin connected to TK33 DIN
#define NUM_LEDS 5 // Number of LEDs in TK33 bar
#define BRIGHTNESS 100 // Brightness level (0-255)
// LED array
CRGB leds[NUM_LEDS];
// Police light colors
#define POLICE_RED CRGB(255, 0, 0) // Pure red
#define POLICE_BLUE CRGB(0, 0, 255) // Pure blue
#define POLICE_WHITE CRGB(255, 255, 255) // White (optional)
void setup() {
// Initialize FastLED
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
// Initialize serial communication
Serial.begin(9600);
Serial.println("TK33 Police Car Light Effect");
Serial.println("============================");
}
void loop() {
// Pattern 1: Standard Police Lights
Serial.println("Pattern 1: Standard Police Lights");
standardPoliceLights(10); // Run for 10 cycles
// Pattern 2: Chase Effect
Serial.println("Pattern 2: Chase Effect");
chasePoliceLights(5); // Run for 5 cycles
// Pattern 3: Strobe Effect
Serial.println("Pattern 3: Strobe Effect");
strobePoliceLights(20); // Run for 20 cycles
// Pattern 4: Rotating Effect
Serial.println("Pattern 4: Rotating Effect");
rotatingPoliceLights(8); // Run for 8 cycles
// Pattern 5: Fast Emergency
Serial.println("Pattern 5: Fast Emergency");
fastEmergencyLights(15); // Run for 15 cycles
}
// Standard police light pattern
void standardPoliceLights(int cycles) {
for (int cycle = 0; cycle < cycles; cycle++) {
// All LEDs red
fill_solid(leds, NUM_LEDS, POLICE_RED);
FastLED.show();
delay(500);
// All LEDs off
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(100);
// All LEDs blue
fill_solid(leds, NUM_LEDS, POLICE_BLUE);
FastLED.show();
delay(500);
// All LEDs off
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(100);
}
}
// Chase effect - moving lights across the bar
void chasePoliceLights(int cycles) {
for (int cycle = 0; cycle < cycles; cycle++) {
// Red chase from left to right
for (int i = 0; i < NUM_LEDS; i++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
leds[i] = POLICE_RED;
FastLED.show();
delay(150);
}
// Blue chase from right to left
for (int i = NUM_LEDS - 1; i >= 0; i--) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
leds[i] = POLICE_BLUE;
FastLED.show();
delay(150);
}
}
}
// Strobe effect - quick flashing
void strobePoliceLights(int cycles) {
for (int cycle = 0; cycle < cycles; cycle++) {
// Red strobe
fill_solid(leds, NUM_LEDS, POLICE_RED);
FastLED.show();
delay(80);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(80);
// Blue strobe
fill_solid(leds, NUM_LEDS, POLICE_BLUE);
FastLED.show();
delay(80);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(80);
}
}
// Rotating effect - circular pattern
void rotatingPoliceLights(int cycles) {
for (int cycle = 0; cycle < cycles; cycle++) {
// Red rotating pattern
for (int offset = 0; offset < NUM_LEDS; offset++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = 0; i < NUM_LEDS; i += 2) {
int ledIndex = (i + offset) % NUM_LEDS;
leds[ledIndex] = POLICE_RED;
}
FastLED.show();
delay(200);
}
// Blue rotating pattern
for (int offset = 0; offset < NUM_LEDS; offset++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = 0; i < NUM_LEDS; i += 2) {
int ledIndex = (i + offset) % NUM_LEDS;
leds[ledIndex] = POLICE_BLUE;
}
FastLED.show();
delay(200);
}
}
}
// Fast emergency pattern
void fastEmergencyLights(int cycles) {
for (int cycle = 0; cycle < cycles; cycle++) {
// Quick red flash
fill_solid(leds, NUM_LEDS, POLICE_RED);
FastLED.show();
delay(100);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(50);
// Quick blue flash
fill_solid(leds, NUM_LEDS, POLICE_BLUE);
FastLED.show();
delay(100);
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(50);
}
}
```
## **Advanced Police Light Code**
```cpp
#include <FastLED.h>
// Configuration
#define LED_PIN 5
#define NUM_LEDS 5
#define BRIGHTNESS 100
// LED array
CRGB leds[NUM_LEDS];
// Timing variables
unsigned long lastRedFlash = 0;
unsigned long lastBlueFlash = 0;
bool redState = false;
bool blueState = false;
// Police light colors with fade
#define POLICE_RED CRGB(255, 0, 0)
#define POLICE_BLUE CRGB(0, 0, 255)
#define POLICE_WHITE CRGB(255, 255, 255)
void setup() {
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
Serial.begin(9600);
Serial.println("Advanced Police Light Effect");
Serial.println("============================");
}
void loop() {
// Advanced Pattern 1: Fading Police Lights
fadingPoliceLights(8);
// Advanced Pattern 2: Split Pattern
splitPoliceLights(6);
// Advanced Pattern 3: Random Strobe
randomStrobePoliceLights(25);
// Advanced Pattern 4: Wave Effect
wavePoliceLights(4);
}
// Fading police lights with smooth transitions
void fadingPoliceLights(int cycles) {
Serial.println("Advanced Pattern 1: Fading Police Lights");
for (int cycle = 0; cycle < cycles; cycle++) {
// Fade in red
for (int brightness = 0; brightness <= 255; brightness += 5) {
fill_solid(leds, NUM_LEDS, POLICE_RED);
FastLED.setBrightness(brightness);
FastLED.show();
delay(20);
}
// Fade out red
for (int brightness = 255; brightness >= 0; brightness -= 5) {
fill_solid(leds, NUM_LEDS, POLICE_RED);
FastLED.setBrightness(brightness);
FastLED.show();
delay(20);
}
// Fade in blue
for (int brightness = 0; brightness <= 255; brightness += 5) {
fill_solid(leds, NUM_LEDS, POLICE_BLUE);
FastLED.setBrightness(brightness);
FastLED.show();
delay(20);
}
// Fade out blue
for (int brightness = 255; brightness >= 0; brightness -= 5) {
fill_solid(leds, NUM_LEDS, POLICE_BLUE);
FastLED.setBrightness(brightness);
FastLED.show();
delay(20);
}
// Reset brightness
FastLED.setBrightness(BRIGHTNESS);
}
}
// Split pattern - different colors on different sides
void splitPoliceLights(int cycles) {
Serial.println("Advanced Pattern 2: Split Pattern");
for (int cycle = 0; cycle < cycles; cycle++) {
// Left side red, right side blue
for (int i = 0; i < NUM_LEDS/2; i++) {
leds[i] = POLICE_RED;
}
for (int i = NUM_LEDS/2; i < NUM_LEDS; i++) {
leds[i] = POLICE_BLUE;
}
FastLED.show();
delay(400);
// All off
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(100);
// Left side blue, right side red
for (int i = 0; i < NUM_LEDS/2; i++) {
leds[i] = POLICE_BLUE;
}
for (int i = NUM_LEDS/2; i < NUM_LEDS; i++) {
leds[i] = POLICE_RED;
}
FastLED.show();
delay(400);
// All off
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(100);
}
}
// Random strobe with varying intensity
void randomStrobePoliceLights(int cycles) {
Serial.println("Advanced Pattern 3: Random Strobe");
for (int cycle = 0; cycle < cycles; cycle++) {
// Random red strobe
int redIntensity = random(100, 255);
fill_solid(leds, NUM_LEDS, CRGB(redIntensity, 0, 0));
FastLED.show();
delay(random(50, 150));
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(random(30, 100));
// Random blue strobe
int blueIntensity = random(100, 255);
fill_solid(leds, NUM_LEDS, CRGB(0, 0, blueIntensity));
FastLED.show();
delay(random(50, 150));
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
delay(random(30, 100));
}
}
// Wave effect - flowing light pattern
void wavePoliceLights(int cycles) {
Serial.println("Advanced Pattern 4: Wave Effect");
for (int cycle = 0; cycle < cycles; cycle++) {
// Red wave
for (int wave = 0; wave < NUM_LEDS * 2; wave++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = 0; i < NUM_LEDS; i++) {
int distance = abs(i - wave);
if (distance < 3) {
int intensity = 255 - (distance * 85);
leds[i] = CRGB(intensity, 0, 0);
}
}
FastLED.show();
delay(100);
}
// Blue wave
for (int wave = 0; wave < NUM_LEDS * 2; wave++) {
fill_solid(leds, NUM_LEDS, CRGB::Black);
for (int i = 0; i < NUM_LEDS; i++) {
int distance = abs(i - wave);
if (distance < 3) {
int intensity = 255 - (distance * 85);
leds[i] = CRGB(0, 0, intensity);
}
}
FastLED.show();
delay(100);
}
}
}
```
## **Interactive Police Light Code**
```cpp
#include <FastLED.h>
// Configuration
#define LED_PIN 5
#define NUM_LEDS 5
#define BRIGHTNESS 100
// LED array
CRGB leds[NUM_LEDS];
// Pattern selection
int currentPattern = 0;
int totalPatterns = 5;
void setup() {
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(BRIGHTNESS);
Serial.begin(9600);
Serial.println("Interactive Police Light Effect");
Serial.println("===============================");
Serial.println("Commands:");
Serial.println("1-5: Select pattern");
Serial.println("+: Increase brightness");
Serial.println("-: Decrease brightness");
Serial.println("s: Stop all lights");
Serial.println("n: Next pattern");
Serial.println("p: Previous pattern");
}
void loop() {
// Check for serial commands
if (Serial.available()) {
char command = Serial.read();
handleCommand(command);
}
// Run current pattern
switch (currentPattern) {
case 0:
standardPoliceLights(1);
break;
case 1:
chasePoliceLights(1);
break;
case 2:
strobePoliceLights(2);
break;
case 3:
rotatingPoliceLights(1);
break;
case 4:
fastEmergencyLights(3);
break;
}
}
void handleCommand(char command) {
switch (command) {
case '1':
currentPattern = 0;
Serial.println("Pattern 1: Standard Police Lights");
break;
case '2':
currentPattern = 1;
Serial.println("Pattern 2: Chase Effect");
break;
case '3':
currentPattern = 2;
Serial.println("Pattern 3: Strobe Effect");
break;
case '4':
currentPattern = 3;
Serial.println("Pattern 4: Rotating Effect");
break;
case '5':
currentPattern = 4;
Serial.println("Pattern 5: Fast Emergency");
break;
case '+':
FastLED.setBrightness(min(255, BRIGHTNESS + 25));
Serial.println("Brightness increased");
break;
case '-':
FastLED.setBrightness(max(0, BRIGHTNESS - 25));
Serial.println("Brightness decreased");
break;
case 's':
fill_solid(leds, NUM_LEDS, CRGB::Black);
FastLED.show();
Serial.println("All lights stopped");
break;
case 'n':
currentPattern = (currentPattern + 1) % totalPatterns;
Serial.print("Next pattern: ");
Serial.println(currentPattern + 1);
break;
case 'p':
currentPattern = (currentPattern - 1 + totalPatterns) % totalPatterns;
Serial.print("Previous pattern: ");
Serial.println(currentPattern + 1);
break;
}
}
// Include the pattern functions from the basic code above
void standardPoliceLights(int cycles) {
// Same as basic code
}
void chasePoliceLights(int cycles) {
// Same as basic code
}
void strobePoliceLights(int cycles) {
// Same as basic code
}
void rotatingPoliceLights(int cycles) {
// Same as basic code
}
void fastEmergencyLights(int cycles) {
// Same as basic code
}
```
## **Code Explanation**
### **Pattern Types**
1. **Standard Police Lights**: Classic red-blue alternating pattern
2. **Chase Effect**: Moving lights across the LED bar
3. **Strobe Effect**: Quick flashing for attention
4. **Rotating Effect**: Circular pattern around the bar
5. **Fast Emergency**: High-speed flashing for urgency
### **Key Functions**
- **`fill_solid()`**: Set all LEDs to same color
- **`FastLED.show()`**: Update LED display
- **`delay()`**: Control timing between effects
- **`random()`**: Create random variations
### **Advanced Features**
- **Fading Effects**: Smooth brightness transitions
- **Split Patterns**: Different colors on different sides
- **Wave Effects**: Flowing light patterns
- **Interactive Control**: Serial commands for pattern selection
## **Troubleshooting**
### **Lights not flashing correctly:**
- Check timing values in delay() functions
- Verify LED_PIN is correct
- Ensure FastLED.show() is called after color changes
### **Patterns too fast or slow:**
- Adjust delay() values in pattern functions
- Standard timing: 400-500ms per color
- Fast timing: 100-200ms per color
- Strobe timing: 50-100ms per flash
### **Colors not showing properly:**
- Verify color order (GRB vs RGB)
- Check if POLICE_RED and POLICE_BLUE are defined correctly
- Test with basic colors first
### **Interactive commands not working:**
- Ensure Serial Monitor is set to 9600 baud
- Check for typos in command characters
- Verify handleCommand() function is called in loop()
## **Customization Ideas**
### **Add More Patterns:**
- **Ambulance Pattern**: Red-white alternating
- **Fire Truck Pattern**: Red with white strobe
- **Construction Pattern**: Yellow-orange alternating
- **Celebration Pattern**: Multi-color sequence
### **Add Sensors:**
- **Sound Sensor**: Flash on loud noises
- **Motion Sensor**: Activate on movement
- **Light Sensor**: Adjust brightness automatically
- **Button**: Manual pattern selection
### **Add Effects:**
- **Fade Transitions**: Smooth color changes
- **Random Timing**: Varying flash speeds
- **Intensity Control**: Brightness variations
- **Color Mixing**: Blend red and blue
## **Next Steps**
- Experiment with different timing values
- Create custom patterns for specific applications
- Combine with other sensors for interactive effects
- Scale up to longer LED strips for larger displays
## **Resources**
- **FastLED Documentation**: https://fastled.io/
- **Police Light Standards**: Research local emergency vehicle lighting regulations
- **Color Theory**: Understanding RGB color mixing
- **Timing Patterns**: Study real emergency vehicle light patterns