Nerf gun target game

Hi, Fairly new to Arduino but have muddled through a few projects so far. We have been tasked with creating a target game for Nerf style guns and successfully sent out a prototype that uses piezo sensors to trigger a count displayed on a large 7 seg display, made out of ws2821b led reel.

Our client has asked us to add sound to trigger on each hit, I have had some success using the dfplayer, however my code for the counter and for the df player seem to be causing issues with each other. Any help with the code would be much appreciated.
Everything works as i want it to if the first trigger is hit within the first few seconds of start up. If it is not then the trigger for the sensor does nothing.

Code below

#include "FastLED.h"

#define DATA_PIN    2
#define LED_TYPE    WS2812B
#define COLOR_ORDER BGR
#define NUM_LEDS    63
#define BRIGHTNESS  250
#define FRAMES_PER_SECOND 120

#include "SoftwareSerial.h"         // Include the SoftwareSerial library for serial communication
#include "DFRobotDFPlayerMini.h"    // Include the DFRobotDFPlayerMini library for the DFPlayer Mini module

SoftwareSerial mySoftwareSerial(10, 11); // Create a software serial connection on pins 10 (RX) and 11 (TX)
DFRobotDFPlayerMini myDFPlayer;          // Create a DFPlayerMini object



int btn4=9;  //button for reset
int cnt=0;
int incPrev, decPrev, dec2Prev;
const int knockSensor = A0;  // the piezo is connected to analog pin 0
const int threshold = 40;   // threshold value to decide when the detected sound is a knock or not
int sensorReading = 0;



uint16_t pps = 3;  // number of Pixels Per Segment
CHSV segON100(100,255,200);  // color of 100s digit segments
CHSV segON10(100,255,200);  // color of 10s digit segments
CHSV segON(100,255,200);  // color of 1s digit segments

/* CRGB leds[NUM_LEDS];  <--not using this.  Using CRGBArray instead. */
CRGBArray<NUM_LEDS> leds;

// Name segments (based on layout in link above) and define pixel ranges.
CRGBSet segA(  leds(pps*0,  pps-1+(pps*0)  ));
CRGBSet segB(  leds(pps*1,  pps-1+(pps*1)  ));
CRGBSet segC(  leds(pps*2,  pps-1+(pps*2)  ));
CRGBSet segD(  leds(pps*3,  pps-1+(pps*3)  ));
CRGBSet segE(  leds(pps*4,  pps-1+(pps*4)  ));
CRGBSet segF(  leds(pps*5,  pps-1+(pps*5)  ));
CRGBSet segG(  leds(pps*6,  pps-1+(pps*6)  ));

uint16_t count = 0;  // keeps track of what number to display


//---------------------------------------------------------------
void setup() {
  Serial.begin(115200);  // Allows serial monitor output (check baud rate)
  delay(3000); // 3 second delay for recovery
  //FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.addLeds<LED_TYPE,DATA_PIN,COLOR_ORDER>(leds, NUM_LEDS).setCorrection(TypicalLEDStrip);
  FastLED.setBrightness(BRIGHTNESS);
  FastLED.clear();  // Initially clear all pixels

  mySoftwareSerial.begin(9600);     // Start software serial communication at 9600 baud rate

   if (!myDFPlayer.begin(mySoftwareSerial)) { // Initialize the DFPlayer Mini module

    while (true);                  // If initialization fails, print error messages and halt the program
  }

  myDFPlayer.setTimeOut(500);       // Set the timeout value for serial communication
  myDFPlayer.volume(15);            // Set the volume level (0 to 30)
  myDFPlayer.EQ(5);                 // Set the equalizer setting (0: Normal, 1: Pop, 2: Rock, 3: Jazz, 4: Classic, 5: Bass)
}


//---------------------------------------------------------------
void loop()
{
    
    int reset = digitalRead(9);
    sensorReading = analogRead(knockSensor);

    setSegments(count);

    //Reset
    if(reset == HIGH)
    {
      delay(100);
      count= 0;
    }

    //sensor
    if (sensorReading >= threshold)
    {
      delay(100);
      count+= 50;
      myDFPlayer.play(1);            // Play the third audio file on the SD card
      delay(200);                   // Delay for 2 seconds
    }


    FastLED.delay(1000/FRAMES_PER_SECOND); 
    
}




