Cheap Yellow Display – based Solfeggio Tone Generator

Posted 21 January 2026

My wife recently asked me if I could build a ‘Solfeggio’ tone generator that she could listen to as a sleep aid. A quick net search yielded the following:

Solfeggio frequencies are a set of specific tones believed to promote healing, relaxation, and balance. The primary nine frequencies range from 174 Hz to 963 Hz, each associated with different benefits, such as emotional healing, stress reduction, and chakra alignment.

963 Hz: Connection to the divine and awakening.
These frequencies can be used in sound therapy and meditation practices to enhance well-being.

174 Hz: Pain relief and grounding.

285 Hz: Healing tissue and organs.

396 Hz: Liberating guilt and fear.

417 Hz: Facilitating change and undoing situations.

528 Hz: Transformation and DNA repair.

639 Hz: Enhancing communication and relationships.

741 Hz: Awakening intuition and problem-solving.

852 Hz: Returning to spiritual order.

As a result of a previous project to create a GPS-enabled DashCam Power Switch, I thought this would be a perfect ‘Cheap Yellow Display project. The Cheap Yellow Display (CYD) is a ESP32-2432S028R development board integrated with a 240×320 pixel color touch-sensitive display. In the case of my DashCam project, this meant that I only needed a GPS module, a low-Rds MOSFET, and a bit of circuitry to make it all work – neat. For this tone generation project, it looked like I might be able to do the whole thing with just a CWD and a pair of BT earbuds, as the ESP32-2432S028R dev board incorporates BT capability. The wife already had a pair of BT earbuds, and I had acquired two more CYD modules after it worked so well for my DashCam, so I was all set.

As I did with the DashCam project, I started consulting with Grok right away. If you haven’t yet taken advantage of this – you should – Not only can Grok code in any language, it is also mind-bogglingly fast for internet searches on particular topics. So I started out with this conversation:

Me: I want to build a rechargeable battery-operated tone generator using the ESP32/CYD configuration. I would like the battery to be the same (or smaller) width/length as the CYD. The input to the charging circuit would be +5V from the Type-C connector on the CYD. What battery and charging circuit would you suggest?

Grok: For a rechargeable battery-operated tone generator using the ESP32-based Cheap Yellow Display (CYD), which measures approximately 50mm x 86mm, you’ll want a compact 3.7V LiPo battery that fits within those dimensions for easy integration (e.g., mounted behind the board). The tone generator can use the ESP32’s built-in DAC (8-bit resolution) or PWM for audio output, connected to a small speaker or amp. Power management involves charging the battery via the CYD’s USB-C (which supplies 5V) and boosting the battery voltage to 5V for the board when unplugged, as the CYD expects 5V input on its power pins.Suggested BatteryA 3.7V 1000mAh LiPo battery with JST connector, such as a 603450 cell or equivalent.

Why this? It provides 3-5 hours of runtime for a low-power tone generator (ESP32 + display draws ~200-300mA at 5V under load; enable deep sleep modes to extend life). It’s widely available, rechargeable, and includes built-in protection (PCM) against overcharge/discharge. Smaller options like 300-500mAh (e.g., 402030 at 40mm x 20mm x 3mm) work if runtime isn’t critical, but 1000mAh balances size and capacity for ESP32 projects. ezsbc.shop +3 Avoid larger capacities (e.g., 3000mAh) if they exceed ~65mm x 35mm, as they may not fit neatly.

Dimensions: Approximately 60mm x 34mm x 5mm (fits well within 86mm x 50mm, leaving room for wiring).

