RSeries astromech firmware
FireStrip.h
Go to the documentation of this file.
1 #ifndef FireStrip_h
2 #define FireStrip_h
3 
4 #include "ReelTwo.h"
5 #include "core/LEDPixelEngine.h"
6 #include "core/SetupEvent.h"
7 #include "core/AnimatedEvent.h"
8 #include "core/CommandEvent.h"
9 
10 #if USE_LEDLIB == 0
11 template<uint8_t DATA_PIN, uint32_t RGB_ORDER, uint16_t NUM_LEDS>
12 class FireStripPCB : public FastLED_NeoPixel<NUM_LEDS, DATA_PIN, RGB_ORDER>
13 {
14 public:
16 };
17 #define USE_FIRESTRIP_TEMPLATE 1
18 #elif USE_LEDLIB == 1
19 template<uint8_t DATA_PIN, uint32_t RGB_ORDER, uint16_t NUM_LEDS>
20 class FireStripPCB : public Adafruit_NeoPixel
21 {
22 public:
23  FireStripPCB() :
24  Adafruit_NeoPixel(NUM_LEDS, DATA_PIN, RGB_ORDER)
25  {
26  }
27 };
28 #else
29  #error Unsupported
30 #endif
31 
48 #if USE_FIRESTRIP_TEMPLATE
49 template<uint8_t DATA_PIN, uint32_t RGB_ORDER = GRB, uint16_t NUM_LEDS = 8>
50 class FireStrip :
51  private FireStripPCB<DATA_PIN, RGB_ORDER, NUM_LEDS>,
53 #else
54 class FireStrip :
55  private Adafruit_NeoPixel,
57 #endif
58 {
59 public:
60 #if USE_FIRESTRIP_TEMPLATE
61  FireStrip(const int id = 0) :
62  fID(id)
63  {
64  }
65 #else
66  enum PixelType
67  {
68  kRGBW = NEO_GRBW + NEO_KHZ800,
69  kRGB = NEO_GRB + NEO_KHZ800
70  };
71 
72  FireStrip(const byte pin, PixelType type = kRGBW, const int id = 0) :
73  Adafruit_NeoPixel(NUM_LEDS, pin, type),
74  fID(id)
75  {
76  }
77 #endif
78 
82  inline int getID()
83  {
84  return fID;
85  }
86 
90  void spark(uint16_t duration)
91  {
92  fEffectType = kSparkEffect;
93  fEffectEnd = millis() + duration;
94  fNextTime = 0;
95  }
96 
100  void burn(uint16_t duration)
101  {
102  fEffectType = kFireEffect;
103  fEffectEnd = millis() + duration;
104  fNextTime = 0;
105  }
106 
110  void off()
111  {
112  fEffectEnd = 0;
113  fFlipFlop = false;
114  fEffectType = kNoEffect;
115  for (unsigned i = 0; i < NUM_LEDS; i++)
116  setPixelColor(i, 0);
117  dirty();
118  }
119 
123  virtual void setup() override
124  {
126  setBrightness(BRIGHT);
127  dirty();
128  }
129 
133  virtual void animate() override
134  {
135  uint32_t currentTime = millis();
136  switch (fEffectType)
137  {
138  case kNoEffect:
139  return;
140  case kSparkEffect:
141  if (currentTime > fNextTime)
142  {
143  if (!fFlipFlop)
144  {
145  setAll(0x33+random(0x77), 0x33+random(0x77), 0xFF);
146  }
147  else
148  {
149  setAll(0, 0, 0);
150  }
151  fNextTime = currentTime + 10+(10*random(2,5));
152  fFlipFlop = !fFlipFlop;
153  }
154  break;
155  case kFireEffect:
156  if (currentTime > fNextTime)
157  {
158  fire(55, 120);
159  fNextTime = currentTime + 10+(10*random(2,5));
160  fFlipFlop = !fFlipFlop;
161  }
162  break;
163  }
164  if (currentTime > fEffectEnd)
165  off();
166 
167  if (fDirty)
168  {
170  show();
172  fDirty = false;
173  }
174  }
175 
179  virtual void handleCommand(const char* cmd) override
180  {
181  if (*cmd++ == 'F' && *cmd++ == 'S')
182  {
183  switch (cmd[0])
184  {
185  case 'O':
186  if (cmd[1] == 'F' && cmd[2] == 'F' && cmd[3] == '\0')
187  {
188  off();
189  }
190  break;
191  case '0':
192  off();
193  break;
194 
195  case '1':
196  spark(atoi(&cmd[1]));
197  break;
198  case '2':
199  burn(atoi(&cmd[1]));
200  break;
201  }
202  }
203  }
204 
205  inline void dirty()
206  {
207  fDirty = true;
208  }
209 
210 private:
211 #if USE_FIRESTRIP_TEMPLATE
212  void begin()
213  {
215  }
216 
217  void show()
218  {
220  }
221 
222  void setPixelColor(uint16_t n, uint32_t c)
223  {
225  }
226 
227  void setPixelColor(uint16_t n, uint8_t r, uint8_t g, uint8_t b)
228  {
230  }
231 #else
232  constexpr static int NUM_LEDS = 8;
233 #endif
234  enum
235  {
236  BRIGHT = 100
237  };
238  enum
239  {
240  kNoEffect,
241  kSparkEffect,
242  kFireEffect,
243  };
244  int fID;
245  int fEffectType = kNoEffect;
246  bool fFlipFlop;
247  bool fDirty;
248  uint32_t fEffectEnd;
249  uint32_t fNextTime;
250 
251  static long atoi(const char* s)
252  {
253  long int val = 0;
254  while (*s >= '0' && *s <= '9')
255  {
256  val = val * 10 + (*s++ - '0');
257  }
258  return val;
259  }
260 
261  void setAll(byte red, byte green, byte blue)
262  {
263  for (unsigned i = 0; i < NUM_LEDS; i++)
264  {
265  setPixelColor(i, red, green, blue);
266  }
267  dirty();
268  }
269 
270  void fire(int Cooling, unsigned Sparking)
271  {
272  static byte heat[NUM_LEDS];
273  int cooldown;
274 
275  // Step 1. Cool down every cell a little
276  for (int i = 0; i < NUM_LEDS; i++)
277  {
278  cooldown = random(0, ((Cooling * 10) / NUM_LEDS) + 2);
279 
280  if (cooldown>heat[i])
281  {
282  heat[i] = 0;
283  }
284  else
285  {
286  heat[i] = heat[i] - cooldown;
287  }
288  }
289 
290  // Step 2. Heat from each cell drifts 'up' and diffuses a little
291  for (int k= NUM_LEDS - 1; k >= 2; k--)
292  {
293  heat[k] = (heat[k - 1] + heat[k - 2] + heat[k - 2]) / 3;
294  }
295 
296  // Step 3. Randomly ignite new 'sparks' near the bottom
297  if (random(255) < Sparking)
298  {
299  int y = random(7);
300  heat[y] = heat[y] + random(160,255);
301  }
302 
303  // Step 4. Convert heat to LED colors
304  for (int j = 0; j < NUM_LEDS; j++)
305  {
306  setPixelHeatColor(j, heat[j]);
307  }
308 
309  dirty();
310  }
311 
312  void setPixelHeatColor(int pixel, byte temperature)
313  {
314  // Scale 'heat' down from 0-255 to 0-191
315  byte t192 = round((temperature/255.0)*191);
316 
317  // calculate ramp up from
318  byte heatramp = t192 & 0x3F; // 0..63
319  heatramp <<= 2; // scale up to 0..252
320 
321  // figure out which third of the spectrum we're in:
322  if (t192 > 0x80)
323  {
324  // hottest
325  setPixelColor(pixel, 255, 255, heatramp);
326  }
327  else if (t192 > 0x40)
328  {
329  // middle
330  setPixelColor(pixel, 255, heatramp, 0);
331  }
332  else
333  {
334  // coolest
335  setPixelColor(pixel, heatramp, 0, 0);
336  }
337  }
338 };
339 
340 #endif
LEDPixelEngine.h
TEENSY_PROP_NEOPIXEL_SETUP
#define TEENSY_PROP_NEOPIXEL_SETUP()
Definition: ReelTwo.h:163
FireStrip::off
void off()
Turn of all LEDs.
Definition: FireStrip.h:110
FireStripPCB
Definition: FireStrip.h:12
FireStrip
Animates electrical sparks and then fire.
Definition: FireStrip.h:50
FireStrip::dirty
void dirty()
Definition: FireStrip.h:205
CommandEvent
Base class for all command enabled devices. CommandEvent::handleCommand() is called for each device e...
Definition: CommandEvent.h:17
ReelTwo.h
SetupEvent.h
AnimatedEvent
Base class for all animated devices. AnimatedEvent::animate() is called for each device once through ...
Definition: AnimatedEvent.h:18
FireStrip::FireStrip
FireStrip(const int id=0)
Definition: FireStrip.h:61
SetupEvent
Base class for all devices that require setup that cannot happen in the constructor....
Definition: SetupEvent.h:15
AnimatedEvent.h
FireStrip::handleCommand
virtual void handleCommand(const char *cmd) override
FireStrip Commands start with 'FS'.
Definition: FireStrip.h:179
FireStrip::burn
void burn(uint16_t duration)
Fire animation for the specified millisecond duration.
Definition: FireStrip.h:100
TEENSY_PROP_NEOPIXEL_BEGIN
#define TEENSY_PROP_NEOPIXEL_BEGIN()
Definition: ReelTwo.h:166
FireStrip::setup
virtual void setup() override
Configures the NeoPixel ring and centers the holoprojector if servos have been assigned.
Definition: FireStrip.h:123
FireStripPCB::FireStripPCB
FireStripPCB()
Definition: FireStrip.h:15
FireStrip::animate
virtual void animate() override
Runs through one frame of animation for this FireStrip instance.
Definition: FireStrip.h:133
FireStrip::getID
int getID()
Definition: FireStrip.h:82
CommandEvent.h
FireStrip::spark
void spark(uint16_t duration)
Spark animation for the specified millisecond duration.
Definition: FireStrip.h:90
TEENSY_PROP_NEOPIXEL_END
#define TEENSY_PROP_NEOPIXEL_END()
Definition: ReelTwo.h:169