|
| 1 | +use rs_ws281x::ControllerBuilder; |
| 2 | +use rs_ws281x::ChannelBuilder; |
| 3 | +use rs_ws281x::StripType; |
| 4 | +use rs_ws281x::Controller; |
| 5 | +use rand::{thread_rng, Rng}; |
| 6 | + |
| 7 | +pub fn main() { |
| 8 | + let mut controller = ControllerBuilder::new() |
| 9 | + .freq(800_000) |
| 10 | + .dma(10) |
| 11 | + .channel( |
| 12 | + 0, // Channel Index |
| 13 | + ChannelBuilder::new() |
| 14 | + .pin(18) // GPIO 10 = SPI0 MOSI |
| 15 | + .count(100) // Number of LEDs |
| 16 | + .strip_type(StripType::Ws2812) |
| 17 | + .brightness(255) // default: 255 |
| 18 | + .invert(false) |
| 19 | + .build(), |
| 20 | + ) |
| 21 | + .build() |
| 22 | + .unwrap(); |
| 23 | + |
| 24 | + |
| 25 | + let led_count = controller.leds_mut(0).len(); |
| 26 | + let custom_mid_point = 60; // Custom midpoint, can be set dynamically |
| 27 | + |
| 28 | + // Calculate the delay for the second LED to start |
| 29 | + let delay_start = custom_mid_point - (led_count - custom_mid_point); |
| 30 | + |
| 31 | + // Phase 1: Two LEDs meet in the middle |
| 32 | + for step in 0..custom_mid_point { |
| 33 | + let leds = controller.leds_mut(0); |
| 34 | + // Clear the strip in each iteration to ensure only the intended LEDs are lit |
| 35 | + for led in leds.iter_mut() { |
| 36 | + *led = [0, 0, 0, 0]; |
| 37 | + } |
| 38 | + |
| 39 | + // Light up the first LED from the start |
| 40 | + if step < custom_mid_point { |
| 41 | + leds[step] = [255, 255, 255, 0]; // Left moving LED |
| 42 | + } |
| 43 | + |
| 44 | + // Start the second LED after the calculated delay |
| 45 | + if step >= delay_start { |
| 46 | + let right_led_position = led_count - (step - delay_start) - 1; |
| 47 | + leds[right_led_position] = [255, 255, 255, 0]; // Right moving LED |
| 48 | + } |
| 49 | + |
| 50 | + controller.render().unwrap(); |
| 51 | + std::thread::sleep(std::time::Duration::from_millis(50)); // Movement speed |
| 52 | + } |
| 53 | + |
| 54 | + // Ensure the midpoint includes two LEDs, one for each side |
| 55 | + let leds = controller.leds_mut(0); |
| 56 | + leds[custom_mid_point - 1] = [255, 255, 255, 0]; // Adjust for 0-based index |
| 57 | + leds[custom_mid_point] = [255, 255, 255, 0]; |
| 58 | + controller.render().unwrap(); |
| 59 | + |
| 60 | + // Phase 2: Fill in the strip from the middle back to the ends |
| 61 | + for step in 1..custom_mid_point { // Start from 1 to avoid re-lighting the midpoint LEDs |
| 62 | + let leds = controller.leds_mut(0); |
| 63 | + |
| 64 | + // Fill towards the start from the left of the custom midpoint |
| 65 | + if custom_mid_point - step > 0 { // Check to avoid underflow |
| 66 | + leds[custom_mid_point - step - 1] = [255, 255, 255, 0]; // Left side |
| 67 | + } |
| 68 | + |
| 69 | + // Fill towards the end from the right of the custom midpoint |
| 70 | + if custom_mid_point + step < led_count { // Check to avoid overflow |
| 71 | + leds[custom_mid_point + step] = [255, 255, 255, 0]; // Right side |
| 72 | + } |
| 73 | + |
| 74 | + controller.render().unwrap(); |
| 75 | + std::thread::sleep(std::time::Duration::from_millis(50)); // Movement speed |
| 76 | + } |
| 77 | + |
| 78 | + // Phase 3: Breathing effect |
| 79 | + for _ in 0..4 { |
| 80 | + let min_brightness = 1; // Very dim but not off |
| 81 | + let max_brightness = 255; // Max brightness |
| 82 | + let step_size = 5; // Adjust for smoother or quicker transitions |
| 83 | + |
| 84 | + // Gradually decrease brightness |
| 85 | + for brightness in (min_brightness..=max_brightness).rev().step_by(step_size) { |
| 86 | + controller.set_brightness(0, brightness); // Apply to channel 0 |
| 87 | + controller.render().unwrap(); |
| 88 | + std::thread::sleep(std::time::Duration::from_millis(30)); // Adjust speed |
| 89 | + } |
| 90 | + |
| 91 | + // Gradually increase brightness |
| 92 | + for brightness in (min_brightness..=max_brightness).step_by(step_size) { |
| 93 | + controller.set_brightness(0, brightness); // Apply to channel 0 |
| 94 | + controller.render().unwrap(); |
| 95 | + std::thread::sleep(std::time::Duration::from_millis(30)); // Adjust speed |
| 96 | + } |
| 97 | + } |
| 98 | + |
| 99 | + // Phase 4: Starry Night |
| 100 | + // Initialize a vector to track the state and duration of each LED |
| 101 | + let mut led_states = vec![(0, 0); led_count]; // (brightness, duration) |
| 102 | + |
| 103 | + for _ in 0..50 { // Run the animation for 50 iterations |
| 104 | + let leds = controller.leds_mut(0); |
| 105 | + |
| 106 | + // Update LED states based on their remaining duration |
| 107 | + for (i, led) in leds.iter_mut().enumerate() { |
| 108 | + if led_states[i].1 > 0 { |
| 109 | + // If the LED has remaining duration, decrease it |
| 110 | + led_states[i].1 -= 1; |
| 111 | + *led = [led_states[i].0, led_states[i].0, led_states[i].0, 0]; |
| 112 | + } else { |
| 113 | + // Turn off the LED if its duration has elapsed |
| 114 | + *led = [0, 0, 0, 0]; |
| 115 | + } |
| 116 | + } |
| 117 | + |
| 118 | + // Randomly select a new LED to light up |
| 119 | + let led_index = thread_rng().gen_range(0..led_count); |
| 120 | + // Use a weighted approach for brightness to favor lower values and more off LEDs |
| 121 | + let brightness = if thread_rng().gen_bool(0.3) { // 30% chance to light up an LED |
| 122 | + thread_rng().gen_range(1..=255) |
| 123 | + } else { |
| 124 | + 0 // Most LEDs stay off |
| 125 | + }; |
| 126 | + |
| 127 | + if brightness > 0 { |
| 128 | + // Light up the new LED and set its duration |
| 129 | + leds[led_index] = [brightness, brightness, brightness, 0]; |
| 130 | + led_states[led_index] = (brightness, 5); // Keep the LED on for 5 iterations |
| 131 | + } |
| 132 | + |
| 133 | + controller.render().unwrap(); |
| 134 | + std::thread::sleep(std::time::Duration::from_millis(100)); // Testing speed, adjust to 500ms for slower, calming effect |
| 135 | + } |
| 136 | + |
| 137 | + // Phase 5: Aurora Borealis |
| 138 | + for _ in 0..20 { // Run the animation for 50 iterations |
| 139 | + let leds = controller.leds_mut(0); |
| 140 | + for i in 0..led_count { |
| 141 | + let color = match i % 3 { |
| 142 | + 0 => [0, 255, 0, 0], // Green |
| 143 | + 1 => [0, 0, 255, 0], // Blue |
| 144 | + _ => [128, 0, 128, 0], // Purple |
| 145 | + }; |
| 146 | + leds[i] = color; |
| 147 | + } |
| 148 | + controller.render().unwrap(); |
| 149 | + std::thread::sleep(std::time::Duration::from_millis(200)); // Testing speed, adjust to 1000ms for slower, mesmerizing effect |
| 150 | + } |
| 151 | + |
| 152 | + // Phase 7: Sunrise Simulation |
| 153 | + for brightness in 1..=255 { |
| 154 | + let leds = controller.leds_mut(0); |
| 155 | + for led in leds.iter_mut() { |
| 156 | + *led = [(brightness / 2) as u8, (brightness / 4) as u8, 0, 0]; // Dark red to bright yellow |
| 157 | + } |
| 158 | + controller.render().unwrap(); |
| 159 | + std::thread::sleep(std::time::Duration::from_millis(50)); // Testing speed, adjust to 100ms for a slower sunrise effect |
| 160 | + } |
| 161 | +} |
0 commit comments