Suggested Charging Circuit: Use a TP4056-based module with integrated battery protection (BMS).

  • Why this? It’s a simple, inexpensive ($1-2) 1A charger for single-cell LiPo batteries, accepting 5V input directly from the CYD’s USB-C (via wires to the module’s IN+ / IN- pads). It handles charging to 4.2V safely and includes overcharge/over-discharge protection. When USB-C is plugged in, it charges the battery; when unplugged, the module’s OUT+ / OUT- pads provide battery voltage (3.7V)
  • Additional component needed: Pair it with a small boost converter like the MT3608 (adjustable to 5V output) connected to the TP4056’s OUT pads. This boosts the 3.7V battery voltage to 5V for the CYD’s 5V pin (avoid direct 3.7V connection, as the board’s regulator expects 5V for stable operation). github.com +2 Add a switch on the boost output for power control.

There was some back-and-forth to nail down the actual modules I would need, but pretty soon I had the battery (li-ion 603450), charger (TP4056) and DC-DC converter (MT3608) on order from Amazon. The reason I went with separate charger and up-converter modules instead of the IP5306 all-in-one is due the IP5306 requiring a minimum load current to remain active, and this would conflict with my plan to put the ESP32 to sleep during idle times to extend battery life.

After getting the hardware issues resolved, the next step was the ESP32 software. I had Grok develop the software using Arduino code, with the following specs:

