Modded my daughter's Fisher Price Sea Turtle toy to play custom audio files.
Things used in this project
Hardware components
Hand tools and fabrication machines
Rotary Tool (Dremel)
Soldering iron (generic)
Wire (24 gauge)
Perfboard
Tape, Electrical
Tape, Velcro® Stick On Tape/Strip
Super Glue
Screwdriver
Story
This project started shortly after I learned about Arduino. My daughter was playing with one of her toys, the Fisher Price Sit-to-Crawl Sea Turtle, and I decided to take a look under the hood.
When I disassembled the toy, I learned that it essentially consists of a couple switches, a microchip, and a speaker. Since I had recently bought an Arduino starter kit, I wondered if I could mod the toy to play custom audio files. After a month of learning and tinkering, I created this:
How it works
This mod works by adding a custom circuit board to the toy and connecting that board to both the toy's speaker and 4.5v source (3 AA batteries).
Here's the schematic of the circuit board that was added to the toy:
And here's an internal diagram of modded toy:
Playing custom audio with an Arduino
Creating an mp3 player is much harder than I imagined. Luckily, a little mp3 player module exists - the DFPlayer Mini. It's pretty easy to connect the DFPlayer to an Arduino, load some tracks on it, and play those tracks through a speaker.
That said, the DFPlayer is a quirky module. I had issues writing code for the module and with noise on playback. I was able to solve all my code issues and most of the noise issues by searching around and finding threads online from people that had similar problems.
I also added a custom button to the toy that will play the next audio file loaded on the DFPlayer. I positioned the button in the toy so that the a press of the toy's orange panel would trigger it.
Switching between factory and custom modes
One of the most important features I wanted to build into this mod was to be able to switch back and forth between the factory audio and my custom audio. There wasn't enough room in they toy for a second speaker or voltage source, so I needed to connect my custom board to the toy's batteries and speaker.
To separate the circuits and prevent them from being turned on at the same time, I added a slide switch to the toy. The slide switch is double pole/double throw and switches which board is connected to the batteries and speaker.
CustomLEDs
The original toy blinks RGB LEDs to the beat of the music while each audio track plays. I didn't get that fancy with my custom LEDs. Instead, I installed red LEDs that blinked on and off while the custom audio tracks played.
Fittingeverythinginthetoy
Using an Arduino Nano Every helped as it is one of the smaller and fully featured chips available. It also helped that the DFPlayer Mini is so small. I positioned the chips on my perfboard to minimize space and with some dremeling of the toy's shell, I was able to fit them inside the toy. To secure the perfboard, I used adhesive velcro.
I had to do some additional dremeling to a hole in the bottom of the toy so I could access the custom slide switch.
For my custom play button, I super glued it to the top of the factory button in the toy and then did a little dremeling to the toy's orange panel so it would fit with the additional button. Now when you press down on the toy's orange panel, both the custom button and factory button are toggled.
Unsresolved Issues
BatteryDrain
The batteries get drained even when the toy is turned off, so for now I have to take one battery out when the toy is not in use. I assume this is because I grounded my custom circuit through a random solder point on the factory board, which I determined was connected to the negative terminal of the battery holder using a multimeter. I did this because I could not figure out a way to directly ground my circuitry to the negative terminal of the battery holder. Fisher Price really hid the negative terminal. Perhaps with some creative dremeling and wiring I could figure it out.
AudioNoise
There is some audio noise, or stuttering, when playing certain custom tracks through the toys speaker. I'm not sure what is is about certain tracks that trigger the stuttering noise, but my assumption is that the problem is related to variable or inadequate current being supplied to the DFPlayer Mini. This assumption is based on the observation that the noise was considerably worse when using a 9v battery, which outputs much less current than 3 AA batteries. I wonder if adding capacitors of the proper value and configuration could eliminate the noise issue, but that's above my head and not really worth as the audio doesn't sound terrible.
Final Thoughts
This was a fun project and served as a perfect introduction to both the Arduino and DIY electronics. I can't tell you how much I learned and how much problem solving I had to do. I didn't even know how to solder when I started this project. Thankfully, I had a lot of help from countless others who had similar problems and took the time to document them online. I also posted some questions directly to /r/Arduino on Reddit, which was very helpful.
If you want see a deeper dive into how I made this project work, watch the video below.
Schematics
Sea Turtle Audio Mod - Schematic
Code
Sea Turtle Mod - Code - Main file
Arduino
#include "Led.h"
#include <DFPlayerMini_Fast.h>
// LED Pins
const int LED_1_PIN = 3;
const int LED_1_PATTERN[patternSize] = {400, 400, 400, 400};
const int LED_2_PIN = 6;
const int LED_2_PATTERN[patternSize] = {400, 400, 400, 400};
// Led object init
Led led1(LED_1_PIN);
Led led2(LED_2_PIN);
// Create the Player object
DFPlayerMini_Fast player;
// Pin for play button
const int PLAY_BTN = 12;
// DFPlayer Control States
int fileCount;
bool toggleState = 1;
bool lastToggleState = 1;
bool busyState = 0;
int lastTrack = 0; // 0 is no track played
void setup() {
// Init USB serial port for debugging
Serial.begin(9600);
// Init Serial1 for DFPlayer Mini
Serial1.begin(9600);
player.begin(Serial1, false, 500);
delay(1000);
// Set volume
player.volume(26);
delay(500);
// Get number of tracks
fileCount = player.numSdTracks();
delay(500);
// Init play button pin
pinMode(PLAY_BTN, INPUT_PULLUP);
// initialize leds, turn them on, and load blink patterns
led1.init();
led1.on();
led1.loadPattern(LED_1_PATTERN);
led2.init();
led2.on();
led2.loadPattern(LED_2_PATTERN);
}
void loop() {
// get toggle state
toggleState = digitalRead(PLAY_BTN);
// get busy state
busyState = player.isPlaying();
// Debug states
Serial.print("Busy: ");
Serial.print(busyState);
Serial.print(" Last Track: ");
Serial.print(lastTrack);
Serial.print(" Toggle: ");
Serial.print(toggleState);
Serial.print(" Last Toggle: ");
Serial.print(lastToggleState);
Serial.print(" File Count: ");
Serial.println(fileCount);
// if button has been pressed and track is not playing, play the next track
if (!toggleState and lastToggleState) {
lastToggleState = 0;
if (lastTrack == fileCount) {
lastTrack = 0;
}
lastTrack++;
player.playFromMP3Folder(lastTrack);
delay(500);
} else if (toggleState and !lastToggleState) {
lastToggleState = 1;
}
// run blink pattern for each led for duration (blinkDur)
if (busyState) {
led1.blinkPattern();
led2.blinkPattern();
}
}
Sea Turtle Mod - Code - Led.cpp
Arduino
#include "Led.h"
Led::Led(byte pin) {
this->pin = pin;
}
void Led::init() {
pinMode(pin, OUTPUT);
off();
}
void Led::off() {
digitalWrite(pin, LOW);
}
void Led::on() {
digitalWrite(pin, HIGH);
}
void Led::loadPattern(int arr[patternSize]) {
for (int i = 0; i < patternSize; i++) {
pattern[i] = arr[i];
}
}
void Led::blinkPattern() {
unsigned long currentMillis = millis();
if (currentMillis - lastBlink >= pattern[blinkStep]) {
// debugging output
// Serial.print("Last Blink: ");
// Serial.print(lastBlink);
// Serial.print(" Blink Step: ");
// Serial.print(blinkStep);
// Serial.print(" Blink Interval: ");
// Serial.println(pattern[blinkStep]);
if (state == LOW) {
state = HIGH;
on();
} else {
state = LOW;
off();
}
lastBlink = currentMillis;
if (blinkStep == patternSize-1) {
blinkStep = 0;
} else {
blinkStep++;
}
}
}
Sea Turtle Mod - Code - Led.h
Arduino
#ifndef MY_LED_H
#define MY_LED_H
#include <Arduino.h>
const int patternSize = 4;
class Led {
private:
byte pin;
unsigned long lastBlink = 0;
int blinkStep = 0;
bool state = HIGH;
public:
int pattern[patternSize];
Led(byte pin);
void init();
void off();
void on();
void loadPattern(int arr[patternSize]);
void blinkPattern();
};
#endif