Happosay

Iron Man Repulsor

Apr 8th, 2021
638
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 17.41 KB | None | 0 0
  1. /*****************************************************************************
  2. ** COPYRIGHT (C) 2014-2015, ADVANCER TECHNOLOGIES, ALL RIGHTS RESERVED.
  3. *****************************************************************************/
  4.  
  5. //***********************************************
  6. // Muscle Controlled NeoPixel Repulsor
  7. //
  8. // Developed by Brian E. Kaminski - Advancer Technologies,
  9. // http://www.AdvancerTechnologies.com
  10. //
  11. // Uses code from Lilypad MP3 Player "Trigger" example from
  12. // SparkFun Electronics (indicated below).
  13. //
  14. // Uses the SdFat library by William Greiman, which is supplied
  15. // with this archive, or download from http://code.google.com/p/sdfatlib/
  16. //
  17. // Uses the SFEMP3Shield library by Bill Porter, which is supplied
  18. // with this archive, or download from http://www.billporter.info/
  19. //
  20. // License: CC BY-SA 3.0 https://creativecommons.org/licenses/by-sa/3.0/
  21. //
  22. // Revision history:
  23. // 1.0 initial release BEK 03Jan2015
  24. //***********************************************
  25.  
  26. //***************************************************************************
  27. // Example code from Trigger.ino a sketch for Lilypad MP3 Player
  28. //***************************************************************************
  29. // We'll need a few libraries to access all this hardware:
  30. #include <SPI.h> // To talk to the SD card and MP3 chip
  31. #include <SdFat.h> // SD card file system
  32. #include <SFEMP3Shield.h> // MP3 decoder chip
  33. #include <Adafruit_NeoPixel.h> // NeoPixel library
  34.  
  35. // Constants for the trigger input pins, which we'll place
  36. // in an array for convenience:
  37. const int TRIG1 = A0;
  38. const int TRIG2 = A4;
  39. const int TRIG3 = A5;
  40. const int TRIG4 = 1;
  41. const int TRIG5 = 0;
  42. int trigger[5] = {TRIG1,TRIG2,TRIG3,TRIG4,TRIG5};
  43.  
  44. // And a few outputs we'll be using:
  45. const int ROT_LEDR = 10; // Red LED in rotary encoder (optional)
  46. const int EN_GPIO1 = A2; // Amp enable + MIDI/MP3 mode select
  47. const int SD_CS = 9; // Chip Select for SD card
  48.  
  49. // Create library objects:
  50. SFEMP3Shield MP3player;
  51. SdFat sd;
  52. boolean interrupt = true; // set triggered file to be able to be interrupted.
  53. boolean interruptself = true; // set triggered file to interrupt itself.
  54.  
  55.  
  56. // We'll store the five filenames as arrays of characters.
  57. // "Short" (8.3) filenames are used, followed by a null character.
  58. char filename[9][13];
  59. //***************************************************************************
  60.  
  61. //0 PWRDOWN / Muscle Sensor Trigger
  62. //1 Trigger 2
  63. //2 Trigger 3
  64. //3 Trigger 4
  65. //4 Trigger 5
  66. //5 IMPORT
  67. //6 ONLINE
  68. //7 PWRUP
  69. //8 FIRE
  70.  
  71. // We need to setup a muscle sensor reading value which will be used to tell
  72. // at what level of muscle flexion we want the repulsor to be triggered.
  73. // Adjust higher to make less sensative, adjust lower to make more sensitive
  74. int iThreshold = 200; // Value to trigger repulsor power up
  75. const int NeoPixelPin = 5; // pin connected to the Glove
  76. bool bPreviousState = false;
  77. bool firstLoop = true;
  78. long POWERUP_SFX_LENGTH = 1080; //ms
  79. long POWERDWN_SFX_LENGTH = 1250; //ms
  80. long FIRE_SFX_LENGTH = 1828; //ms
  81. long LED_MAX = 255;
  82. long brightnessValue = 1;
  83.  
  84. Adafruit_NeoPixel strip = Adafruit_NeoPixel(12, NeoPixelPin, NEO_GRB + NEO_KHZ800);
  85.  
  86.  
  87. //----------------------------------------------------------------------------
  88. //
  89. /// powerUp
  90. ///
  91. /// @desc Plays the repulsor power up sound effect while reading the muscle sensor.
  92. /// The sound effect will be interupted if the muscle sensor signal drops below
  93. /// the threshold. This allows for rapid firing of the repulsor.
  94. ///
  95. //----------------------------------------------------------------------------
  96. void powerUp()
  97. {
  98. brightnessValue = 1;
  99. MP3player.playMP3(filename[7]);
  100.  
  101. // setup fade in variables
  102. long currTime = millis();
  103. long prevTime = currTime;
  104. long brightnessStart = brightnessValue;
  105. long brightnessEnd = 20;
  106. long timeDivision = POWERUP_SFX_LENGTH/(abs(brightnessEnd-brightnessStart)); // clip length in milliseconds divided by the desired LED value (25% brightness)
  107.  
  108. while (MP3player.isPlaying())
  109. {
  110. // fade in from min to max over length of clip:
  111. currTime = millis();
  112. if(currTime-prevTime >= timeDivision)
  113. {
  114. brightnessValue +=1;
  115.  
  116. // update glove LEDs
  117. if(brightnessValue <= brightnessEnd)
  118. {
  119. strip.setBrightness(brightnessValue);
  120. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(127, 0, 0));}
  121. strip.show();
  122. }
  123.  
  124. prevTime = currTime;
  125. }
  126.  
  127. if(interrupt)
  128. {
  129. boolean bState = ReadMuscleSensor(TRIG1);
  130. if(!bState)
  131. MP3player.stopTrack();
  132.  
  133. ReadMP3PlayerTriggers();
  134. }
  135. }
  136. }
  137.  
  138. //----------------------------------------------------------------------------
  139. //
  140. /// fire
  141. ///
  142. /// @desc Plays the repulsor firing sound effect while reading the muscle sensor.
  143. /// The sound effect will be interupted if the muscle sensor signal goes above
  144. /// the threshold (meaning another fire sequence is being initiated. If the firing
  145. /// sound effect is not interupted, the repulsor power down sound effect is played.
  146. /// The power down sound effect can also be interupted. This allows for rapid firing
  147. /// of the repulsor.
  148. ///
  149. //----------------------------------------------------------------------------
  150. void fire()
  151. {
  152. //long brightnessValue = LED_MAX; // full brightness
  153. boolean bState = false;
  154.  
  155. MP3player.playMP3(filename[8]);
  156.  
  157. int colorValue = 0;
  158. // turn on the glove LEDs
  159. while(brightnessValue < LED_MAX)
  160. {
  161. brightnessValue++;
  162. strip.setBrightness(brightnessValue);
  163. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(127, colorValue, colorValue));}
  164. strip.show();
  165. if(colorValue < 127)
  166. colorValue++;
  167. }
  168.  
  169. // fade out over length of clip:
  170. while (MP3player.isPlaying())
  171. {
  172. if(brightnessValue > 20)
  173. brightnessValue--;
  174. strip.setBrightness(brightnessValue);
  175. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(127, colorValue, colorValue));}
  176. strip.show();
  177. if(colorValue > 0)
  178. colorValue--;
  179.  
  180. if(interrupt)
  181. {
  182. bState = ReadMuscleSensor(TRIG1);
  183. if(bState)
  184. MP3player.stopTrack();
  185.  
  186. ReadMP3PlayerTriggers();
  187. }
  188. }
  189.  
  190. if(!bState)
  191. {
  192. // now power down
  193. MP3player.playMP3(filename[0]);
  194.  
  195. //setup fade out variables
  196. long currTime = millis();
  197. long prevTime = currTime;
  198. long brightnessStart = brightnessValue;
  199. long brightnessEnd = 1;
  200. long timeDivision = POWERDWN_SFX_LENGTH/(abs(brightnessEnd-brightnessStart)); // clip length in milliseconds divided by the desired LED brightness value
  201.  
  202. while (MP3player.isPlaying())
  203. {
  204. // fade out from max to min over length of clip:
  205. currTime = millis();
  206. if(currTime-prevTime >= timeDivision)
  207. {
  208. if(brightnessValue > brightnessEnd)
  209. brightnessValue--;
  210.  
  211. if(colorValue > 0)
  212. colorValue--;
  213.  
  214. // update glove LEDs
  215. strip.setBrightness(brightnessValue);
  216. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(127, colorValue, colorValue));}
  217. strip.show();
  218.  
  219. prevTime = currTime;
  220. }
  221.  
  222. if(interrupt)
  223. {
  224. bState = ReadMuscleSensor(TRIG1);
  225. if(bState)
  226. MP3player.stopTrack();
  227.  
  228. ReadMP3PlayerTriggers();
  229. }
  230. }
  231. }
  232.  
  233. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, 0);}
  234. strip.show(); // turn off the glove LEDs
  235. }
  236.  
  237. //-----------------------------------------------------------------------------------------------------------------------------------
  238. //
  239. /// ReadMuscleSensor
  240. ///
  241. /// @desc This method reads each game button's state. If a button is pressed, it will change the button's
  242. /// state to true. If not, it will change the button's state to false.
  243. ///
  244. /// @param iMuscleSensorPin // Analog pin reading muscle sensor output
  245. ///
  246. /// @return true if the muscle sensor value is greater than the threshold
  247. //-----------------------------------------------------------------------------------------------------------------------------------
  248. bool ReadMuscleSensor(int iMuscleSensorPin)
  249. {
  250. int val = analogRead(iMuscleSensorPin);
  251.  
  252. if(val >= iThreshold)
  253. return true;
  254. else
  255. return false;
  256. }
  257.  
  258. //***************************************************************************
  259. // Example code from Trigger.ino a sketch for Lilypad MP3 Player
  260. //***************************************************************************
  261. void SetupMP3Player()
  262. {
  263. byte result;
  264. // The board uses a single I/O pin to select the
  265. // mode the MP3 chip will start up in (MP3 or MIDI),
  266. // and to enable/disable the amplifier chip:
  267. pinMode(EN_GPIO1,OUTPUT);
  268. digitalWrite(EN_GPIO1,LOW); // MP3 mode / amp off
  269.  
  270. result = sd.begin(SD_CS, SPI_HALF_SPEED); // 1 for success
  271.  
  272. if (result != 1) // Problem initializing the SD card
  273. errorBlink(1); // Halt forever, blink LED if present.
  274.  
  275. // Start up the MP3 library
  276. result = MP3player.begin(); // 0 or 6 for success
  277.  
  278. // Check the result, see the library readme for error codes.
  279. if ((result != 0) && (result != 6)) // Problem starting up
  280. errorBlink(result); // Halt forever, blink red LED if present.
  281.  
  282. FindAudioFilenames();
  283.  
  284. // Set the VS1053 volume. 0 is loudest, 255 is lowest (off):
  285. MP3player.setVolume(0,255);
  286.  
  287. // Turn on the amplifier chip:
  288. digitalWrite(EN_GPIO1,HIGH);
  289. }
  290.  
  291. void FindAudioFilenames()
  292. {
  293. SdFile file;
  294. char tempfilename[13];
  295. int index;
  296. // Now we'll access the SD card to look for any (audio) files
  297. // starting with the characters '1' to '5':
  298.  
  299. // Start at the first file in root and step through all of them:
  300. sd.chdir("/");
  301. while (file.openNext(sd.vwd(),O_READ))
  302. {
  303. // get filename
  304. file.getName(tempfilename, 13);
  305.  
  306. // Does the filename start with char '1' through '10'?
  307. if (tempfilename[0] >= '0' && tempfilename[0] <= '9')
  308. {
  309. // Yes! subtract char '1' to get an index of 0 through 4.
  310. index = tempfilename[0] - '0';
  311.  
  312. // Copy the data to our filename array.
  313. strcpy(filename[index],tempfilename);
  314. }
  315. file.close();
  316. }
  317. }
  318.  
  319. void ReadMP3PlayerTriggers()
  320. {
  321. int t; // current trigger
  322. static int last_t; // previous (playing) trigger
  323. int x;
  324. byte result;
  325.  
  326. // Step through the trigger inputs, looking for LOW signals.
  327. // The internal pullup resistors will keep them HIGH when
  328. // there is no connection to the input. Only check triggers 2-5.
  329. for(t = 2; t <= 5; t++)
  330. {
  331. // The trigger pins are stored in the inputs[] array.
  332. // Read the pin and check if it is LOW (triggered).
  333. if (digitalRead(trigger[t-1]) == LOW)
  334. {
  335. // Wait for trigger to return high for a solid 50ms
  336. // (necessary to avoid switch bounce on T2 and T3
  337. // since we need those free for I2C control of the
  338. // amplifier)
  339. x = 0;
  340. while(x < 50)
  341. {
  342. if (digitalRead(trigger[t-1]) == HIGH) {x++;}
  343. else {x = 0;}
  344.  
  345. delay(1);
  346. }
  347.  
  348. // If a file is already playing, and we've chosen to
  349. // allow playback to be interrupted by a new trigger,
  350. // stop the playback before playing the new file.
  351. if (interrupt && MP3player.isPlaying() && ((t != last_t) || interruptself))
  352. {
  353. MP3player.stopTrack();
  354. }
  355.  
  356. // Play the filename associated with the trigger number.
  357. // (If a file is already playing, this command will fail
  358. // with error #2).
  359. result = MP3player.playMP3(filename[t-1]);
  360. if (result == 0) last_t = t; // Save playing trigger
  361.  
  362. }
  363. }
  364. }
  365.  
  366. void errorBlink(int blinks)
  367. {
  368. // The following function will blink the repulsor a given number
  369. // of times and repeat forever. This is so you can see any startup
  370. // error codes without having to use the serial monitor window.
  371.  
  372. int x;
  373.  
  374. while(true) // Loop forever
  375. {
  376. for (x=0; x < blinks; x++) // Blink the given number of times
  377. {
  378. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(127, 0, 0));}
  379. strip.show(); // Turn LED ON
  380. delay(250);
  381. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, 0);}
  382. strip.show(); // Turn LED OFF
  383. delay(250);
  384. }
  385. delay(1500); // Longer pause between blink-groups
  386. }
  387. }
  388.  
  389.  
  390. void IncrementAndDirection(int &value, const int minValue, const int maxValue,
  391. const int incValue, bool &forward )
  392. {
  393. if(forward && value >= maxValue)
  394. {
  395. value = maxValue;
  396. forward = !forward;
  397. }
  398. else if(!forward && value <= minValue)
  399. {
  400. value = minValue;
  401. forward = !forward;
  402. }
  403.  
  404. if(forward)
  405. value = value + incValue;
  406. else
  407. value = value - incValue;
  408. }
  409.  
  410. // Input a value 0 to 255 to get a color value.
  411. // The colours are a transition r - g - b - back to r.
  412. uint32_t Wheel(byte WheelPos) {
  413. WheelPos = 255 - WheelPos;
  414. if(WheelPos < 85) {
  415. return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  416. }
  417. else if(WheelPos < 170) {
  418. WheelPos -= 85;
  419. return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  420. }
  421. else {
  422. WheelPos -= 170;
  423. return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  424. }
  425. }
  426.  
  427.  
  428. void setup()
  429. {
  430. //***************************************************************************
  431. // Example code from Trigger.ino a sketch for Lilypad MP3 Player
  432. //***************************************************************************
  433. int x, index;
  434. SdFile file;
  435. byte result;
  436. char tempfilename[13];
  437.  
  438. // Setup the five trigger pins
  439. for (x = 0; x <= 4; x++)
  440. {
  441. pinMode(trigger[x],INPUT);
  442. if(x > 0)
  443. digitalWrite(trigger[x],HIGH);
  444. }
  445. //***************************************************************************
  446.  
  447. // Setup the repulsor LED PWM pin
  448. pinMode(NeoPixelPin, OUTPUT);
  449.  
  450. //
  451. SetupMP3Player();
  452.  
  453. delay(20);
  454. }
  455.  
  456. void loop()
  457. {
  458. if(firstLoop)
  459. {
  460. // First time through we want the JARVIS SFXs to play
  461. // Play the JARVIS "Importing Preferences" SFX
  462. MP3player.playMP3(filename[5]);
  463.  
  464. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, 0);}
  465. int pixelIndex = 0;
  466. int colorIndex = 0;
  467. while (MP3player.isPlaying())
  468. {
  469. // This code creates a fluctuating comet that travels around
  470. // the NeoPixel ring varying brightness and color
  471. int numCluster = 3; //change this value to set the comet tail length
  472. bool fwdColor = true;
  473. const int colorInc = 5;
  474.  
  475. // turn on leading NeoPixel
  476. strip.setBrightness(20);
  477. strip.setPixelColor(pixelIndex, Wheel(colorIndex % 255));
  478. // turn off trailing NeoPixels
  479. if(pixelIndex-numCluster >= 0)
  480. strip.setPixelColor(pixelIndex-numCluster, 0);
  481. else
  482. strip.setPixelColor(strip.numPixels() + (pixelIndex-numCluster), 0);
  483. strip.show();
  484.  
  485. IncrementAndDirection(colorIndex, 0, 255, 5, fwdColor); // color: min=0, max=255, increment=5
  486. pixelIndex++;
  487.  
  488. if(pixelIndex > strip.numPixels())
  489. pixelIndex = 0;
  490.  
  491. delay(50);
  492. }
  493.  
  494. // turn all NeoPixels off
  495. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, 0);}
  496.  
  497. //Play the JARVIS "Online and Ready" SFX
  498. MP3player.playMP3(filename[6]);
  499.  
  500. // color wipe green
  501. int brightIndex = 20;
  502. strip.setBrightness(brightIndex);
  503. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(0, 127, 0));strip.show();delay(50);}
  504.  
  505. bool fwdBright = false;
  506. while (MP3player.isPlaying())
  507. {
  508. strip.setBrightness(brightIndex);
  509. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, strip.Color(0, 127, 0));}
  510. strip.show();
  511.  
  512. IncrementAndDirection(brightIndex, 3, 20, 1, fwdBright); // brightness: min=1, max=255
  513. delay(25);
  514. }
  515. for(int i=0; i<strip.numPixels(); i++) {strip.setPixelColor(i, 0);strip.show();delay(50);}
  516. firstLoop = false;
  517. }
  518.  
  519. // Read the muscle sensor value
  520. boolean bState = ReadMuscleSensor(TRIG1);
  521.  
  522. // If the muscle sensor value is over the threshold (bState = true)
  523. // and the previous state was below the threshold, then play the
  524. // power up SFX. If the muscle sensor goes back below the threshold,
  525. // then play the fire SFX and turn the repulsor on while the SFX is
  526. // playing and the power down SFX afterwards.
  527. if(bState && !bPreviousState)
  528. {
  529. //digitalWrite(NeoPixelPin, HIGH); // Turn the repulsor on when flexing
  530. powerUp(); // Play the Repulsor Power Up SFX
  531. }
  532. else if(!bState && bPreviousState)
  533. {
  534. //digitalWrite(NeoPixelPin, LOW); // Turn the repulsor off when relaxed
  535. fire(); // Play the Repulsor Firing and Power Down SFXs
  536. }
  537.  
  538. // Store state for next loop
  539. bPreviousState = bState;
  540.  
  541. // Check to see
  542. ReadMP3PlayerTriggers();
  543.  
  544. delay(50);
  545. }
  546. //***************************************************************************
Add Comment
Please, Sign In to add comment