I have created code for a treasure chest which randomly changes LED colors, creates a periodic twinkle across the LEDs, and plays a random mp3 track from a folder of mp3 tracks. This code must operate with a switch, that plays back these effects when the switch is high and shuts them off when the switch is low. From earlier versions of my code, I have optimized the code to enable a random track to be played. The base random play function of the dfPlayer does not play a random track, always beginning with track 1 and then randomizes tracks when playing the next track. It was more desirable to have the treasure chest play a random track when initially opened.
Early in my development, before random track playback, the code ran quickly such that the change from low to high and high to low resulted in a closer to instantaneous effect. When you opened the treasure box, the lights were on and twinkling before you could actually see the lights as example.
The time it takes to lift the lid to an open position where you could see the lights is about 250 milliseconds. My current code is running at approximately 750 - 1250 milliseconds before the LEDs are lit, hence the lid can be fully open when the lights turn on.
As I am fairly new to this, I would appreciate guidance on how I might optimize the code or change my coding approach to accomplish the desired effects in a faster time-frame. I have left the print lines and the comments within the code for my development reminders and testing. I have tried removing these to see if the speed improves, but do not see any substantial improvement. I do plan to remove these when my code is final.
#include <Adafruit_NeoPixel.h>
// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN 13 // change to 7 for beta chest
// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 24
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
//DF Player configuration
#include "Arduino.h"
#include "SoftwareSerial.h"
#include "DFRobotDFPlayerMini.h"
SoftwareSerial mySoftwareSerial(10, 9); // RX, TX - change to 10, 9 for beta chest, 11, 10 for v1 pcb
DFRobotDFPlayerMini myDFPlayer;
void printDetail(uint8_t type, int value);
//Global variables
long n;
long timing;
long mix;
long count = 0;
long track;
uint32_t set;
int i;
long twinkle;
int inputPin = 2;
int buttonState;
int pauseState = 0;
int lastState = LOW; // the previous state from the input pin
int val; // the current reading from the input pin
void setup() {
// put your setup code here, to run once:
pinMode(inputPin, INPUT);
digitalWrite(inputPin, HIGH);
Serial.begin(115200); //debug using serial monitor
randomSeed(analogRead(A0)); //necessary to get randomization
mySoftwareSerial.begin(9600);
Serial.println();
Serial.println(F("DFRobot DFPlayer Mini Demo"));
Serial.println(F("Initializing DFPlayer ... (May take 3~5 seconds)"));
buttonState = digitalRead(inputPin); // store initial button state (should be high)
Serial.print("Initial button state is ");
Serial.println(buttonState);
if (!myDFPlayer.begin(mySoftwareSerial)) { //Use softwareSerial to communicate with mp3.
Serial.println(F("Unable to begin:"));
Serial.println(F("1.Please recheck the connection!"));
Serial.println(F("2.Please insert the SD card!"));
while(true);
}
Serial.println(F("DFPlayer Mini online."));
myDFPlayer.setTimeOut(500); //Set serial communictaion time out 500ms
val = digitalRead(inputPin);
if (val==LOW) {
Serial.println("Button - Low");
LEDoff();
}
else {
Serial.println("Button - High");
LEDon();
}
myDFPlayer.volume(25); //Set volume value. From 0 to 30
}
void loop() {
// put your main code here, to run repeatedly:
val = digitalRead(inputPin);
if (val == LOW) {
Serial.println("Button - Low");
Serial.print("Pause State: ");
Serial.println(pauseState);
LEDoff();
myDFPlayer.stop();
pauseState = 0;
}
else {
Serial.println("Button - high");
Serial.print("Pause State: ");
Serial.println(pauseState);
//DF Player serial monitor activity
if (myDFPlayer.available()) {
printDetail(myDFPlayer.readType(), myDFPlayer.read()); //Print the detail message from DFPlayer to handle different errors and states.
//DF Player to play random track if no track is playing
if (myDFPlayer.readType()==DFPlayerPlayFinished) {
Serial.println("Song ended, selecting new song.");
randomTrack();
}
}
if (pauseState == 0) {
LEDon();
randomTrack();
pauseState=1;
}
//Twinkle white
timing=random(300, 1200); //generate random timing between twinkles
delay (timing); //wait between twinkles
n=random(0,LED_COUNT-1); //generate a random pixel number
uint32_t color=strip.getPixelColor(n); //store random pixel current color data
Serial.print("LED number ");
Serial.print(n);
Serial.print(" is currently set to this color: ");
Serial.println(color, HEX); //debugging serial monitor
strip.setPixelColor(n, 255, 255, 255, 0); //change the random pixel color data to white, adjust brightness to desired
strip.show(); //display pixel color
twinkle=random(40,120);
delay (twinkle); //pause before returning to original pixel color
strip.setPixelColor(n, color); //change the random pixel back to its original color
strip.show(); //display pixel color
}
buttonState = val;
}
void printDetail(uint8_t type, int value){
switch (type) {
case TimeOut:
Serial.println(F("Time Out!"));
break;
case WrongStack:
Serial.println(F("Stack Wrong!"));
break;
case DFPlayerCardInserted:
Serial.println(F("Card Inserted!"));
break;
case DFPlayerCardRemoved:
Serial.println(F("Card Removed!"));
break;
case DFPlayerCardOnline:
Serial.println(F("Card Online!"));
break;
case DFPlayerPlayFinished:
Serial.print(F("Number:"));
Serial.print(value);
Serial.println(F(" Play Finished!"));
break;
case DFPlayerError:
Serial.print(F("DFPlayerError:"));
switch (value) {
case Busy:
Serial.println(F("Card not found"));
break;
case Sleeping:
Serial.println(F("Sleeping"));
break;
case SerialWrongStack:
Serial.println(F("Get Wrong Stack"));
break;
case CheckSumNotMatch:
Serial.println(F("Check Sum Not Match"));
break;
case FileIndexOut:
Serial.println(F("File Index Out of Bound"));
break;
case FileMismatch:
Serial.println(F("Cannot Find File"));
break;
case Advertise:
Serial.println(F("In Advertise"));
break;
default:
break;
}
break;
default:
break;
}
}
void LEDon () {
//Turns LEDs on to a random color
strip.begin();
strip.setBrightness(255); //Overall Brightness must be kept at 255 for reading the color of LED
//set brightness by adjusting the color pallet
//Brightness of the colors can be set using the following scale: 100% is 255, 80% is 204, 60% is 153, 40% is 102, 20% is 51
//defines the desired color pallet
uint32_t red=strip.Color(153, 0, 0, 0); //HEX 990000
uint32_t green=strip.Color(0, 153, 0, 0); //HEX 009900
uint32_t blue=strip.Color(0, 0, 153, 0); //HEX 000099
uint32_t purple=strip.Color(75, 0, 153, 0); //HEX 4b0099
uint32_t yellow=strip.Color(153, 153, 0, 0); //HEX 999900
uint32_t cyan=strip.Color(0, 153, 153, 0); //HEX 009999
uint32_t lime=strip.Color(66, 153, 0, 0); //HEX 994200
uint32_t orange=strip.Color(153, 48, 0, 0); //HEX 993000
uint32_t magenta=strip.Color(153, 0, 153, 0); //HEX 999999
uint32_t myArray[9]={red, green, blue, purple, yellow, cyan, lime, orange, magenta};
for (i=0; i <= LED_COUNT-1; i++) {
mix=random(0,8); //Generate random number in a range ewual to the number of pallet colors
set=myArray[mix];
strip.setPixelColor(i, set); //set each pixel to a random color from color pallet
uint32_t color=strip.getPixelColor(i); //store random pixel current color data
Serial.print("Set LED ");
Serial.print(i); //debugging check
Serial.print(" to color: ");
Serial.println(set, HEX); //debugging serial monitor
Serial.print("LED number ");
Serial.print(i);
Serial.print(" read color: ");
Serial.println(color, HEX);
}
}
void LEDoff () {
for (i=0; i <= LED_COUNT-1; i++) {
strip.setPixelColor(i, 000000); //set each pixel to a random color from color pallet
}
strip.show(); //LEDs all black
}
void randomTrack () {
Serial.print("Count: ");
Serial.println(count);
if (count == 0) {
count = myDFPlayer.readFileCounts(); //Count the number of tracks on the SD card
Serial.print("Number of tracks on SD card: ");
Serial.println(count);
count = count +1;
}
track = random(1, count);
myDFPlayer.play(track); //Play the random mp3
Serial.print("Playing Track: ");
Serial.println(track);
}