Troubleshooting Guide~
Common issues and solutions for the Tasmota Berry Animation Framework.
Note: This guide focuses on DSL usage, which is the recommended way to create animations. For programmatic API issues, see the Animation Development Guide.
Installation Issues~
Framework Not Found~
Problem: import animation or import animation_dsl fails with "module not found"
Solutions: 1. Check Module Import:
import animation # Core framework
import animation_dsl # DSL compiler
-
Set Module Path:
berry -m lib/libesp32/berry_animation -
Verify File Structure:
lib/libesp32/berry_animation/ ├── animation.be # Main module file ├── dsl/ # DSL components ├── core/ # Core classes ├── animations/ # Animation effects └── ...
Missing Dependencies~
Problem: Errors about missing tasmota or Leds classes
Solutions: 1. For Tasmota Environment: - Ensure you're running on actual Tasmota firmware - Check that Berry support is enabled
- For Development Environment:
# Mock Tasmota for testing if !global.contains("tasmota") global.tasmota = { "millis": def() return 1000 end, "scale_uint": def(val, from_min, from_max, to_min, to_max) return int((val - from_min) * (to_max - to_min) / (from_max - from_min) + to_min) end } end
Animation Issues~
Animations Not Starting~
Problem: DSL animations compile but LEDs don't change
Diagnostic Steps:
import animation
import animation_dsl
# Test basic DSL execution
var dsl_code = "color red = 0xFF0000\n" +
"animation red_anim = solid(color=red)\n" +
"run red_anim"
try
animation_dsl.execute(dsl_code)
print("DSL executed successfully")
except .. as e, msg
print("DSL Error:", msg)
end
Timing Behavior Note: The framework has updated timing behavior where: - The start() method only resets the time origin if the animation/value provider was already started previously - The first actual rendering tick occurs in update(), render(), or produce_value() methods - This ensures proper timing initialization and prevents premature time reference setting
Common Solutions:
-
Missing Strip Declaration:
# Add explicit strip length if needed strip length 30 color red = 0xFF0000 animation red_anim = solid(color=red) run red_anim -
Animation Not Executed:
# Make sure you have a 'run' statement color red = 0xFF0000 animation red_anim = solid(color=red) run red_anim # Don't forget this! -
Strip Auto-Detection Issues:
# Force strip length if auto-detection fails strip length 30 # Must be first statement color red = 0xFF0000 animation red_anim = solid(color=red) run red_anim
Colors Look Wrong~
Problem: Colors appear different than expected
Common Issues:
-
Missing Alpha Channel:
# Note: 0xFF0000 is valid RGB format (alpha defaults to 0xFF) color red = 0xFF0000 # RGB format (alpha=255 assumed) # Explicit alpha channel (ARGB format) color red = 0xFFFF0000 # ARGB format (alpha=255, red=255) color semi_red = 0x80FF0000 # ARGB format (alpha=128, red=255) -
Color Format Confusion:
# ARGB format: 0xAARRGGBB color red = 0xFFFF0000 # Alpha=FF, Red=FF, Green=00, Blue=00 color green = 0xFF00FF00 # Alpha=FF, Red=00, Green=FF, Blue=00 color blue = 0xFF0000FF # Alpha=FF, Red=00, Green=00, Blue=FF -
Brightness Issues:
# Use opacity parameter or property assignment animation red_anim = solid(color=red, opacity=255) # Full brightness # Or assign after creation animation pulse_red = pulsating_animation(color=red, period=2s) pulse_red.opacity = 200 # Adjust brightness # Use value providers for dynamic brightness set brightness = smooth(min_value=50, max_value=255, period=3s) animation breathing = solid(color=red) breathing.opacity = brightness
Animations Too Fast/Slow~
Problem: Animation timing doesn't match expectations
Solutions:
-
Check Time Units:
# DSL uses time units (converted to milliseconds) animation pulse_anim = pulsating_animation(color=red, period=2s) # 2 seconds animation fast_pulse = pulsating_animation(color=blue, period=500ms) # 0.5 seconds -
Adjust Periods:
# Too fast - increase period animation slow_pulse = pulsating_animation(color=red, period=5s) # 5 seconds # Too slow - decrease period animation fast_pulse = pulsating_animation(color=red, period=500ms) # 0.5 seconds -
Performance Limitations:
# Use sequences instead of multiple simultaneous animations sequence optimized_show { play animation1 for 3s play animation2 for 3s play animation3 for 3s } run optimized_show # Instead of: # run animation1 # run animation2 # run animation3
DSL Issues~
DSL Compilation Errors~
Problem: DSL code fails to compile
Diagnostic Approach:
try
var berry_code = animation_dsl.compile(dsl_source)
print("Compilation successful")
except "dsl_compilation_error" as e, msg
print("DSL Error:", msg)
end
Common DSL Errors:
-
Undefined Colors:
# Wrong - color not defined animation red_anim = solid(color=red) # Correct - define color first color red = 0xFF0000 animation red_anim = solid(color=red) -
Invalid Color Format:
# Wrong - # prefix not supported (conflicts with comments) color red = #FF0000 # Correct - use 0x prefix color red = 0xFF0000 -
Missing Time Units:
# Wrong - no time unit animation pulse_anim = pulsating_animation(color=red, period=2000) # Correct - with time unit animation pulse_anim = pulsating_animation(color=red, period=2s) -
Reserved Name Conflicts:
# Wrong - 'red' is a predefined color color red = 0x800000 # Correct - use different name color dark_red = 0x800000 -
Invalid Parameter Names:
# Wrong - invalid parameter name animation pulse_anim = pulsating_animation(color=red, invalid_param=123) # Error: "Parameter 'invalid_param' is not valid for pulsating_animation" # Correct - use valid parameters (see Dsl_Reference.md for complete list) animation pulse_anim = pulsating_animation(color=red, period=2s) -
Variable Duration Support:
# Now supported - variables in play/wait durations set eye_duration = 5s sequence cylon_eye { play red_eye for eye_duration # ✓ Variables now work wait eye_duration # ✓ Variables work in wait too } # Also supported - value providers for dynamic duration set dynamic_time = triangle(min_value=1000, max_value=3000, period=10s) sequence demo { play animation for dynamic_time # ✓ Dynamic duration } -
Template Definition Errors:
# Wrong - missing braces template pulse_effect param color type color param speed # Error: Expected '{' after template name # Wrong - invalid parameter syntax template pulse_effect { param color as color # Error: Use 'type' instead of 'as' param speed } # Wrong - missing template body template pulse_effect { param color type color } # Error: Template body cannot be empty # Correct - proper template syntax template pulse_effect { param color type color param speed animation pulse = pulsating_animation( color=color period=speed ) run pulse } -
Template Call Errors:
# Wrong - template not defined pulse_effect(red, 2s) # Error: "Undefined reference: 'pulse_effect'" # Wrong - incorrect parameter count template pulse_effect { param color type color param speed # ... template body ... } pulse_effect(red) # Error: Expected 2 parameters, got 1 # Correct - define template first, call with correct parameters template pulse_effect { param color type color param speed animation pulse = pulsating_animation(color=color, period=speed) run pulse } pulse_effect(red, 2s) # ✓ Correct usage -
Parameter Constraint Violations:
# Wrong - negative period not allowed animation bad_pulse = pulsating_animation(color=red, period=-2s) # Error: "Parameter 'period' value -2000 violates constraint: min=1" # Wrong - invalid enum value animation bad_comet = comet_animation(color=red, direction=5) # Error: "Parameter 'direction' value 5 not in allowed values: [-1, 1]" # Correct - valid parameters within constraints animation good_pulse = pulsating_animation(color=red, period=2s) animation good_comet = comet_animation(color=red, direction=1) -
Repeat Syntax Errors:
# Wrong - old colon syntax no longer supported sequence bad_demo { repeat 3 times: # Error: Expected '{' after 'times' play anim for 1s } # Wrong - missing braces sequence bad_demo2 { repeat 3 times play anim for 1s # Error: Expected '{' after 'times' } # Correct - use braces for repeat blocks sequence good_demo { repeat 3 times { play anim for 1s } } # Also correct - alternative syntax sequence good_demo_alt repeat 3 times { play anim for 1s } # Correct - forever syntax sequence infinite_demo { repeat forever { play anim for 1s wait 500ms } }
Template Issues~
Template Definition Problems~
Problem: Template definitions fail to compile
Common Template Errors:
-
Missing Template Body:
# Wrong - empty template template empty_template { param color type color } # Error: "Template body cannot be empty" # Correct - template must have content template pulse_effect { param color type color param speed animation pulse = pulsating_animation(color=color, period=speed) run pulse } -
Invalid Parameter Syntax:
# Wrong - old 'as' syntax template pulse_effect { param color as color } # Error: Expected 'type' keyword, got 'as' # Correct - use 'type' keyword template pulse_effect { param color type color param speed # Type annotation is optional } -
Template Name Conflicts:
# Wrong - template name conflicts with built-in function template solid { # 'solid' is a built-in animation function param color type color # ... } # Error: "Template name 'solid' conflicts with built-in function" # Correct - use unique template names template solid_effect { param color type color # ... }
Template Usage Problems~
Problem: Template calls fail or behave unexpectedly
Common Issues:
-
Undefined Template:
# Wrong - calling undefined template my_effect(red, 2s) # Error: "Undefined reference: 'my_effect'" # Correct - define template first template my_effect { param color type color param speed # ... template body ... } my_effect(red, 2s) # Now works -
Parameter Count Mismatch:
template pulse_effect { param color type color param speed param brightness } # Wrong - missing parameters pulse_effect(red, 2s) # Error: Expected 3 parameters, got 2 # Correct - provide all parameters pulse_effect(red, 2s, 200) -
Parameter Type Issues:
template pulse_effect { param color type color param speed } # Wrong - invalid color parameter pulse_effect("not_a_color", 2s) # Runtime error: Invalid color value # Correct - use valid color pulse_effect(red, 2s) # Named color pulse_effect(0xFF0000, 2s) # Hex color
Template vs User Function Confusion~
Problem: Mixing template and user function concepts
Key Differences:
# Template (DSL-native) - Recommended for most cases
template pulse_effect {
param color type color
param speed
animation pulse = pulsating_animation(color=color, period=speed)
run pulse
}
# User Function (Berry-native) - For complex logic
def create_pulse_effect(engine, color, speed)
var pulse = animation.pulsating_animation(engine)
pulse.color = color
pulse.period = speed
return pulse
end
animation.register_user_function("pulse_effect", create_pulse_effect)
When to Use Each: - Templates: Simple to moderate effects, DSL syntax, type safety - User Functions: Complex logic, Berry features, return values
DSL Runtime Errors~
Problem: DSL compiles but fails at runtime
Common Issues:
-
Strip Not Initialized:
# Add strip declaration if needed strip length 30 color red = 0xFF0000 animation red_anim = solid(color=red) run red_anim -
Repeat Performance Issues:
# Efficient - runtime repeats don't expand at compile time sequence efficient { repeat 1000 times { # No memory overhead for large counts play anim for 100ms wait 50ms } } # Nested repeats work efficiently sequence nested { repeat 100 times { repeat 50 times { # Total: 5000 iterations, but efficient play quick_flash for 10ms } wait 100ms } } -
Sequence Issues:
# Make sure animations are defined before sequences color red = 0xFF0000 animation red_anim = solid(color=red) # Define first sequence demo { play red_anim for 3s # Use after definition wait 1s # Optional pause between animations } run demo -
Undefined References:
# Wrong - using undefined animation in sequence sequence bad_demo { play undefined_animation for 3s } # Error: "Undefined reference: 'undefined_animation'" # Correct - define all references first color blue = 0x0000FF animation blue_anim = solid(color=blue) sequence good_demo { play blue_anim for 3s } run good_demo
Performance Issues~
CPU Metrics and Profiling~
Feature: Built-in CPU metrics tracking to monitor animation performance
The AnimationEngine automatically tracks CPU usage and provides detailed statistics every 5 seconds. This helps identify performance bottlenecks and optimize animations for ESP32 embedded systems.
Automatic Metrics:
When the engine is running, it automatically logs performance statistics:
AnimEngine: ticks=1000/1000 missed=0 total=0.50ms(0-2) anim=0.30ms(0-1) hw=0.20ms(0-1) cpu=10.0%
Phase1(checks): mean=0.05ms(0-0)
Phase2(events): mean=0.05ms(0-0)
Phase3(anim): mean=0.20ms(0-1)
Metrics Explained: - ticks: Actual ticks executed vs expected (at 5ms intervals) - missed: Hint of missed ticks (negative means extra ticks, positive means missed) - total: Mean total tick time with (min-max) range in milliseconds - anim: Mean animation calculation time with (min-max) range - everything before hardware output - hw: Mean hardware output time with (min-max) range - just the LED strip update - cpu: Overall CPU usage percentage over the 5-second period
Phase Metrics (Optional): When intermediate measurement points are available, the engine also reports phase-based timing: - Phase1(checks): Initial checks (strip length, throttling, can_show) - Phase2(events): Event processing time - Phase3(anim): Animation update and render time (before hardware output)
Timestamp-Based Profiling:
The engine uses a timestamp-based profiling system that stores only timestamps (not durations) in instance variables:
ts_start- Tick start timestampts_1- After initial checks (optional)ts_2- After event processing (optional)ts_3- After animation update/render (optional)ts_hw- After hardware outputts_end- Tick end timestamp
Durations are computed from these timestamps in _record_tick_metrics() with nil checks to ensure values are valid.
Accessing Profiling Data:
import animation
var strip = Leds(30)
var engine = animation.create_engine(strip)
# Add an animation
var anim = animation.solid(engine)
anim.color = 0xFFFF0000
engine.add(anim)
engine.run()
# Run for a while to collect metrics
# After 5 seconds, metrics are automatically logged
# Access current metrics programmatically
print("Tick count:", engine.tick_count)
print("Total time sum:", engine.tick_time_sum)
print("Animation time sum:", engine.anim_time_sum)
print("Hardware time sum:", engine.hw_time_sum)
# Access phase metrics if available
if engine.phase1_time_sum > 0
print("Phase 1 time sum:", engine.phase1_time_sum)
end
Profiling Benefits:
- Memory Efficient:
- Only stores timestamps (6 instance variables)
- No duration storage or arrays
-
Streaming statistics with no memory overhead
-
Automatic Tracking:
- No manual instrumentation needed
- Runs continuously in background
-
Reports every 5 seconds
-
Detailed Breakdown:
- Separates animation calculation from hardware output
- Optional phase-based timing for deeper analysis
- Min/max/mean statistics for all metrics
Interpreting Performance Metrics:
- High Animation Time:
- Too many simultaneous animations
- Complex value provider calculations
- Inefficient custom effects
Solution: Simplify animations or use sequences
- High Hardware Time:
- Large LED strip (many pixels)
- Slow SPI/I2C communication
- Hardware limitations
Solution: Reduce update frequency or strip length
- Missed Ticks:
- CPU overload (total time > 5ms per tick)
- Other Tasmota tasks interfering
Solution: Optimize animations or reduce complexity
- High CPU Percentage:
- Animations consuming too much CPU
- May affect other Tasmota functions
Solution: Increase animation periods or reduce effects
Example Performance Optimization:
import animation
var strip = Leds(60)
var engine = animation.create_engine(strip)
# Before optimization - complex animation
var complex_anim = animation.rainbow_animation(engine)
complex_anim.period = 100 # Very fast, high CPU
engine.add(complex_anim)
engine.run()
# Check metrics after 5 seconds:
# AnimEngine: ticks=950/1000 missed=50 total=5.2ms(4-8) cpu=104.0%
# ^ Too slow! Missing ticks and over 100% CPU
# After optimization - slower period
complex_anim.period = 2000 # 2 seconds instead of 100ms
# Check metrics after 5 seconds:
# AnimEngine: ticks=1000/1000 missed=0 total=0.8ms(0-2) cpu=16.0%
# ^ Much better! All ticks processed, reasonable CPU usage
Choppy Animations~
Problem: Animations appear jerky or stuttering
Solutions:
-
Use Sequences Instead of Multiple Animations:
# Good - sequential playback sequence smooth_show { play animation1 for 3s play animation2 for 3s play animation3 for 3s } run smooth_show # Avoid - too many simultaneous animations # run animation1 # run animation2 # run animation3 -
Increase Animation Periods:
# Smooth - longer periods animation smooth_pulse = pulsating_animation(color=red, period=3s) # Choppy - very short periods animation choppy_pulse = pulsating_animation(color=red, period=50ms) -
Optimize Value Providers:
# Efficient - reuse providers set breathing = smooth(min_value=50, max_value=255, period=2s) color red = 0xFF0000 color blue = 0x0000FF animation anim1 = pulsating_animation(color=red, period=2s) anim1.opacity = breathing animation anim2 = pulsating_animation(color=blue, period=2s) anim2.opacity = breathing # Reuse same provider -
Monitor CPU Metrics:
# Check if CPU is overloaded # Look for missed ticks or high CPU percentage in metrics # AnimEngine: ticks=950/1000 missed=50 ... cpu=95.0% # ^ This indicates performance issues # Use profiling to find bottlenecks engine.profile_start("suspect_code") # ... code that might be slow ... engine.profile_end("suspect_code")
Memory Issues~
Problem: Out of memory errors or system crashes
Solutions:
-
Clear Unused Animations:
# Clear before adding new animations engine.clear() engine.add(new_animation) -
Limit Palette Size:
# Good - reasonable palette size palette simple_fire = [ (0, 0x000000), (128, 0xFF0000), (255, 0xFFFF00) ] # Avoid - very large palettes # palette huge_palette = [ # (0, color1), (1, color2), ... (255, color256) # ] -
Use Sequences Instead of Simultaneous Animations:
# Memory efficient - sequential playback sequence show { play animation1 for 5s play animation2 for 5s play animation3 for 5s } # Memory intensive - all at once # run animation1 # run animation2 # run animation3
Event System Issues~
Events Not Triggering~
Problem: Event handlers don't execute
Diagnostic Steps:
# Check if handler is registered
var handlers = animation.get_event_handlers("button_press")
print("Handler count:", size(handlers))
# Test event triggering
animation.trigger_event("test_event", {"debug": true})
Solutions:
-
Verify Handler Registration:
def test_handler(event_data) print("Event triggered:", event_data) end var handler = animation.register_event_handler("test", test_handler, 0) print("Handler registered:", handler != nil) -
Check Event Names:
# Event names are case-sensitive animation.register_event_handler("button_press", handler) # Correct animation.trigger_event("button_press", {}) # Must match exactly -
Verify Conditions:
def condition_func(event_data) return event_data.contains("required_field") end animation.register_event_handler("event", handler, 0, condition_func) # Event data must satisfy condition animation.trigger_event("event", {"required_field": "value"})
Hardware Issues~
LEDs Not Responding~
Problem: Framework runs but LEDs don't light up
Hardware Checks:
- Power Supply:
- Ensure adequate power for LED count
- Check voltage (5V for WS2812)
-
Verify ground connections
-
Wiring:
- Data line connected to correct GPIO
- Ground connected between controller and LEDs
-
Check for loose connections
-
LED Strip:
- Test with known working code
- Check for damaged LEDs
- Verify strip type (WS2812, SK6812, etc.)
Software Checks:
# Test basic LED functionality
var strip = Leds(30) # 30 LEDs
strip.set_pixel_color(0, 0xFFFF0000) # Set first pixel red
strip.show() # Update LEDs
# Test with animation framework
import animation
var engine = animation.create_engine(strip)
var red_anim = animation.solid(engine)
red_anim.color = 0xFFFF0000
engine.add(red_anim)
engine.run()
# If basic strip works but animation doesn't, check framework setup
Wrong Colors on Hardware~
Problem: Colors look different on actual LEDs vs. expected
Solutions:
-
Color Order:
# Some strips use different color orders # Try different strip types in Tasmota configuration # WS2812: RGB order # SK6812: GRBW order -
Gamma Correction:
# Enable gamma correction in Tasmota # SetOption37 128 # Enable gamma correction -
Power Supply Issues:
- Voltage drop causes color shifts
- Use adequate power supply
- Add power injection for long strips
Debugging Techniques~
DSL vs Berry API Debugging~
For DSL Issues (Recommended):
# Enable DSL debug output
import animation_dsl
var dsl_code = "color red = 0xFF0000\nanimation test = solid(color=red)\nrun test"
# Check compilation
try
var berry_code = animation_dsl.compile(dsl_code)
print("DSL compilation successful")
print("Generated Berry code:")
print(berry_code)
except .. as e, msg
print("DSL compilation error:", msg)
end
# Execute with debug
try
animation_dsl.execute(dsl_code, true) # debug=true
except .. as e, msg
print("DSL execution error:", msg)
end
For Framework Issues (Advanced):
# Direct Berry API debugging (for framework developers)
import animation
var strip = Leds(30)
var engine = animation.create_engine(strip, true) # debug=true
var anim = animation.solid(engine)
anim.color = 0xFFFF0000
engine.add(anim)
engine.run()
Step-by-Step Testing~
# Test each component individually
print("1. Creating strip...")
var strip = Leds(30)
print("Strip created:", strip != nil)
print("2. Creating engine...")
var engine = animation.create_engine(strip)
print("Engine created:", engine != nil)
print("3. Creating animation...")
var anim = animation.solid(engine)
anim.color = 0xFFFF0000
print("Animation created:", anim != nil)
print("4. Adding animation...")
engine.add(anim)
print("Animation count:", engine.size())
print("5. Starting engine...")
engine.run()
print("Engine active:", engine.is_active())
Monitor Performance~
# Check timing
var start_time = tasmota.millis()
# ... run animation code ...
var end_time = tasmota.millis()
print("Execution time:", end_time - start_time, "ms")
# Monitor memory (if available)
import gc
print("Memory before:", gc.allocated())
# ... create animations ...
print("Memory after:", gc.allocated())
Getting Help~
Information to Provide~
When asking for help, include:
- Hardware Setup:
- LED strip type and count
- GPIO pin used
-
Power supply specifications
-
Software Environment:
- Tasmota version
- Berry version
-
Framework version
-
Code:
- Complete minimal example that reproduces the issue
- Error messages (exact text)
-
Expected vs. actual behavior
-
Debugging Output:
- Debug mode output
- Generated Berry code (for DSL issues)
- Console output
Example Bug Report~
**Problem:** DSL animation compiles but LEDs don't change
**Hardware:**
- 30x WS2812 LEDs on GPIO 1
- ESP32 with 5V/2A power supply
**Code:**
```berry
color red = 0xFF0000
animation red_anim = solid(color=red)
run red_anim
Error Output:
DSL compilation successful
Engine created: true
Animation count: 1
Engine active: true
Expected: LEDs turn red Actual: LEDs remain off
Additional Info: - Basic strip.set_pixel_color(0, 0xFFFF0000); strip.show() works - Tasmota 13.2.0, Berry enabled
This format helps identify issues quickly and provide targeted solutions.
## Prevention Tips
### Code Quality
1. **Use Try-Catch Blocks:**
```berry
try
runtime.load_dsl(dsl_code)
except .. as e, msg
print("Error:", msg)
end
```
2. **Validate Inputs:**
```berry
if type(color) == "int" && color >= 0
var anim = animation.solid(color)
else
print("Invalid color:", color)
end
```
3. **Test Incrementally:**
- Start with simple solid colors
- Add one effect at a time
- Test each change before proceeding
### Performance Best Practices
1. **Limit Complexity:**
- 1-3 simultaneous animations
- Reasonable animation periods (>1 second)
- Moderate palette sizes
2. **Resource Management:**
- Clear unused animations
- Reuse value providers
- Use sequences for complex shows
3. **Hardware Considerations:**
- Adequate power supply
- Proper wiring and connections
- Appropriate LED strip for application
## Quick Reference: Common DSL Patterns
### Basic Animation
```berry
color red = 0xFF0000
animation red_solid = solid(color=red)
run red_solid
Templates~
# Define reusable template
template pulse_effect {
param base_color type color # Use descriptive names
param speed type time # Add type annotations for clarity
animation pulse = pulsating_animation(color=base_color, period=speed)
run pulse
}
# Use template multiple times
pulse_effect(red, 2s)
pulse_effect(blue, 1s)
Common Template Parameter Issues:
# ❌ AVOID: Parameter name conflicts
template bad_example {
param color type color # Error: conflicts with built-in color name
param animation type number # Error: conflicts with reserved keyword
}
# ✅ CORRECT: Use descriptive, non-conflicting names
template good_example {
param base_color type color # Clear, non-conflicting name
param anim_speed type time # Descriptive parameter name
}
# ⚠️ WARNING: Unused parameters generate warnings
template unused_param_example {
param used_color type color
param unused_value type number # Warning: never used in template body
animation test = solid(color=used_color)
run test
}
Animation with Parameters~
color blue = 0x0000FF
animation blue_pulse = pulsating_animation(color=blue, period=2s, opacity=200)
run blue_pulse
Using Value Providers~
set breathing = smooth(min_value=50, max_value=255, period=3s)
color green = 0x00FF00
animation breathing_green = solid(color=green)
breathing_green.opacity = breathing
run breathing_green
Sequences~
color red = 0xFF0000
color blue = 0x0000FF
animation red_anim = solid(color=red)
animation blue_anim = solid(color=blue)
sequence demo {
play red_anim for 2s
wait 500ms
play blue_anim for 2s
}
run demo
Multiple Strip Lengths~
strip length 60 # Must be first statement
color rainbow = rainbow_color_provider(period=5s)
animation rainbow_anim = solid(color=rainbow)
run rainbow_anim
Following these guidelines will help you avoid most common issues and create reliable LED animations.