NeoPixelFunLoop.ino 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // NeoPixelFunLoop
  2. // This example will move a trail of light around a series of pixels.
  3. // A ring formation of pixels looks best.
  4. // The trail will have a slowly fading tail.
  5. //
  6. // This will demonstrate the use of the NeoPixelAnimator.
  7. // It shows the advanced use an animation to control the modification and
  8. // starting of other animations.
  9. // It also shows the normal use of animating colors.
  10. // It also demonstrates the ability to share an animation channel rather than
  11. // hard code them to pixels.
  12. //
  13. #include <NeoPixelBus.h>
  14. #include <NeoPixelAnimator.h>
  15. const uint16_t PixelCount = 16; // make sure to set this to the number of pixels in your strip
  16. const uint16_t PixelPin = 2; // make sure to set this to the correct pin, ignored for Esp8266
  17. const uint16_t AnimCount = PixelCount / 5 * 2 + 1; // we only need enough animations for the tail and one extra
  18. const uint16_t PixelFadeDuration = 300; // third of a second
  19. // one second divide by the number of pixels = loop once a second
  20. const uint16_t NextPixelMoveDuration = 1000 / PixelCount; // how fast we move through the pixels
  21. NeoGamma<NeoGammaTableMethod> colorGamma; // for any fade animations, best to correct gamma
  22. NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount, PixelPin);
  23. // For Esp8266, the Pin is omitted and it uses GPIO3 due to DMA hardware use.
  24. // There are other Esp8266 alternative methods that provide more pin options, but also have
  25. // other side effects.
  26. //NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(PixelCount);
  27. //
  28. // NeoEsp8266Uart800KbpsMethod uses GPI02 instead
  29. // what is stored for state is specific to the need, in this case, the colors and
  30. // the pixel to animate;
  31. // basically what ever you need inside the animation update function
  32. struct MyAnimationState
  33. {
  34. RgbColor StartingColor;
  35. RgbColor EndingColor;
  36. uint16_t IndexPixel; // which pixel this animation is effecting
  37. };
  38. NeoPixelAnimator animations(AnimCount); // NeoPixel animation management object
  39. MyAnimationState animationState[AnimCount];
  40. uint16_t frontPixel = 0; // the front of the loop
  41. RgbColor frontColor; // the color at the front of the loop
  42. void SetRandomSeed()
  43. {
  44. uint32_t seed;
  45. // random works best with a seed that can use 31 bits
  46. // analogRead on a unconnected pin tends toward less than four bits
  47. seed = analogRead(0);
  48. delay(1);
  49. for (int shifts = 3; shifts < 31; shifts += 3)
  50. {
  51. seed ^= analogRead(0) << shifts;
  52. delay(1);
  53. }
  54. // Serial.println(seed);
  55. randomSeed(seed);
  56. }
  57. void FadeOutAnimUpdate(const AnimationParam& param)
  58. {
  59. // this gets called for each animation on every time step
  60. // progress will start at 0.0 and end at 1.0
  61. // we use the blend function on the RgbColor to mix
  62. // color based on the progress given to us in the animation
  63. RgbColor updatedColor = RgbColor::LinearBlend(
  64. animationState[param.index].StartingColor,
  65. animationState[param.index].EndingColor,
  66. param.progress);
  67. // apply the color to the strip
  68. strip.SetPixelColor(animationState[param.index].IndexPixel,
  69. colorGamma.Correct(updatedColor));
  70. }
  71. void LoopAnimUpdate(const AnimationParam& param)
  72. {
  73. // wait for this animation to complete,
  74. // we are using it as a timer of sorts
  75. if (param.state == AnimationState_Completed)
  76. {
  77. // done, time to restart this position tracking animation/timer
  78. animations.RestartAnimation(param.index);
  79. // pick the next pixel inline to start animating
  80. //
  81. frontPixel = (frontPixel + 1) % PixelCount; // increment and wrap
  82. if (frontPixel == 0)
  83. {
  84. // we looped, lets pick a new front color
  85. frontColor = HslColor(random(360) / 360.0f, 1.0f, 0.25f);
  86. }
  87. uint16_t indexAnim;
  88. // do we have an animation available to use to animate the next front pixel?
  89. // if you see skipping, then either you are going to fast or need to increase
  90. // the number of animation channels
  91. if (animations.NextAvailableAnimation(&indexAnim, 1))
  92. {
  93. animationState[indexAnim].StartingColor = frontColor;
  94. animationState[indexAnim].EndingColor = RgbColor(0, 0, 0);
  95. animationState[indexAnim].IndexPixel = frontPixel;
  96. animations.StartAnimation(indexAnim, PixelFadeDuration, FadeOutAnimUpdate);
  97. }
  98. }
  99. }
  100. void setup()
  101. {
  102. strip.Begin();
  103. strip.Show();
  104. SetRandomSeed();
  105. // we use the index 0 animation to time how often we move to the next
  106. // pixel in the strip
  107. animations.StartAnimation(0, NextPixelMoveDuration, LoopAnimUpdate);
  108. }
  109. void loop()
  110. {
  111. // this is all that is needed to keep it running
  112. // and avoiding using delay() is always a good thing for
  113. // any timing related routines
  114. animations.UpdateAnimations();
  115. strip.Show();
  116. }