04 - Lab Police Car Light Effect

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** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250722161321.png?v=1753856096) 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** ![](https://cdn.shopify.com/s/files/1/0331/9994/7908/files/Pasted_image_20250723103231.png?v=1753856109) ## **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