NeoPixelAnimation.ino 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. // NeoPixelAnimation
  2. // This example will randomly pick a new color for each pixel and animate
  3. // the current color to the new color over a random small amount of time, using
  4. // a randomly selected animation curve.
  5. // It will repeat this process once all pixels have finished the animation
  6. //
  7. // This will demonstrate the use of the NeoPixelAnimator extended time feature.
  8. // This feature allows for different time scales to be used, allowing slow extended
  9. // animations to be created.
  10. //
  11. // This will demonstrate the use of the NeoEase animation ease methods; that provide
  12. // simulated acceleration to the animations.
  13. //
  14. // It also includes platform specific code for Esp8266 that demonstrates easy
  15. // animation state and function definition inline. This is not available on AVR
  16. // Arduinos; but the AVR compatible code is also included for comparison.
  17. //
  18. // The example includes some serial output that you can follow along with as it
  19. // does the animation.
  20. //
  21. #include <NeoPixelBus.h>
  22. #include <NeoPixelAnimator.h>
  23. const uint16_t PixelCount = 4; // make sure to set this to the number of pixels in your strip
  24. const uint8_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
  25. NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
  26. // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use.
  27. // There are other Esp8266 alternative methods that provide more pin options, but also have
  28. // other side effects.
  29. //NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount);
  30. //
  31. // NeoEsp8266Uart800KbpsMethod uses GPI02 instead
  32. // NeoPixel animation time management object
  33. NeoPixelAnimator animations(PixelCount, NEO_CENTISECONDS);
  34. // create with enough animations to have one per pixel, depending on the animation
  35. // effect, you may need more or less.
  36. //
  37. // since the normal animation time range is only about 65 seconds, by passing timescale value
  38. // to the NeoPixelAnimator constructor we can increase the time range, but we also increase
  39. // the time between the animation updates.
  40. // NEO_CENTISECONDS will update the animations every 100th of a second rather than the default
  41. // of a 1000th of a second, but the time range will now extend from about 65 seconds to about
  42. // 10.9 minutes. But you must remember that the values passed to StartAnimations are now
  43. // in centiseconds.
  44. //
  45. // Possible values from 1 to 32768, and there some helpful constants defined as...
  46. // NEO_MILLISECONDS 1 // ~65 seconds max duration, ms updates
  47. // NEO_CENTISECONDS 10 // ~10.9 minutes max duration, centisecond updates
  48. // NEO_DECISECONDS 100 // ~1.8 hours max duration, decisecond updates
  49. // NEO_SECONDS 1000 // ~18.2 hours max duration, second updates
  50. // NEO_DECASECONDS 10000 // ~7.5 days, 10 second updates
  51. //
  52. #ifdef ARDUINO_ARCH_AVR
  53. // for AVR, you need to manage the state due to lack of STL/compiler support
  54. // for Esp8266 you can define the function using a lambda and state is created for you
  55. // see below for an example
  56. struct MyAnimationState
  57. {
  58. RgbColor StartingColor; // the color the animation starts at
  59. RgbColor EndingColor; // the color the animation will end at
  60. AnimEaseFunction Easeing; // the acceleration curve it will use
  61. };
  62. MyAnimationState animationState[PixelCount];
  63. // one entry per pixel to match the animation timing manager
  64. void AnimUpdate(const AnimationParam& param)
  65. {
  66. // first apply an easing (curve) to the animation
  67. // this simulates acceleration to the effect
  68. float progress = animationState[param.index].Easeing(param.progress);
  69. // this gets called for each animation on every time step
  70. // progress will start at 0.0 and end at 1.0
  71. // we use the blend function on the RgbColor to mix
  72. // color based on the progress given to us in the animation
  73. RgbColor updatedColor = RgbColor::LinearBlend(
  74. animationState[param.index].StartingColor,
  75. animationState[param.index].EndingColor,
  76. progress);
  77. // apply the color to the strip
  78. strip.SetPixelColor(param.index, updatedColor);
  79. }
  80. #endif
  81. void SetRandomSeed()
  82. {
  83. uint32_t seed;
  84. // random works best with a seed that can use 31 bits
  85. // analogRead on a unconnected pin tends toward less than four bits
  86. seed = analogRead(0);
  87. delay(1);
  88. for (int shifts = 3; shifts < 31; shifts += 3)
  89. {
  90. seed ^= analogRead(0) << shifts;
  91. delay(1);
  92. }
  93. // Serial.println(seed);
  94. randomSeed(seed);
  95. }
  96. void setup()
  97. {
  98. Serial.begin(115200);
  99. while (!Serial); // wait for serial attach
  100. strip.Begin();
  101. strip.Show();
  102. SetRandomSeed();
  103. // just pick some colors
  104. for (uint16_t pixel = 0; pixel < PixelCount; pixel++)
  105. {
  106. RgbColor color = RgbColor(random(255), random(255), random(255));
  107. strip.SetPixelColor(pixel, color);
  108. }
  109. Serial.println();
  110. Serial.println("Running...");
  111. }
  112. void SetupAnimationSet()
  113. {
  114. // setup some animations
  115. for (uint16_t pixel = 0; pixel < PixelCount; pixel++)
  116. {
  117. const uint8_t peak = 128;
  118. // pick a random duration of the animation for this pixel
  119. // since values are centiseconds, the range is 1 - 4 seconds
  120. uint16_t time = random(100, 400);
  121. // each animation starts with the color that was present
  122. RgbColor originalColor = strip.GetPixelColor(pixel);
  123. // and ends with a random color
  124. RgbColor targetColor = RgbColor(random(peak), random(peak), random(peak));
  125. // with the random ease function
  126. AnimEaseFunction easing;
  127. switch (random(3))
  128. {
  129. case 0:
  130. easing = NeoEase::CubicIn;
  131. break;
  132. case 1:
  133. easing = NeoEase::CubicOut;
  134. break;
  135. case 2:
  136. easing = NeoEase::QuadraticInOut;
  137. break;
  138. }
  139. #ifdef ARDUINO_ARCH_AVR
  140. // each animation starts with the color that was present
  141. animationState[pixel].StartingColor = originalColor;
  142. // and ends with a random color
  143. animationState[pixel].EndingColor = targetColor;
  144. // using the specific curve
  145. animationState[pixel].Easeing = easing;
  146. // now use the animation state we just calculated and start the animation
  147. // which will continue to run and call the update function until it completes
  148. animations.StartAnimation(pixel, time, AnimUpdate);
  149. #else
  150. // we must supply a function that will define the animation, in this example
  151. // we are using "lambda expression" to define the function inline, which gives
  152. // us an easy way to "capture" the originalColor and targetColor for the call back.
  153. //
  154. // this function will get called back when ever the animation needs to change
  155. // the state of the pixel, it will provide a animation progress value
  156. // from 0.0 (start of animation) to 1.0 (end of animation)
  157. //
  158. // we use this progress value to define how we want to animate in this case
  159. // we call RgbColor::LinearBlend which will return a color blended between
  160. // the values given, by the amount passed, hich is also a float value from 0.0-1.0.
  161. // then we set the color.
  162. //
  163. // There is no need for the MyAnimationState struct as the compiler takes care
  164. // of those details for us
  165. AnimUpdateCallback animUpdate = [=](const AnimationParam& param)
  166. {
  167. // progress will start at 0.0 and end at 1.0
  168. // we convert to the curve we want
  169. float progress = easing(param.progress);
  170. // use the curve value to apply to the animation
  171. RgbColor updatedColor = RgbColor::LinearBlend(originalColor, targetColor, progress);
  172. strip.SetPixelColor(pixel, updatedColor);
  173. };
  174. // now use the animation properties we just calculated and start the animation
  175. // which will continue to run and call the update function until it completes
  176. animations.StartAnimation(pixel, time, animUpdate);
  177. #endif
  178. }
  179. }
  180. void loop()
  181. {
  182. if (animations.IsAnimating())
  183. {
  184. // the normal loop just needs these two to run the active animations
  185. animations.UpdateAnimations();
  186. strip.Show();
  187. }
  188. else
  189. {
  190. Serial.println();
  191. Serial.println("Setup Next Set...");
  192. // example function that sets up some animations
  193. SetupAnimationSet();
  194. }
  195. }