Me: Referencing our discussion of my ESP32 CYD Sinewave Tone Generator Project, I would like to see your take on Arduino code for the ESP32, with the following specs:

  1. Non-K&R bracket convention (beginning bracket on new line)
  2. Nine (9) touch-sensitive radio buttons for the ‘Solfeggio frequencies’ (https://www.bing.com/search?q=complete+list+of+solfeggio+frequencies&FORM=R5FD1).
  3. A volume slider (horizontal at the bottom or vertical on the side)
  4. Tone output directed to Bluetooth transmitter
  5. Sleep mode after 10 minutes from coming out of sleep mode
  6. Battery charge indicator based on A/D measurements of the LiPo battery voltage
  7. Whatever other obvious requirement that I have failed to mention

Within a few seconds, Grok produced the following code:

Not only did Grok produce initial code, but it helped me work through some subtle issues with the ‘AudioTools’ library as I had not used this library before. Grok would offer code, then I would run (or try to run) and report back on any errors encountered. Pretty soon I had code that compiled cleanly and ran, and then it was a case of exercising the code and reporting any debug output back to Grok. This went around for a while, but we eventually got to working code. I learned that while Grok is very fast, he’s not always all that accurate. For anything other than the most trivial programming task, the human at the other end of the conversation must have relevant experience. At one point in the debugging process, Grok was recommending some hardware changes on the CYD board, but I knew from prior experience with the DashCam project that no such mods were required for detecting user touches on the touch-screen. So I was able to provide Grok with a small working program to do this and Grok was happy to incorporate the new information into the complete program. This, however, brought up another ‘gotcha’. Grok takes input from the human, thinks for a few seconds, and then disgorges another complete program – without any accompanying explanation. So, I said “what was the problem with the previous code?” and got a pretty comprehensive answer- yay.

Grok really doesn’t do a very good job of troubleshooting or code debug at all – that’s where the human’s engineering experience comes in. At one point I tried to describe the ‘cut the world in two’ troubleshooting technique I have been using for decades, but I’m not sure if Grok has any ability to remember things like that, or any ability to apply them, so I suspect that was a waste of time. Grok will continue to produce code without explanation if you let it – kind of a ‘random walk’ shotgun approach AFAICT. At the end of this hours-long session, I got kind of frustrated with this behavior and terminated the session. I put up a DM to @xAI, but never got a response.

Eventually, over a 2-3 day period we got a working program that would connect via BT to my wife’s earbuds and play the tone (with some ‘reverb’ added, even!) selected by tapping a button on the CYD screen.

This program worked fine, but had a few problems:

  • The ESP32 ‘deep sleep’ mode was problematic. The mode itself worked fine (and dropped the current drain down to just a few mA, but when the system came back awake, it wouldn’t reconnect to the BT earbuds. We eventually wound up using the ‘light sleep’ mode, which would reliably reconnect to the earbuds, but drew significantly more current (less battery life).
  • The earbuds themselves were an issue. When/if the system failed to reconnect, then only way to do so was to put the earbuds back in their charging container and force them back into ‘pairing’ mode so the tone generator box could ‘see’ them again, and this was a PITA.

These issues led my wife to ask if I could change the project to use wired earbuds rather than wireless. This made the design both simpler and more complex. Simpler because now ‘sleep’ wouldn’t be an issue as the wired earbuds eliminated the need to connect via BT. More complex, because the CYD has no native stereo output, so an additional module to convert I2S protocol stereo audio data to human-audible stereo sound was required, and in turn this required finding a third output-enabled GPIO line (the CYD configuration uses most of the ESP32’s GPIO lines to run the display), and this required cutting a board trace and running a jumper to access GPIO26.

Here’s my statement to Grok:

Me: referencing our CYD Tone Generator project, I want to modify it to use plug-in wired earbuds rather than BT. I believe this will require outputting the audio on two GPIO lines (22 & 27)? and implementing an audio amplifier and a volume control. Can you recommend a good audio amplifier package for this?

Grok immediately identified a really nice module:

Grok: I recommend the PCM5102A I2S DAC module (often labeled as “PCM5102 DAC Decoder” or similar). It’s a compact, affordable breakout board widely used in ESP32 audio projects for its simplicity and good sound quality (32-bit, up to 384kHz sampling). Many versions include a built-in 3.5mm headphone jack, making it plug-and-play for wired earbuds without additional soldering for the connector.

Why this one?

Directly interfaces with ESP32 I2S output (no need for the internal DAC on GPIO 25/26).

Provides line-level analog output that can drive most earbuds (16–32Ω impedance) at reasonable volumes without distortion—users commonly report success with direct connection for low-power applications like tones.

Low noise, high SNR (112dB), and minimal external components needed.

Cheap and available: ~$5–10 on Amazon, AliExpress, or electronics sites like Adafruit/SparkFun (search for “PCM5102 I2S DAC module”).

If your earbuds are very sensitive or you need more headroom, some variants include an integrated headphone amplifier (e.g., based on LM4880M—look for “PCM5102 with headphone amp” on Tindie or AliExpress for ~$10–15).

Connections (assuming standard I2S remapping in code):

VCC: 3.3V from ESP32.

GND: Shared ground.

BCLK (bit clock): Connect to your GPIO 22 (or remap as needed).

LRCK/WS (word select/left-right clock): You’ll likely need a third GPIO (e.g., 25 or 26) for this—add it if not already in your setup.

DIN/SDIN (data in): Connect to your GPIO 27.

FMT, FLT, DMP, SCL: Ground these (or leave default for standard I2S format).

XMT/XSMT: 3.3V (unmutes the output).

Analog out: Directly to 3.5mm jack for earbuds.

So I got a couple of the PCM5102A I2S DAC modules from Amazon, and wired them up according to Grok’s instructions. 3.3V, Gnd, BCLK, DIN all came from CN1 on the CYD, but I had to cut a trace to free GPIO26 from it’s normal connection through an audio amp to the ‘speaker’ connector so I could use it for LRCK. See below for the details:

Here’s the program:

This all worked really well, except for one last major ‘gotcha’. We used GPIO35 (input only) to monitor the battery voltage, and implemented a small ‘slider’ style battery charge indicator at the very top of the display. A call to ‘analogRead()’ in loop() measured battery voltage, and this value was depicted by the length and color of the ‘slider’ display. Unfortunately it turned out that the ESP32 library required to run the PCM5102A DAC module conflicted with the Arduino library used for ‘analogRead()’ calls. As hard as this was to believe, it was real, and neither Grok nor I could figure any way around it. So, we wound up using ‘digitalRead()’ instead (which obviously will only return a ‘0’ or ‘1’) and displaying either a full-length green slider (battery good) or a full-length red slider (battery bad).

And the schematic:

Leave a Reply

Your email address will not be published. Required fields are marked *