//---------------------------------------------------------------
void setSegments(uint16_t count){
  // Based on the current count set number segments on or off
  uint16_t c1 = 0;  // Variable to store 1s digit
  uint16_t c10 = 0;  // Variable to store 10s digit
  uint16_t c100 = 0;  // Variable to store 100s digit
  uint16_t c;
  CHSV segCOLOR(0,0,0);

  c1 = count % 10;
  c10 = (count / 10) % 10;
  c100 = (count / 100) % 10;
    
  //Serial.print("count = "); Serial.print(count);  // Print to serial monitor current count
  //Serial.print("\t  100s: "); Serial.print(c100);  // Print 100s digit
  //Serial.print("   10s: "); Serial.print(c10);  // Print 10s digit
  //Serial.print("   1s: "); Serial.println(c1);  // Print 1s digit

  // Operate on 1s digit segments first, shift them over,
  // then 10's digit, and then do the 100s digit segments.
  for (uint16_t i=0; i < 3; i++) {
    if (i == 0) {
      c = c1;
      segCOLOR = segON;
    }
    if (i == 1) {
      c = c10;
      segCOLOR = segON10;
    }
    if (i == 2) {
      c = c100;
      segCOLOR = segON100;
    }

    segA = segB = segC = segD = segE = segF = segG = CRGB::Black;  // Initially set segments off

    if (c == 0) { segB = segC = segD = segE = segF = segG = segCOLOR; }
    if (c == 1) { segB = segG = segCOLOR; }
    if (c == 2) { segA = segB = segC = segE = segF = segCOLOR; }
    if (c == 3) { segA = segB = segC = segF = segG = segCOLOR; }
    if (c == 4) { segA = segB = segD = segG = segCOLOR; }
    if (c == 5) { segA = segC = segD = segF = segG = segCOLOR; }
    if (c == 6) { segA = segC = segD = segE = segF = segG = segCOLOR; }
    if (c == 7) { segB = segC = segG = segCOLOR; }
    if (c == 8) { segA = segB = segC = segD = segE = segF = segG = segCOLOR; }
    if (c == 9) { segA = segB = segC = segD = segF = segG = segCOLOR; }

    if (i == 0) {  // Shift segments over to 1s digit display area
      for (uint16_t p=0; p < (7*pps); p++) {
        leds[p+(2*7*pps)] = leds[p];
      }
    }

    if (i == 1) {  // Shift segments over to 10s digit display area
      for (uint16_t p=0; p < (7*pps); p++) {
        leds[p+(7*pps)] = leds[p];
      }
    }

   
    //-------------------------------------------------------------------

  }
}//end setSegments

Every time someone posts a question such as that, always look for "delay()" in the code they wrote. Guess what? I see the use of delay. Rework the logic without the use of delay and see if that solves your problem.

ok thanks, I had read that delay can cause issues performing two tasks from one trigger, but I didn't think this was my issue, as my code works, as long as the first trigger happens before the df player has fully loaded on startup.
I had a feeling it was an issue with the setup code or possibly then end of the loop.
Would it be millis I should be using instead of delay if this is the issue?

You can just millis() and if it has to be faster then you can just micros().

I have tried using millis instead of delay for the triggers but I can't seem to remove it from the fastLED.delay.
Does anyone know of an alternative to using FastLED.delay?

Thanks

What does FastLED.delay() do in your program, and what are you needing?

This must be described.

You must describe "it." The trigger? The first trigger? First few seconds? One second? More than a few seconds?

I am using FastLED to display numbers of the count from the target hits

FastLED.delay is the refresh to check if the count has changed.

I attempted to change to millis but it is not in the FastLED library.

The issue I am having is if I have the df player is in my loop it stops the FastLED from displaying the count and makes no sound.

If I take FastLED.delay out of the code, the df player works correctly but the number display does not work

I think it probably is delay that is causing this to happen but I can't find a way of using FastLED without the delay as millis is not in the FastLED library.

I'm thinking I might need to use something other than Fast LED but that means starting again with a lot of the code.

I see you are using SoftwareSerial to communicate with the DFPlayerMini... maybe some of that is "blocking" or some of the FastLED is "blocking"...

Try DFPlayerMini in "I/O Mode"... it requires VCC, GND, SPK+, SPK-, and DIO pins to IO_1 and IO2. A short-duration grounding with a DIO pin of IO_2 loads the next file. Grounding IO_1 loads the previous file. Long duration grounding (experiment with level duration) of IO_1 will increase volume and long duration ground of IO_2 will decrease volume.

Your program would be just:

  • next file (played)
  • next 7seg number

That’s the first file, not third; and a delay of 200ms, not 2 s.
Plainly not root cause of your problem, but better to fix the delay, as the DFR module is fussy about those, before pursuing further.

Hi Terry, thank you for your reply, it solved my problem, and all is working correctly. Much appreciated.

My next task is creating a flashing light when the target is hit using FastLED and more of the w2812b LED Reel. My concern is that I will affect the 7seg numbers by adding more LEDs. Definitely pushing my limited knowledge, but I'm learning a lot doing it

Post your most recent code in preparation for adding the next feature.