This kind of system already exists even with DIY solutions :
- here is a very good project : https://amaury-laurent.fr/bruiteur-pour-avion-de-modelisme/ but without "gun effect"
- and an excellent commercial one "MrRCSound ASPIRE Sound System" but with a discontinued product
- and another commercial system but with weak amplifier and no "gun effect" : https://www.mr-rcworld.co.uk/shop/realtime-engine-sound-playback-module/
So I decided to build mine with the following features :
- play start engine sound when throttle stick leaves "zero" position
- seamlessly increase/decrease motor RPM sound with the throttle stick
- while motor running, play machine gun sound when pressing the gun button on the radio
- play stop engine sound when turning motor off
And to get a good sound level and quality :
- store the sound files into a SD card (you can change these files easily)
- use a DFPlayer mp3/wav module to decode the files
- amplify the sound with a 60W amplifier
- change the sound volume with a radio channel (potentiometer) or select a fixed volume value
- use an audio exciter instead of a regular loudspeaker
Audio Exciters are loudspeaker components that lack the frame and cone of traditional speakers and function by vibrating a rigid surface to create sound. Instead of mounting them with screws, they're adhered to whatever surface is intended to function as the speaker. In our use case it will be glued on the plane frame inside the cockpit.
All this should cost as cheap as possible (around 30/40 €)
Here is a small video of the system during tests on my desktop :
And a second one with the system fully hidden into the plane.
A software modification was made in order to synchronize the start and stop sounds with the propeller motion.
Result is more realistic. More details into this log
Electronics
Most of the electronics should be based on already available modules:
- An ESP32 lolin32 lite MCU
- A DFPlayer Mini mp3/Wav player
- a 60W audio amplifier
- a DCDC mini 360 stepdown converter
DFPlayer mini
This small module was originally designed by DFRobot
This player supports an microSD card on which can be stored mp3 or Wav files
This chip has a 3.3V ttl logic but its VCC can be between 3.3V and 6V max. A good value is 4.8V. We cannot power this module via the 3.3V of the ESP32 as its voltage regulator would be too weak... So an external power supply is mandatory
DFPlayer can be directly connected to an ESP32 using serial port. And its 3W built in amplifier (Speaker pins) can directly feed a small loudspeaker (less than 3W).
Unfortunately this amplifier is only a 3W model.. So we can add an external amplifier an connect it to the DACs output of the Player.
For my application I will only use a mono amplifier so only connect the amplifier to one of the DACs (DAC_left see schematics below).
Schematics
Here is how to connect the modules.
From left to right :
- 3 pin headers (THR, GUN and VOL) will be connected to 3 servo channels of the RC receiver, their values will be read by the ESP32
- The DFPlayer mini will be connected to the Serial2 port of the ESP32 (TX/RX pins)
- The DAC_Left output of the player will feed the audio amplifier (IN+ pin). IN- being connected to Ground
- Power of the amplifier will be supplied by the plane battery (more details will come) and it will also enter the DC/DC converter to output a strong 5V supply for both ESP32 and DFPlayer mini.
PCB
This schematics was easily routed on a dual sided PCB board.
The PCB was kindly sponsored by PCBWay and is as usual of excellent quality.
You can order it here : PCBWay shared project. It's cheap, delivered very fast and so professional looking!
and if you are new to PCBWay please use this affiliated link : https://pcbway.com/g/o35z4O
This board allows a "mezzanine mount" of all the components, so that the final product enters into a 5x5x2 cm box.
Soldering is fairly easy but you should follow this procedure:
- position the female pin headers to support the ESP32 module
- position the DFPlayer module between these pin headers (if needed trim a little the DFPlayer board)
- Then solder the DFPlayer
- Then solder the female pin headers for ESP32
- then solder the DC/DC converter
As you can see the DFPlayer goes exactly between the ESP32 pin headers
Now you can turn the board and solder the amplifier.
position and solder male pin headers:
Now insert the amplifier and solder it in place.
you can also add the 5V power cable for the ESP32 (bottom of the picture).
But do NOT yet insert the white plug into the ESP32 connector (unlike I did on the picture)
And we need now to power the board...
Power considerations
5V can be delivered either by the DC/DC converter (prefered solution) or directly by the ESC of your plane
power with DC/DC converter :
- first tune the trim pot value in order to get less than 5V (4.8V) output (do not power anything else before...)
- when this 5V is achieved, you can paint the trim pot with a drop of nail varnish to fix the potentiometer
- then (and only then) solder the SJ solder pad on the bottom side of the PCB. The 5V will now flow to the DFPlayer and the ESP32 (via the battery connector)
- Do not solder the SJ1 solder pad
Power with the ESC :
If your ESC is equiped with a strong enough BEC you can power the DFPlayer and the ESP32 directly with the throttle connector :
- do not solder the SJ solder pad (nor the DCDC module if you want)
- solder the SJ1 solder pad
- connect the throttle servo pin header to the THR connector on the board and power your ESC
I recommend the first option (DCDC step down converter) as the ESP32 can eat up to 700MAh (max) and the DFPlayer 200 mAh with integrated 3W amplifier or 50mA with the DAC... Don't forget that classicaly the ESC is also supposed to power the servos of your plane... It's better to avoid to stress more the ESC...
When these components are installed you can solder the audio amplifier on the bottom side of the PCB. Alternatively if 3W power is enough for you the Speakers outputs of the DF Player could be used
Powering the audio amplifier
The XH-M313 TPA3118 60W is an audio amplifier that can be powered up to 24V. As we will fly an electrical RC plane we will for sure power it with a lipo battery from 2s to 6s
A 6s battery will output (when fully charged) 6 x 4.23V = 25.38V which is above the max voltage of our amplifier.
So we will power the amplifier with a maximum 5s battery (5 x 4.23 = 21.15V). If we use a 6s battery for our plane we can pick up the 5s value into the balancer connector of the battery. This will slightly un balance our lipo (5s 1A current (drained for the amplifier) while 6s 40A current will be drained to power the plane motor). This is negligible and will be corrected by the balance charge for next flight !
However depending on the loudspeaker that you will choose, an even smaller voltage could be recommended to avoid burning the speaker coil... 12 to 16V seems to be loud enough !
Software
Software of our system should be very simple as we want to implement this simplified state machine :
- When starting the motor should start with the throttle stick
- then motor sound should change with the throttle (machine gun effect must be added)
- and when throttle goes back to zero, motor stop sound should be played
Basically we need the following features:
- decode throttle, gun and volume channels from the radio receiver
- play a sound until its end
- play a sound in loop and allow to interrupt it (when throttle changes or when gun button is pressed)
- change volume on the fly
Reading the receiver channels
I found an excellent library to decode PWM Rx channels with embedded RMT hardware of the ESP32.
Using this library is fantastically simple :
Declare the channels (pins) you want to decode
//Rx servo reader library : https : //github.com/rewegit/esp32-rmt-pwm-reader
#include <esp32-rmt-pwm-reader.h>
// #include "esp32-rmt-pwm-reader.h" // if the lib is located directly in the project directory
// init channels and pins
uint8_t pins[] = { 32, 33, 25 }; // desired input pins
int numberOfChannels = sizeof(pins) / sizeof(uint8_t);
Then read a channel at a time
// Reading the actual pulse width of Throttle channel
speedIndex = constrain((pwm_get_rawPwm(0) - 1000), 0, 1000); //clip throttle value between 0 and 5
speedIndex = map(speedIndex, 0, 1000, 0, 5);
Here the throttle channel. As you can see the output of the library is a standard pulse duration between 1ms to 2ms with a center position at 1.5ms
I remap this value between 0 and 5 so that I can play 5 sounds depending on the throttle stick position. Simple!
Having read these Rx channels, it's now simple to code the state machine:
// Do something with the pulse width... throttle and gun
switch (status) { //handle motor and gun
case statusIdle:
startTime = millis();
if (speedIndex > 0) {
status = statusStarting;
volume(volIndex);
currentSpeedIndex = -1; //will force exit from startmotor playing
PlaySound(0x00, 0); //PlaySound(motor_start)/Play the 1.mp3 (motor start)
Serial.println("starting");
}
break;
case statusStarting:
if (((millis() - startTime) > startDuration) || (startPlayed == true)) { // wait for the startPayed event of the startmotor track (or failsafe time out)
status = statusRunning;
PlaySound(0x00, 1); //PlaySound(1_mot.wav) now go to the 001 rpm sound
PlaySoundLoop();
Serial.println("running");
}
break;
case statusRunning:
stopTime = millis();
if ((speedIndex != currentSpeedIndex) || (shoot != previousShoot)) {
currentSpeedIndex = speedIndex;
previousShoot = shoot;
if (speedIndex == 0) { // change status to stop motor
status = statusStopping;
} else {
PlaySound(shoot, speedIndex); //Play the speedIndex.wav (motor run (+ gun if shoot)) and loop
PlaySoundLoop();
}
}
break;
case statusStopping:
if (speedIndex == 0) {
if ((millis() - stopTime) > 100) {
PlaySound(0x00, 6); //Play the 06_motorStop.wav (motor stop) and do not loop
Serial.println("stopping");
status = statusIdle;
}
} else status = statusRunning;
break;
default:
// statements
break;
}
Well it should have been simple if the DFPlayer was working as expected !
Interfacing the DFPlayer with ESP32
My first idea was to use the DFRobotDFPlayerMini Arduino library. But I quite soon discovered that my DFPlayer was not a genuine one and with this library... I got the bad error mesage at startup :
Unable to begin:
1.Please recheck the connection!
2.Please insert the SD card!
I finally got the DFPlayer working and I wrote my own code as the protocol was quite simple and as I didn't need all the commands...
Sound files naming rules
DFPlayer has quite strict naming rules for sound files and folders.
You can add files into folders with names "XX" where XX are numbers 0 to 9.
I created two folders "00" and "01" containing respectively the "normal" and the "machine gun" files
And files into the folders must start with a 3 digits code. But files names can be appended with text to ease understanding the sd card content
With these naming conventions the DFplayer alllows commands such as :
PlaySound(folderNum, fileNum)
- PlaySound(0, 1) would play the 001.wav file into folder 00
- while PlaySound(1, 1) would play the 001_gun.wav file into folder 01
I also coded two useful functions
- "CMD_Set_repeat_playback_of_current_track" to allow repeating the current track
- "CMD_Specify_volume" to change volume (between 0 and 30)
Finally I coded a way to detect end of song (return code 0x3D)
switch (receive_frame.CMD) {
case 0x3A:
Serial.println("card inserted");
break;
case 0x3B:
Serial.println("card ejected");
break;
case 0x3D:
{
Serial.println("card playing finished");
if (status == statusStarting) startPlayed = true;
else startPlayed = false;
}
break;
And that's it. The DFPlayer was working and my project almost finished!
The full code is available into my Github pages
Preparing the sound files
Sound files should be into Wav format. This format is uncompressed so eats much more room on your SD card... but is fast to decode (no decoding) so easier to read for the DF Player. Thus there is almost no sound gap when changing track neither any audible nasty click
I use 16bits PCM monophonic Wav format which is compact enough and still with a good quality.
You will find planes sounds files on this site : https://simviation.com/1/browse-Flight+Simulator+Sounds-112-0
Or you can unzip the sounds Pack that I have created.
If you want to change the sounds pack the procedure to create your own sounds is quite easy.
You will have to install Audacity software
Then open any track you want (here is an example with a stereo machine gun sound)
First step will be to transform this stereo file into a mono one:
now you can trim the start and end to only keep the gun sound (select and cut)
you can now copy and paste the full track to repeat the sound effect :
And finally export the full track:
You can also mix the motor sound with the gun effect:
open both tracks, trim them so that they start and stop at the right same moment.
Then mix them (mix and render menu)
And export the result as a mono Wav file.
Now that you know how to mix sounds you can easily create your own mix including Stuka siren sound. Have a look at this log to understand what I mean
choosing the right Exciter and integration into the plane
An RC plane has a very important design constraint : WEIGHT
So adding this sound machine must take this constraint into consideration. We would like to add the most powerful loudspeaker... But we shouldn't if it is heavy.
So we have searched for a good balance point between weight and power.
We found this tiny yet powerful Dayton Audio Exciter : DAEX25CT
It weights 75g, it's small enough to fit into the fuselage and still has 10W RMS power.
Our amplifier is said to go to 60W... Too much for this exciter ? Well no if we power the amplifier with 12 to 16V instead of 23V (max).
So a 3s lipo battery would be perfect. We could even jump to 4s depending on our motor specifications !
And with 3s or 4s we can directly pick the juice on all the cells of the battery without any risk of unbalancing the cells. (see power considerations above).