{"id":16623687,"url":"https://github.com/jandelgado/carl","last_synced_at":"2025-10-29T22:31:46.201Z","repository":{"id":43755983,"uuid":"357684396","full_name":"jandelgado/carl","owner":"jandelgado","description":"Carl music box","archived":false,"fork":false,"pushed_at":"2023-08-01T21:03:29.000Z","size":8871,"stargazers_count":20,"open_issues_count":0,"forks_count":3,"subscribers_count":4,"default_branch":"main","last_synced_at":"2023-08-01T22:11:39.829Z","etag":null,"topics":["arduino","dfplayer","dfplayer-mini","diy","mp3","mp3player"],"latest_commit_sha":null,"homepage":"","language":"C++","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/jandelgado.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-04-13T20:47:00.000Z","updated_at":"2023-08-01T22:11:39.830Z","dependencies_parsed_at":"2022-08-29T21:52:23.029Z","dependency_job_id":null,"html_url":"https://github.com/jandelgado/carl","commit_stats":null,"previous_names":[],"tags_count":3,"template":null,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jandelgado%2Fcarl","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jandelgado%2Fcarl/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jandelgado%2Fcarl/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/jandelgado%2Fcarl/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/jandelgado","download_url":"https://codeload.github.com/jandelgado/carl/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":219857107,"owners_count":16556074,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["arduino","dfplayer","dfplayer-mini","diy","mp3","mp3player"],"created_at":"2024-10-12T03:24:37.791Z","updated_at":"2025-10-29T22:31:45.543Z","avatar_url":"https://github.com/jandelgado.png","language":"C++","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Carl music box\n\n[![build firmware](https://github.com/jandelgado/carl/actions/workflows/build.yml/badge.svg)](https://github.com/jandelgado/carl/actions/workflows/build.yml)\n\nCarl is an MP3 player for kids. This repository hosts the firmware\nand build instructions.\n\nCarl was featured in the German edition of the Make Magazine in August 2021:\n\n\u003cp float=\"left\"\u003e\n  \u003cimg src=\".images/make_04_21.jpg\" height=300\u003e\n  \u003cimg src=\".images/carl.jpg\" height=300 alt=\"carl music box\"\u003e\n\u003c/p\u003e\n\n\u003c!-- vim-markdown-toc GFM --\u003e\n\n* [Hardware](#hardware)\n    * [Bill of Material](#bill-of-material)\n    * [Notes on the assembly](#notes-on-the-assembly)\n    * [Circuit](#circuit)\n        * [Buttons](#buttons)\n            * [Calibration](#calibration)\n        * [MP3 player module](#mp3-player-module)\n            * [Note on DFPlayer Mini Modules](#note-on-dfplayer-mini-modules)\n        * [Amplification and volume control](#amplification-and-volume-control)\n        * [Status LED](#status-led)\n        * [Power supply](#power-supply)\n        * [Wiring details](#wiring-details)\n    * [Construction of the case](#construction-of-the-case)\n    * [Artwork](#artwork)\n* [Build the firmware](#build-the-firmware)\n    * [Configuration](#configuration)\n        * [DFPlayer driver library selection](#dfplayer-driver-library-selection)\n        * [GD3200B Quirks mode](#gd3200b-quirks-mode)\n    * [Arduino IDE](#arduino-ide)\n    * [PlatformIO](#platformio)\n    * [Connecting the USB-to-Serial adapter](#connecting-the-usb-to-serial-adapter)\n* [References](#references)\n* [Author](#author)\n\n\u003c!-- vim-markdown-toc --\u003e\n\n## Hardware\n\n### Bill of Material\n\n  * wooden box for the case\n  * 1 [Arduino Pro Mini](https://www.arduino.cc/en/pmwiki.php?n=Main/ArduinoBoardProMini)\n  * 1 [DFPlayer Mini MP3 Module](https://wiki.dfrobot.com/DFPlayer_Mini_SKU_DFR0299)\n  * 1 full range speaker (4 Ohms, 10W, 10cm diameter)\n  * 1 USB Power bank (1 cell including charging and DC-DC converter)\n  * 3 arcade buttons\n  * 9 momentary buttons\n  * 1 potentiometer\n  * 1 power switch\n  * 1 LED + Resistor (220 Ohms)\n  * Resistors (1x500, 11x100, 1x1K) Ohms\n  * cables, screws, glue, metal plates\n\n### Notes on the assembly\n\nI recommend to first build and test the electronics, and if it's running, to \nbuild the case and assemble everything. The electronics can be built and tested\nstep-by-step:\n\n* Connect DFPlayer Mini to the Arduino\n* Connect the speaker to the DFPlayer\n* Connect the status-LED\n* Connect the volume control potentiometer\n* Flash the firmware\n* Connect the power bank\n* First test with the *virtual keyboard* and a testing SD-Card (see links)\n* Assemble and connect the keypad\n* Test and calibration of the keypad\n* Final test with a self-prepared SD-Card\n\nThe first test is best done with Carl's *virtual keyboad* feature, which does\nnot require the physical keypad. Carl is remote-controlled via the serial port\nper with simple key presses. For that to work, connect Carl using the serial\nconsole of the Arduino IDE with 9600 Baud. The keys `1` to `9` select a\nplaylist, `p` is the play/pause/stop button and `+` and `-` skip songs forward\nor backward. Download a pre-populated SD-Card image from the [carl-testdata\nrepository](https://github.com/jandelgado/carl-testdata) to start immediately.\n\n![SerialMonitor](.images/SerialMonitor.png)\n\n### Circuit\n\n![Schematic](.images/Bild03_schematic_handdrawn.PNG)\n\n#### Buttons\n\nThe 12 buttons are connected by a resistor network using only a single wire and\nan analog input of the Arduino. In contrast to a traditional wiring, where every\nbutton is connected individually (12 inputs needed), or using a matrix (3+4\ninputs needed), this drastically simplifies wiring and resource usage on the\nmicro controller. \n\nThe principle is as follows: if no button is pressed, the circuit is grounded and\nno current flows. If a button is pressed, the circuit will become a voltage\ndivider. Depending on which button is pressed, a different voltage is connected\nto the A2 analog GPIO of the Arduino. Carl uses the [AnalogMultiButton Library](\nhttps://github.com/dxinteractive/AnalogMultiButton) to determine which button\nwas pressed (by measuring the voltage):\n\n\u003cp float=\"left\"\u003e\n   \u003cimg alt=\"Button wiring schema\" src=\".images/Bild14_tastenschema.PNG\" height=180\u003e\n   \u003cimg alt=\"wiring detail\" src=\".images/carl_detail_playlist_taster_verdrahtung.JPG\" height=180\u003e\n   \u003cimg alt=\"push button wiring detail\" src=\".images/Bild06_carl_detail_verkabelung_skip_buttons.JPG\" height=180\u003e\n\u003c/p\u003e\n\n##### Calibration\n\nThe *AnalogMultiButton* Library used must me calibrated with the expected\nvoltages. This is because we use a network of resistors, which have tolerances.\nThe calibration is done by connecting the keypad to the Arduino and running a simple\ncalibration sketch, which measures the voltage for each key-press:\n\n```c++\nconstexpr auto PIN_BUTTONS = A2;\n\nvoid setup() {\n    pinMode(PIN_BUTTONS, INPUT);\n    Serial.begin(9600);\n}\n\nvoid loop(){\n    Serial.println(analogRead(PIN_BUTTONS));\n    delay(50);\n}\n```\n\nThe sketch must be compiled in the Arduino IDE. Afterwards upload it to the \nArduino and open the serial monitor of the Arduino IDE. Press the buttons in\nthe order of connection, starting with the `PREV SONG` button, and write \ndown the resulting values (voltages). These values must then be configured in the\n`button_values_[]` array of the [keypad.h](carl/keypad.h) source file, like e.g.:\n\n```c++\n// excerpt from keypad.h\nstatic constexpr int button_values_[] = {\n      ...\n      // add your measured 12 values here\n      323, 344, 369, 398, 431, 470,\n      517, 574, 645, 736, 857, 1023\n};\n```\n\nIn the example the butons were pressed in the order of connection and the \nvalues `323`, `344`, `369` etc. were determined using the calibration script.\n\n#### MP3 player module\n\nThe main components used are an Arduino Pro Mini and the DFPlayer Mini MP3\nmodule. The latter is controlled through a serial connection to the Arduino\nusing a simple protocol. We use a software serial implementation so we can\nstill use the builtin serial interface of the Arduino for flashing and to\nmonitor logging output. The DFPlayer Mini module provides a `busy` signal,\nwhich is fed back into the Arduino to monitor, when playback in the module is\nactive.\n\n\u003cimg alt=\"DFPlayerMini pinout\" src=\".images/DFPlayerMini.png\" height=250\u003e\n\n(See my Arduino page [for an evaluation of different MP3 modules](https://github.com/jandelgado/arduino/blob/b1bb1a1546428236d478bec674c78952836e2a1d/README.md))\n\n##### Note on DFPlayer Mini Modules\n\nDuring the tests of Carl, we encountered different DFPlayer Mini modules, which\nturned out to behave differently. DFPlayer's with the `GD3200B` chip for example\nwere found ~~**not** to work with any of the available libraries~~ to only work\nin a quirks mode.\n\nThe differences can easily be spotted and are described below.\n\n| Working                                                 | ~~Not Working~~ Working with Quirks                    |\n|---------------------------------------------------------|--------------------------------------------------------|\n| 24 pins, labeled `AA20HFJ648-94`                       | 16 pins, labeled `GD3200B`                            |\n| \u003cimg src=\".images/dfplayer_mini_good.jpg\" height=\"200\"\u003e | \u003cimg src=\".images/dfplayer_mini_bad.jpg\" height=\"200\"\u003e |\n\nThe DFPlayerMini with the `GD3200B` failed reporting correctly the number of\nsongs per folder. A Quirks mode is provided, to get these modules work with\nCarl.\n\nBesides the mentioned `GD3200B` model, there are more models out there which\nmay be incompatible, see [this site for a testing tool and further\ninformation](https://github.com/ghmartin77/DFPlayerAnalyzer).\n\n#### Amplification and volume control\n\nFor amplification, the built-in speaker amplifier (3W) of the DFPlayer Mini is\nused. This works very well even with a larger speaker as used in this project. The\nvolume is controlled indirectly by a potentiometer which output is connected to\nan analog input of the Arduino. The value of the potentiometer is used to\ncontrol the output volume of the DFPlayer Mini by sending a volume control\ncommand to the DFPlayer Mini.\n\n#### Status LED\n\nThe status LED is built into the play/pause button. It is used to give visual\nfeedback during operation. In future versions, we could add more LEDs to\nprovide some effects or more feedback. But be aware that a single LED draws\nabout 20mA, which contributes significantly to the total power consumption of\nthe player (about 90mA in operation). The LED is controlled by the\n[JLed](https://github.com/jandelgado/jled) library, which evolved as a\nside-project during development of Carl.\n\n#### Power supply\n\nA USB power bank is used as the power supply. Since these devices use a DC-DC\nstep up converter (aka boost-converter), this is more efficient then using a\nhigher rated power source (e.g. 9V battery) and stepping the voltage down using\nthe Arduino's built-in power regulator. Using a power bank also allows to easily\ncharge Carl with an off-the-shelf USB charger.\n\n\u003cimg alt=\"connecting the usb power bank\" src=\".images/carl_stromversorgung.png\"\u003e\n\n#### Wiring details\n\nInner view of Carl and the stripboard with the Arduino and DFPlayer Mini with\nthe USB-to-Serial adapter used for flashing the Arduino connected.\n\n\u003cp float=\"left\"\u003e\n    \u003cimg alt=\"inner view\" src=\".images/Bild10_carl_innen_full3.JPG\" height=180\u003e\n    \u003cimg alt=\"stripboard\" src=\".images/Bild07_bau_lochrasterplatine_mit_arduino_und_dfplayer.JPG\" height=180\u003e\n    \u003cimg alt=\"push button wiring detail\" src=\".images/bau_lochrasterplatine_rueckseite.JPG\" height=180\u003e\n\u003c/p\u003e\n\n### Construction of the case\n\nWhile the electronics are straight forward, the case was by far the most time\nconsuming part of the project (at least for me...). It was built of an old box\nI had left over from a packaging of two bottles of wine. At first I shorted\nthe box little, then I finished the wood with sandpaper. Next the drillings for\nthe 3 big buttons and the opening for the speaker were made. The holes for the\nbig arcade buttons were drilled using an 1-inch forstner drill.\n\n\u003cp float=\"left\"\u003e\n  \u003cimg alt=\"original case\" src=\".images/Bild04_bau_gehaeuse_weinkiste.JPG\" height=200\u003e\n  \u003cimg alt=\"case\" src=\".images/Bild05_bau_gehaeuse_rohbau_ohne_bohrungen.JPG\" height=200\u003e\n  \u003cimg alt=\"case\" src=\".images/bau_einpassen_tastenfeld.JPG\" height=200\u003e\n\u003c/p\u003e\n\nDetails of the key panel for the playlist selection with 9 momentary buttons:\n\n\u003cp float=\"left\"\u003e\n    \u003cimg alt=\"\" src=\".images/bau_blech_fuer_tastenfeld.JPG\" height=130\u003e\n    \u003cimg alt=\"\" src=\".images/bau_schablone_tastenfeld.JPG\" height=130\u003e\n    \u003cimg alt=\"\" src=\".images/bau_blech_tastenfeld_mit_bohrungen.JPG\" height=130\u003e\n    \u003cimg alt=\"\" src=\".images/bau_tastenfeld_vorderseite.JPG\" height=130\u003e\n\u003c/p\u003e\n\nDetails of the back cover plate, which is mounted with 2 screws that can be \nremoved easily without any tools:\n\n\u003cp float=\"left\"\u003e\n    \u003cimg alt=\"detail of the back cover\" src=\".images/carl_rueckseite1.JPG\"i height=200\u003e\n    \u003cimg alt=\"detail of the back cover plate mount\" src=\".images/Bild08_carl_detail_befestigung_deckel.JPG\" height=200\u003e\n\u003c/p\u003e\n\n### Artwork\n\nThe artwork was applied to the case using the so called *acrylic transfer\nmethod*.  Basically it works as follows:\n  * laser print your artwork. The method will not work with ink printed\n    material. Note, that during transfer, the image will be mirror-inverted\n  * apply the acrylic medium to the wood, and put the printout with the printed\n    side on it and carefully press it on the acrylic medium\n  * wait until it the acrylic medium is dry (24 hours)\n  * with a sponge and water, carefully rub of the paper\n  * the toner is is now permanently transferred to the acrylic medium\n  * for fixation, apply a layer of wood glue or acrylic medium on the\n    transferred image\n\n\u003cp float=\"left\"\u003e\n  \u003cimg alt=\"arcyl transfer in progress\" src=\".images/Bild11_bau_acryl_transfer_vorlagen_aufgetragen.JPG\" height=180\u003e\n  \u003cimg alt=\"arcyl transfer removal of paper\" src=\".images/Bild12_bau_acryl_transfer_papier_entfernen.JPG\" height=180\u003e\n  \u003cimg alt=\"arcyl transfer result\" src=\".images/Bild13_carl_artwork1.JPG\" height=180\u003e\n\u003c/p\u003e\n\n## Build the firmware\n\nThe firmware can be built using the Arduino IDE or PlatformIO.\n\n### Configuration\n\nThe firmware image can be configured either in [config.h](carl/config.h) (for Arduino IDE) or\nin [platform.ini](carl/platform.ini). The following options can be configured:\n\n| Option                     | `#define`                    | Default                             |\n|----------------------------|------------------------------|-------------------------------------|\n| Disable logging            | `NO_LOGGING`                 | unset, i.e. logging is enabled      |\n| Enable configuration mode  | `ENABLE_CONFIG_MODE`         | unset, i.e. config mode is disabled |\n| Support large folders      | `USE_LARGE_FOLDERS`          | disabled                            |\n| Use PowerBroker's driver   | `USE_POWERBROKER_MP3_DRIVER` | this is the default                 |\n| Use Makunas's driver       | `USE_MAKUNA_MP3_DRIVER`      |                                     |\n| Use DFRobot's driver       | `USE_DFROBOT_MP3_DRIVER`     |                                     |\n| Enable GD3200B Quirks Mode | `GD3200B_QUIRKS`             | unset                               |\n\n#### DFPlayer driver library selection\n\nChoose one of the `USE_*_MP3_DRIVER` options. If not set, the PowerBroker\ndriver will be used. When the firmware is build using platformio (i.e. using\n`make`) the required libraries are downloaded automatically.  When using the\nArduino IDE, don't forget to install the actual library used, e.g.:\n* [DFPlayerMini_Fast](https://github.com/PowerBroker2/DFPlayerMini_Fast) and [FireTimer](https://github.com/PowerBroker2/FireTimer) for `USE_POWEBROKER_MP3_DRIVER`\n* [DFMiniMp3](https://github.com/Makuna/DFMiniMp3) for `USE_MAKUNA_MP3_DRIVER` (recommended for GD3200B models)\n* [DFRobotPlayerMini](https://github.com/DFRobot/DFRobotDFPlayerMini) for `USE_DFROBOT_MP3_DRIVER`\n\n#### GD3200B Quirks mode\n\nWhen using `GD3200B` based DFPlayer modules, the `GD3200B_QUIRKS` `#define` has\nto be set in order to circumvent some incompatibilities (bugs?) these devices\nhave.  I successfully tested a `GD3200B` DFPlayer using the Makuna-Driver\n(`USE_MAKUNA_MP3_DRIVER`) and the quirks mode enabled. Check the log output\nto make sure that the `GD3200B` quirks mode is enabled on startup:\n\n```\n0(1412): carl starting.\n0(1379): using Makuna driver\n61(1321): m scanning folders...\n62(1319): m enabling GD3200B quirks mode\n```\n\n### Arduino IDE\n\nCheck out the repository on your computer. In the Arduino IDE select `Open ...`\nunder the `File` menu and select the file `carl/carl.ino`.\n\nSelect `Arduino Pro or Pro Mini` as the target board under `Tools` \u003e `Board` \u003e\n`Arduino AVR Boards`. The processor used is an `Atmega328P 5V 16MHz`.\n\nInstall the needed libraries using `Sketch` \u003e `Include Library` \u003e `Manage Libraries...`:\n* AnalogMultiButton (1.0.0)\n* DFPlayerMini_Fast (1.2.4) (Powerbroker DFPlayer Library)\n* JLed (4.9.0)\n* log4arduino (1.1.0)\n\nAlternatively, install the libraries with this command:\n```\narduino --install-library JLed:4.9.0,log4arduino:1.1.0,AnalogMultiButton:1.0.0,DFPlayerMini_Fast:1.2.4,FireTimer:1.0.5\n```\n\nCompile and upload the sketch using the corresponding commands in the Arduino\nIDE.\n\n### PlatformIO\n\nCheck out the repository on your computer. Then `cd carl/carl` and run one of\n\n* `make upload-dfrobot \u0026\u0026 make monitor`\n* `make upload-makuna \u0026\u0026 make monitor`\n* `make upload-powerbroker \u0026\u0026 make monitor`\n\nto build and upload the firmware and to start the serial monitor. The different\ncommands correspond to the different drivers for the DFPlayerMini module that\ncan be used: `DFRobot`, `Makuna` and `PowerBroker2`. Test the different drivers\nin case you have problems getting your module running. When building with\nthe Arduino IDE, the PowerBroker2 driver is used by default.\n\n### Connecting the USB-to-Serial adapter\n\nSince the Arduino Pro Mini has no USB port, we need to connect an USB-to-Serial\nadapter to flash the Arduino:\n\n\u003cimg src=\".images/Bild15_carl_flashing.PNG\" height=250\u003e\n\n\n## References\n\n* [DFRobot DFPlayer Mini]()\n* [Carl testdata generator](https://github.com/jandelgado/carl-testdata/)\n* [DFRobot DFRobotDFPlayerMini Library](https://github.com/DFRobot/DFRobotDFPlayerMini)\n* [Makuna DFMiniMp3 Library](https://github.com/Makuna/DFMiniMp3)\n* [Powerbroker2 DFPlayerMini_Fast Library](https://github.com/PowerBroker2/DFPlayerMini_Fast)\n* [JLed](https://github.com/jandelgado/jled)\n* [log4arduino](https://github.com/jandelgado/log4arduino)\n* [DFPlayer Analyzer](https://github.com/ghmartin77/DFPlayerAnalyzer)\n* [GD3200 information](https://discourse.voss.earth/t/dfplayer-verschiedene-versionen/681/178)\n\n## Author\n\n(C) Copyright 2021-2022 by Jan Delgado.\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjandelgado%2Fcarl","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjandelgado%2Fcarl","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjandelgado%2Fcarl/lists"}