Custom "engine" sounds (or sweet silence) with a DIY replacement VSP controller

My Nissan Leaf Forum

Help Support My Nissan Leaf Forum:

This site may earn a commission from merchant affiliate links, including eBay, Amazon, and others.
@dampkwab if you really want this project to fly, I encourage you (perhaps once you've recouped your development cost selling a few units) to make your PCB design, BoM and 3D case files open source! Just sayin :)

And not wanting to beat the same old drum, but I really think an on-board piezo or connections for an internal cabin speaker would be great. It could create the indicator tick/tock noises and other combination-meter warning noises that people loose when they remove the piezo from their cluster like driving without the seatbelt on (lol, ok maybe not that one)
 
Definitely planning to keep the firmware open-source in case anyone wants to customise that. I kinda figured the hardware designs wouldn't be much use to anyone unless they're planning a production run, but I'll keep it in mind!

Agreed on the idea of an on-board buzzer - that would make it a lot more versatile & could potentially be used for user feedback when adjusting volume/sound/etc settings too. The first run of prototypes does include an expansion connector that breaks out a few PWM-capable GPIO pins. I was planning on using those for the option of adding aftermarket mute/volume controls, but a speaker/buzzer could be plugged in there just as easily.
 
I received the PCBs & enclosures this week! All worked well once assembled (after a tiny bit of manual persuasion for one of the ICs)
PXL_20250104_093705048.jpg

And here it is safely encased in its laser-sintered nyon enclosure:
PXL_20250104_093334357.jpg

I've been working on the firmware & running it through its paces on a benchtop test harness:
PXL_20250104_094546247.jpg

The plug on the left simulates the vehicle connection - providing power, speaker output, mute button, and driving signals over USB2CAN. The plug on the right allows an three additional buttons for adding optional aftermarket volume/mute controls. (Or something else if you're into firmware hacking)

Everything looks pretty good so far! I'll be running it in my car to give it a bit more field testing & putting some finishing touches on the firmware, but I'd say v1 is pretty close to finalised.
 
Update on availability & new sounds:

It's been running smoothly in my car for the last month now, so I think its ready for a wider audience.
There are already a couple on their way out to other forum-goers, and I'm opening up orders to anyone who wants one of their own!
More details & an order form can be found here:
https://meadia.com.au/leafy-warbler/

In addition to the original synth mode I've added the ability to playback arbitrary recordings, so far including:
  • Idling 2-stroke chainsaw motor
  • Coconuts (pantomime horse) that gallop faster as the car speeds up
  • Pac-Man jingle on startup, waka-waka when the car moves, game-over sound on shutdown 😁
The firmware repository has been updated too, so people can recompile it to add whatever other sounds they like.
Keen to see what people come up with!
 
Very excited to load up Forest Speederbike sounds.
Do ZE0 cruise control buttons work, or only ZE1?

I suppose some volume adjustment could be baked into a custom firmware build.
Gitlab is blocked by my ISP, but working around that with VPN and/or cellular hotspot.
Edit: Spent a few hours last night solving build issues, but got it compiling on a Pixelbook Go (Intel m3 x86) and used ffplay to preview the sound samples. Next I'll continue reading over the code and prepping additional new audio samples.
I might want to wire a button to switch sound profiles.
Some persistent memory can be written to record the last selected profile, and flush/write during power down if it's changed.
https://github.com/raspberrypi/pico-examples/blob/master/flash/program/flash_program.c
https://www.makermatrix.com/blog/read-and-write-data-with-the-pi-pico-onboard-flash/
 
Last edited:
For ICE cars, they came up with the SoundRacer, which plugged into the cigarette lighter socket, and would synthesize a V-8 engine over its FM transmitter, so you could tune in and play racing engine sounds over the radio.

I often thought it would be fun to have something like that for the Leaf that could synthesize engine sounds like they had on the Jetsons. Now it looks like that may be an option? Very cool!
 
Do ZE0 cruise control buttons work, or only ZE1?
Only ZE1, as far as I can tell.
I haven't been able to find any mention of the earlier buttons being available on the CAN bus & I don't have an AZE0 of my own to reverse-engineer.
But if anyone knows of a AZE0 CAN frame that exposes those buttons please let me know and I'll add it to the firmware!

EDIT: Lokaim has confirmed the AZE0 steering wheel buttons are compatible too 😁

For ICE cars, they came up with the SoundRacer, which plugged into the cigarette lighter socket, and would synthesize a V-8 engine over its FM transmitter, so you could tune in and play racing engine sounds over the radio.
Love this - inferring engine revs by listening to alternator voltage ripple from the cigarette lighter is genius!
 
Last edited:
Arghh. I have a neighbor who did this with his ICE car (originally a very quiet Mercedes). He likes to rev it up in his driveway before going to work at around 3:00 am.
 
Edit: Spent a few hours last night solving build issues, but got it compiling on a Pixelbook Go (Intel m3 x86) and used ffplay to preview the sound samples. Next I'll continue reading over the code and prepping additional new audio samples.
I might want to wire a button to switch sound profiles.
Some persistent memory can be written to record the last selected profile, and flush/write during power down if it's changed.
https://github.com/raspberrypi/pico-examples/blob/master/flash/program/flash_program.c
https://www.makermatrix.com/blog/read-and-write-data-with-the-pi-pico-onboard-flash/
Just saw this edit - hope it wasn't too difficult to get up & running!

Settings are already saved to persistent memory, so it'll save whether it's muted & what sound/volume it's set to whenever they're changed.
You can find the code for that in src/settings.cpp.

That'd also be the place to put any custom button logic you want to add.
E.g. if you want button 1 to select the coconuts sound, you could comment out its existing logic (cycle through all sounds) and add something like:

C++:
// Dedicated coconuts button
if(debounce( gpio_get(PIN_BTN_1), btn_1_debounce )){
    settings.mode = MODE_COCONUTS;
    changed();
}


The quick & dirty way to add a custom sound would be to replace one or more of the existing raw audio files (in sounds/) and recompile, no coding required.
Otherwise, relevant code can be found in src/sampler.cpp and I'd suggest copying one of the existing sampler modes as a template and customising it from here.

There's not a lot of documentation in the code yet, so let me know if you run into anything confusing and I'll try to improve it or explain it better!
 
Last edited:
Otherwise, relevant code can be found in src/sampler.cpp and I'd suggest copying one of the existing sampler modes as a template and customising it from here.

There's not a lot of documentation in the code yet, so let me know if you run into anything confusing and I'll try to improve it or explain it better!
No worries! I figured out the settings after reading over the full codebase.
I made a number of refactors to optimize some functions, templatize the sampler models and added a few variations including regen B gear, reversing and changing in/out from reverse, added precompiler directives to enable/disable each sound profile/mode (for both individual preference and to manage the output firmware file size) and an optional randomizer for those without controls (ZE0) that picks a random profile each power on (disabling writing the random mode back to eeprom to save on write durability).
I saved a few compiled builds to test the enhancements sequentially (bug checking) and a few variations of sound profiles/modes to verify they don't annoy the spouse: Doctor Who TARDIS and theme song, StarWars lightsabers, StarWars pod racers and TIE fighter.
Endor Speederbikes sound better flying by than being in one.
I struggled to keep the size down to fit the Pico firmware limit, especially for some higher fidelity samples like Americana music (Enclave Eyebot from Fallout). Lowfi samples fared better. I may need to apply audio compression to reduce the bitrate first before converting to final format.
I can (use my cell tether to bypass the ISP block and) push up some pull requests after I test, if you'd like.

The warbler package arrived yesterday (2/28).
I want to express thanks for using USB-c over micro-USB.

What is the 3 pin connector labeled CAN used for?
 
It was an easy install: Remove glove box (4 screws on top, 2 inside top, 4 below. Door jamb panel and foot panel. ), unplug VSP (above glovebox in center top edge, "E" sticker), plug harness into Warbler and tuck Warbler inbetween other wires. I didn't bother removing the VSP module (simpler to leave in place to keep track of it). I plugged a USBc cable into the Warbler and fed it into the glovebox through the side panel handle, for easy access to reprogram it.

Testing in reverse, drive, and revving in neutral worked as expected for the synth mode. 2016 YM in neutral the Cruise Control accel/decel adjusted the volume and CC cancel button muted/unmuted. As described the cruise control enable button didn't do anything for the warbler. Unless we figure out the code for that button (I have an idea to load up a sound file for each number 0-9, and have the warbler read out the code for button press it detects), I'll make the cancel button work as a combo mode selector and mute, but include randomizer as it own mode to persist that (silent, random on startup, mode 1, 2, 3 etc).
Other than the limitations on file size of sounds due to rom size, these enhancements makes it meet all my desires.
Maybe the USB port can be used to mount flash drive storage for larger sound files.
 
Very cool - thanks for posting @Lokaim & congrats on the first install outside of Oz!
I'm baffled that your ISP blocks Gitlab -- why?? I'd love to see your changes though - random mode sounds like pure chaos! 🤣

I want to express thanks for using USB-c over micro-USB.
What is the 3 pin connector labeled CAN used for?
Always glad to meet another USB-C enjoyer.
The 3-pin connector directly exposes the CAR CAN bus - I used it during development & it can be used to capture or inject any other traffic on that bus.
Theoretically the Warbler itself should be able to act as a standalone USB2CAN adapter straight over its USB port, but I haven't written firmware for that (yet).

I struggled to keep the size down to fit the Pico firmware limit, especially for some higher fidelity samples like Americana music (Enclave Eyebot from Fallout). Lowfi samples fared better. I may need to apply audio compression to reduce the bitrate first before converting to final format.
The 16MB of onboard flash is good for ~3min of high-quality uncompressed mono audio - that's way more than I'm using myself (the stock firmware uses short/looped samples & takes up ~10% of that storage) but it would be a limiting factor if you want to upload a lot of audio (like full-length songs).
It's worth noting that lo-fi source audio wouldn't help here as the samples all get saved with the same constant bitrate. You'd need to modify the firmware's bitrate (simpler) or add audio decompression to the firmware (more complicated).
The most space-efficient option is dynamic synthesis - major bonus points if you write your own synth!
Maybe the USB port can be used to mount flash drive storage for larger sound files.
That should be possible with a little bit of hardware modification. The RP2040 supports USB host mode, but the board is configured not to power the USB port. You could allow it to power that USB port by shorting out the diode next to the USB connector - just be aware that doing so would leave any other host device (e.g. a laptop used to flash firmware) unprotected from backflow. I've done this with my own laptop & it worked fine, but your mileage may vary. If in doubt, use an isolator.

2016 YM in neutral the Cruise Control accel/decel adjusted the volume and CC cancel button muted/unmuted
That is really useful info - thanks!
The cruise control enable button on the ZE1 is bit #25 of the ACSD CAN frame and is available in the firmware as leaf_ascd_propilot.
I've just been avoiding using that button myself out of an abundance of caution, but I can't see any reason it shouldn't work.


Thanks again for the write-up - it's great to hear of the Warbler being used out in the wild! 😁
 
When electric cars hit the streets and I heard their synthetic sounds, I immediately imagined that sooner or later clever people like you would devise ways to replace the "factory" sounds with other, vastly more entertaining ones. I see that this day has arrived, and I rejoice!
I just bought a 2013 Leaf and I'll be following this thread to watch the Warbler's evolution, with a plan to put one in my car very soon.
 
The cruise control enable button on the ZE1 is bit #25 of the ACSD CAN frame and is available in the firmware as leaf_ascd_propilot.
I've just been avoiding using that button myself out of an abundance of caution, but I can't see any reason it shouldn't work.
Thanks for the feedback!
I'll go back to separate buttons for mute and mode selection, trying the CC enable button. It does toggle cruise control on and off, but since this is in neutral I can just go out of neutral to toggle CC back to original setting if I had to press it an odd number of times.

While driving last night I noticed the synth intensity drops some when letting off the accelerator. I'm trying a tweak that uses the speed as a minimum for intensity instead of always the average of speed and pedal. Also factoring in the speed more explicitly in the volume, refactoring the calculation, and starting at 10% intensity from minimal positive speed. I'll test and tweak that to ensure pedestrians can hear the car in motion. There are some Decibel requirements in the US, but I'm not sure the ratio to the Warbler's volume value.
Also I noticed and then verified in the code the 50-60-80 km/h fade out for the sound. I found it a bit annoying to still hear the sounds at those speeds. I prefer it to fade out at a lower speed threshold. In the US the legal minimum is 30 km/h (18.6 mph), so I made that the target for full intensity as a defined value, and chose 40 km/h (24.9 mph) as a fade off for silence.
Also chose silence for stopped, so that the audio doesn't bother me at stop lights. Really only want it playing at low speeds.
 
Last edited:
It's a PIA to reach the boot button while the Warbler is plugged in without removing the glovebox. Ordered a few male to female extensions (https://www.aliexpress.us/item/3256804310729374.html is the only listing I could find) to chain to make it easier to reach. Could make a single longer extension myself from male/female connectors and wires, but that is a bit tricky to crimp the small pins.

I'll wait for those to arrive before testing my firmware build so that I only have to remove the glovebox once. Already took care of the cabin air filter while I was installing the warbler.
 
Last edited:
It's a PIA to reach the boot button while the Warbler is plugged in without removing the glovebox.
Agreed. I use a homemade wiring harness extension cord myself, but I've also been playing around with the Pico USB library to make it a bit easier:
C:
#include "pico/stdio_usb.h"
//...
stdio_init_all();
That'll allow you to flash firmware using picotool without needing to reach the BOOT button:
Bash:
picotool load --execute build/warbler.uf2 -f
I'll probably include that in the next firmware release.
The downside for debugging is that if you flash a bad build it can stop picotool from working, in which case you need to get to the BOOT button again.
 
Back
Top