Tasmota/lib/libesp32/berry_animation/docs/TROUBLESHOOTING.md

17 KiB

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
    
  2. Set Module Path:

    berry -m lib/libesp32/berry_animation
    
  3. 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
  2. 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

Common Solutions:

  1. Missing Strip Declaration:

    # Add explicit strip length if needed
    strip length 30
    
    color red = 0xFF0000
    animation red_anim = solid(color=red)
    run red_anim
    
  2. 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!
    
  3. 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:

  1. 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)
    
  2. 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
    
  3. 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:

  1. 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
    
  2. 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
    
  3. 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:

  1. 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)
    
  2. Invalid Color Format:

    # Wrong - # prefix not supported (conflicts with comments)
    color red = #FF0000
    
    # Correct - use 0x prefix
    color red = 0xFF0000
    
  3. 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)
    
  4. Reserved Name Conflicts:

    # Wrong - 'red' is a predefined color
    color red = 0x800000
    
    # Correct - use different name
    color dark_red = 0x800000
    
  5. 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)
    
  6. 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)
    

DSL Runtime Errors

Problem: DSL compiles but fails at runtime

Common Issues:

  1. Strip Not Initialized:

    # Add strip declaration if needed
    strip length 30
    
    color red = 0xFF0000
    animation red_anim = solid(color=red)
    run red_anim
    
  2. 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
    
  3. 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

Choppy Animations

Problem: Animations appear jerky or stuttering

Solutions:

  1. 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
    
  2. 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)
    
  3. 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
    

Memory Issues

Problem: Out of memory errors or system crashes

Solutions:

  1. Clear Unused Animations:

    # Clear before adding new animations
    engine.clear()
    engine.add_animation(new_animation)
    
  2. Limit Palette Size:

    # Good - reasonable palette size
    palette simple_fire = [
      (0, #000000),
      (128, #FF0000),
      (255, #FFFF00)
    ]
    
    # Avoid - very large palettes
    # palette huge_palette = [
    #   (0, color1), (1, color2), ... (255, color256)
    # ]
    
  3. 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:

  1. 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)
    
  2. Check Event Names:

    # Event names are case-sensitive
    animation.register_event_handler("button_press", handler)  # Correct
    animation.trigger_event("button_press", {})               # Must match exactly
    
  3. 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:

  1. Power Supply:

    • Ensure adequate power for LED count
    • Check voltage (5V for WS2812)
    • Verify ground connections
  2. Wiring:

    • Data line connected to correct GPIO
    • Ground connected between controller and LEDs
    • Check for loose connections
  3. 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_animation(red_anim)
engine.start()

# 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:

  1. Color Order:

    # Some strips use different color orders
    # Try different strip types in Tasmota configuration
    # WS2812: RGB order
    # SK6812: GRBW order
    
  2. Gamma Correction:

    # Enable gamma correction in Tasmota
    # SetOption37 128  # Enable gamma correction
    
  3. 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_animation(anim)
engine.start()

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_animation(anim)
print("Animation count:", engine.size())

print("5. Starting engine...")
engine.start()
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:

  1. Hardware Setup:

    • LED strip type and count
    • GPIO pin used
    • Power supply specifications
  2. Software Environment:

    • Tasmota version
    • Berry version
    • Framework version
  3. Code:

    • Complete minimal example that reproduces the issue
    • Error messages (exact text)
    • Expected vs. actual behavior
  4. 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:**
```dsl
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
  1. Validate Inputs:

    if type(color) == "int" && color >= 0
      var anim = animation.solid(color)
    else
      print("Invalid color:", color)
    end
    
  2. 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

color red = 0xFF0000
animation red_solid = solid(color=red)
run red_solid

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.