DFPlayer Project - Please Help - Toy Car playing motor sound and triggered sound

Dear community,

I am almost at the point of despair...
My project seemed to be pretty simple but turns out I am no way near to be a programmer and it sucks.

My Goal:
A toy car is equipped with a SEEED XIAO SAMD21 and a connected DFPlayerMini.
At start-up (power on) an engine starting sound is triggered. After that, an accelerating motor sound should be played in a loop.
Once a certain trigger is activated (digital Input) the engine sound should be paused and a certain sound file should be played.

So far so good.

I manage to get the system running and communicating. Startup sound is also fine. That means I figured out all issues with SD-Card formatting etc.
I fail at programming a loop that works properly and loops infinitely.

Here is my (1000th) not working code. I tried several libraries and still I suck at this.

#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
unsigned long previousMillis = 0;  // will store last time LED was updated

// constants won't change:
const long interval = 8000;  // interval at which to blink (milliseconds)
DFRobotDFPlayerMini myDFPlayer;
bool isPlaying();
int playstate = 0;
  bool AF_Value, WE_Value, AS_Value, BE_Value = false;
  bool lastAF_Value, lastWE_Value, lastAS_Value, lastBE_Value = false;
void setup()
{
  pinMode(0,INPUT);
  pinMode(1,INPUT);
  pinMode(2,INPUT);
  pinMode(3,INPUT);
  pinMode(4,INPUT);

  Serial.begin(115200);
  Serial1.begin(9600);
  
  myDFPlayer.begin(Serial1);
  myDFPlayer.volume(10); //set volume low
  delay(100); //wait another 100ms
  myDFPlayer.EQ(DFPLAYER_EQ_ROCK); //set EQ as pop
  delay(100); //wait another 100ms
  myDFPlayer.play(1);
  delay(3000);
  
 

}

void loop()
{ 
      unsigned long currentMillis = millis();
      if (digitalRead(0)== HIGH)
    {
      Serial.println(digitalRead(0));
      myDFPlayer.advertise(1);
      myDFPlayer.volume(10);
    }
     if (digitalRead(1)== HIGH)
    {
      Serial.println(digitalRead(1));
      myDFPlayer.advertise(2);
      myDFPlayer.volume(10);
    }
    
     if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    myDFPlayer.play(2);
    }
}

I`ve read so many threads on this, that I came to the conclusion Advertising would work best for this scenario.
I happen to fail at these points

a)If I'm starting this thing up.
engine starting sound - true
engine acceleration sound - true
loops "forever" - true
as soon as a trigger gets activated - ad plays - true
engine sound picks up again - true
trigger won't do again (none of them)
after finishing the engine sound file the looping of the sound stops.

Please help me. This is intended as a gift for a coll. retiring.

Best
Bastian

I changed the code so that I can see where it gets stuck:

Seems like its looping 3x and then quits.

#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
unsigned long previousMillis = 0;  // will store last time LED was updated

// constants won't change:
const long interval = 5000;  // interval at which to blink (milliseconds)
DFRobotDFPlayerMini myDFPlayer;

void setup()
{
  Serial.println("setup");
  pinMode(0,INPUT);
  pinMode(1,INPUT);
  pinMode(2,INPUT);
  pinMode(3,INPUT);
  pinMode(4,INPUT);

  Serial.begin(115200);
  Serial1.begin(9600);
  myDFPlayer.begin(Serial1);
  myDFPlayer.volume(10); //set volume low
  delay(100); //wait another 100ms
  myDFPlayer.EQ(DFPLAYER_EQ_ROCK); //set EQ as pop
  delay(100); //wait another 100ms
  myDFPlayer.play(1);
  delay(3000);
}
void loop()
{   
      Serial.println("loop");
      unsigned long currentMillis = millis();
      if (digitalRead(0)== HIGH)
    {
      Serial.println("Werbung 1");
      myDFPlayer.advertise(1);
          }
     if (digitalRead(1)== HIGH)
    {
      Serial.println("Werbung 2");
      myDFPlayer.advertise(2);
          }
     if (currentMillis - previousMillis >= interval) {
    // save the last time you blinked the LED
    previousMillis = currentMillis;
    myDFPlayer.play(2);
    }    

17:32:24.021 -> loop

17:32:24.021 -> loop

17:32:24.021 -> Werbung 2

17:32:24.021 -> loop

17:32:24.021 -> Werbung 2

17:32:24.021 -> loop

17:32:24.021 -> Werbung 2

How are your inputs wired up? They will need external pullup or pulldown resistors since you have declared them as INPUT. Much, much better to declare them as INPUT_PULLUP.

As for your loop, you want to detect when a button is pressed, not if a button is pressed or else you continuously start replaying the same thing. Look at the State Change Detection example in the IDE (File->examples->02.digital->State Change Detection)

Did you remove parts of the sketch?

sketch.ino: In function 'void setup()':
sketch.ino:19:3: error: 'Serial1' was not declared in this scope
   Serial1.begin(9600);
   ^~~~~~~
sketch.ino:19:3: note: suggested alternative: 'Serial'
   Serial1.begin(9600);
   ^~~~~~~
   Serial

I would expect something like this in your sketch:

#include <SoftwareSerial.h>

const byte rxPin = 2;
const byte txPin = 3;

// Set up a new SoftwareSerial object
SoftwareSerial Serial1 (rxPin, txPin);

And an Arduino? Which one? What role is the other MCU playing? What was the starting source for your code? A circuit schematic would also be helpful please.

EDIT: Your latest sketch, post 2, does not compile. There is a missing curly brace sat the end of your loop().
"expected '}' at end ofinput"

The Seeed XIAO SAMD21 is the MCU. It is programmed via Arduino IDE.

The wiring is solid. No issues. I also worked with pull-down resistors to get a stable 0 and avoid toggeling.

The issue lies in the code.
I put a delay (duration ad length) after the ad. Works as a charm now.

But this is far from good programming. I will be testing with the mentioned detection of buttonpress and will give feedback on this in a couple of days.

Thank you so far!

So no Arduino board at all? I have a Uno at hand so have replaced your hw serial with sw serial.

Please post the sketch that is working. Preferably with more or edited comments. The existing ones mention an led, but none is specified. The four bool variables are not used. Is track 1 your engine sound and 2 the acceleration? How long are they?

OK, didn't notice at first. You have it all working. Good luck.

So I've recently changed my sketch.
I implemented the buttonStatusUpdate and it works fine. Any ideas?

Now I've got some kind of timing / digitalRead() issue.
The car drives on a plastic track with several rails on it. The rails have a height of several mm and when the car is "hitting" on them, they push one (or several at once) trigger (8 of em possible). We've built the track that way, that there are 6 points with rails along it. That means, we want play 6 different sounds at these particular points.

So far so good. If I had 6 individual triggers, I wouldn't have a problem. Unfortunately these tracks are built in a way that they push at least 2-3 triggers at once.
I thought easy as pie. Just make some if-statements with AND comparison.

But it doesn't work like I want to. I shortcutted trigger 0 and 1 for testing. Thought that digitalRead(0) && digitalRead(1) would execute. Instead it plays 0 or 1.
I've got 10k pull-down resistors integrated and the code works fine for any individual trigger (up to 8).
In combination, it won't.

bitRead Portregister would work faster I believe. But I can find no information on ports for SEEED SAMD21...

#include "Arduino.h"
#include "DFRobotDFPlayerMini.h"
unsigned long previousMillis = 0;  // will store last time LED was updated
unsigned long previousMillis2 = 0;
unsigned long previousMillis3 = 0;
// constants won't change:
const long interval = 6000;
const long werbedauer1 = 12000;  // interval at which to blink (milliseconds)
const long werbedauer2 = 12000;
const long werbedauer3 = 8000;
DFRobotDFPlayerMini myDFPlayer;

// Variables will change:
int buttonState[8];        // current state of the button
int lastButtonState[8] = {0,0,0,0,0,0,0,0};    // previous state of the button
int rails[] = {0,1,2,3,4,5,8,9};
String StrPinrails = "Input Nr: ";


void setup()
{
  for (int x = 0; x < 2; x++){
   pinMode(rails[x], INPUT);
   delay(2);
 }
 
  Serial.begin(115200);
  Serial1.begin(9600);
  myDFPlayer.begin(Serial1);
  myDFPlayer.volume(20); 
  delay(50); 
  myDFPlayer.EQ(DFPLAYER_EQ_ROCK); 
  delay(50);
  myDFPlayer.play(1);
  delay(1000);
  Serial.println("Es wurden alle Inputs definiert");
}
void loop()
{   
 
  unsigned long currentMillis = millis();
      
  // Prüft den Status der Pick-Ups (ob das Auto über eine Schiene fährt):
    for (int i = 0; i < 2; i++){
      int Port = rails[i];
      String Auslesen = StrPinrails + Port + digitalRead(rails[i]);
      Serial.println(Auslesen);
      buttonState[i] = digitalRead(rails[i]);
      delay(250);
      if (buttonState[i] != lastButtonState[i]) {
        // if the state has changed, increment the counter
        delay(1);
        if ((buttonState[0] == HIGH) && (buttonState[1] != HIGH)) {
        // if the current state is HIGH then the button went from off to on: Hier müsste jetzt noch eine if-Verknüpfung kommen, welche die möglichen UND-Verknüpfungen der Strecke enthält
          Serial.println("Werbung 1");
          myDFPlayer.advertise(1);
          delay(werbedauer1);
        Serial.println("on");
      } 
      delay(1);
      if ((buttonState[1] == HIGH) && (buttonState[0] != HIGH)) {
      Serial.println("Werbung 2");
      myDFPlayer.advertise(2);
      delay(werbedauer2);
      }
      delay(1);
      if ((buttonState[1] == HIGH) && (buttonState[0] == HIGH)) {
      Serial.println("Werbung 3");
      myDFPlayer.advertise(3);
      delay(werbedauer3);
      }
      else {
        // if the current state is LOW then the button went from on to off:
        Serial.println("off");
      }
      } 
    // Delay a little bit to avoid bouncing
    delay(50);
  }
  

  // Vergleicht den Pick-Up Status mit dem vorhergehenden Status
  
  // save the current state as the last state, for next time through the loop
  for (int i = 0; i < 1; i++){
    lastButtonState[i] = buttonState[i];  
    }

You will need to change your logic a bit. Inside loop() you want to read all your buttons and debounce them in a single for() loop.

After that is complete, then apply your logic about what song to play. If you use something like the Bounce2 library, it can handle all the button presses, debouncing, etc. for you which makes your code a lot cleaner.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.