Community project
Build Me Complete Schematic Esp-idf Firmware Ske
This guide walks through building a complete ESP32-based audio device with rotary encoder volume control and push-button inputs. The project combines an 18650 Li-ion battery, 8Ω speaker, KY-040 rotary encoder module, and push buttons into a functional unit powered by ESP-IDF firmware.
The guide provides a complete wiring diagram, detailed assembly steps, parts list, and ready-to-use ESP-IDF firmware. Follow the step-by-step instructions to connect the battery and speaker, adapt the GPIO headers, wire the volume knob and buttons, then power up and test the assembled device.
Wiring diagram

Gather all the parts
| Qty | Component |
|---|---|
| 1 | 3.6 V nominal, 3500 mAh 18650 lithium-ion cell, nominal 3.7 V, ~2500 mAh. Common for higher-capacity portable / battery-bank style projects; needs a holder and protection / charger circuit. |
| 1 | 8 Ω, 0.5 W minimum Generic small 8Ω 0.5-3W loudspeaker (~28mm typical). Pair with an I2S amp (MAX98357A) or class-D amp (TPA3116D2) for usable volume; do not drive directly from a GPIO pin. Audio output for music/voice playback. |
| 1 | EC11, 15 mm 5-pin incremental rotary encoder breakout with integrated momentary push switch. CLK and DT are the quadrature outputs; SW is the built-in push-button output and should not be modelled as a separate Push Button component. |
| 1 | 6×6 mm tactile Momentary push button switch |
| 1 | 6×6 mm tactile Momentary push button switch |
| 1 | 6×6 mm tactile Momentary push button switch |
| 1 | 1.27 mm to 2.54 mm GPIO Header Adapter Cable 1.27 mm → 2.54 mm, 8-position minimum A passive pitch-converter cable that lets the board’s small 1.27 mm GPIO header connect to ordinary 2.54 mm jumper wires. |
Assemble it in 6 steps
1. Check the board version and sockets
Use only a board whose back silkscreen says Rev2.0. Find the narrow 28-pin 1.27 mm GPIO header, the white SH1.0 speaker socket, and the two-pin MX1.25 battery socket. Do not connect ordinary 2.54 mm jumper plugs directly to the narrow GPIO header.
- The V2 has no black rotary knob; the separate EC11 part is required.
- Set the board Battery Switch off before connecting the battery.
- Using a 2.54 mm jumper directly on the 1.27 mm header can bend or short the tiny pins.
2. Connect battery and speaker
Plug the Molicel lead into the board’s MX1.25 battery socket with red on BAT+ and black on BAT−. Plug the speaker cable into the SH1.0 socket; the board socket uses pins 1 SPK+ and 2 SPK−, while pins 3 and 4 are unused.
- The keyed plugs should slide in without force.
- The included 8 Ω speaker is the safer backup choice for this first build.
- Do not reverse the battery lead — reversed battery power can damage the board.
- Do not connect either speaker wire to GND; both wires go only to the SH1.0 speaker socket.
3. Fit the GPIO adapter
Plug the 1.27 mm side of the adapter into the board’s 28-pin GPIO header, then use the 2.54 mm side as the landing point for the M-F jumper leads. This adapter is in-line between the board header and every external control wire.
- If a small adapter came in the Waveshare box, compare its pitch before using it.
- Keep the adapter strain-relieved so it cannot pull sideways on the fine-pitch header.
- A shifted adapter position can put a signal onto the wrong board pin and can damage the board.
4. Wire the volume knob
Wire the EC11 from the adapter: VCC → 3V3 (power), GND → GND (ground), A/CLK → GPIO6 (turn signal), B/DT → GPIO7 (turn direction signal), and SW → GPIO8 (push signal).
- The firmware turns on pull-ups, so no separate resistors are needed for the knob.
- Use five separate jumper leads and keep A and B beside each other to make tracing easier.
- Do not use GPIO2 or GPIO15 for the knob — those are already needed by the onboard audio hardware.
5. Wire the three buttons
Put each 6×6 mm button across the breadboard’s center gap. Join one leg of each button to one shared GND wire (ground). Connect the other legs: Cancel → GPIO9 (cancel signal), Action → GPIO12 (talk/action signal), Back → GPIO13 (back signal).
- On a tactile switch, the two legs on the same side are already joined; use legs from opposite sides.
- A press is read when the GPIO is connected to the shared GND wire.
- If a button is rotated 90 degrees incorrectly, both wires may land on already-connected legs and the button will never change state.
6. Power and test the assembled unit
Place the board, speaker, knob, and buttons where they cannot short against metal. Turn on the Battery Switch, plug USB-C into a 5 V 1 A wall adapter, and then use the board’s USB connection for deployment.
- USB-C is the normal power source; the battery is the deep-sleep backup and charges through the board.
- Build one unit fully first, then repeat the same wire colors and layout for the other two.
- Make sure VCC and GND are not swapped — swapped power can damage the board or external controls.
Review all connections
1. Connections between "gpio_adapter" and "ESP32"
| Function | gpio_adapter | ESP32 |
|---|---|---|
| power | 3V3 | 3V3 |
| ground | GND | GND |
| data | GPIO6 | GPIO 6 |
| data | GPIO7 | GPIO 7 |
| data | GPIO8 | GPIO 8 |
| data | GPIO9 | GPIO 9 |
| data | GPIO12 | GPIO 12 |
| data | GPIO13 | GPIO 13 |
2. Connections between "encoder" and "ESP32"
| Function | encoder | ESP32 |
|---|---|---|
| power | VCC → 1.27 mm to 2.54 mm GPIO Header Adapter Cable 3V3 | EXT |
| ground | GND → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GND | EXT |
| digital | CLK → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO6 | EXT |
| digital | DT → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO7 | EXT |
| digital | SW → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO8 | EXT |
3. Connections between "button_cancel" and "ESP32"
| Function | button_cancel | ESP32 |
|---|---|---|
| digital | SIGNAL → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO9 | EXT |
| ground | GND → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GND | EXT |
4. Connections between "button_action" and "ESP32"
| Function | button_action | ESP32 |
|---|---|---|
| digital | SIGNAL → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO12 | EXT |
| ground | GND → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GND | EXT |
5. Connections between "button_back" and "ESP32"
| Function | button_back | ESP32 |
|---|---|---|
| digital | SIGNAL → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GPIO13 | EXT |
| ground | GND → 1.27 mm to 2.54 mm GPIO Header Adapter Cable GND | EXT |
6. Connections between "speaker" and "ESP32"
| Function | speaker | ESP32 |
|---|---|---|
| analog | POS → Board SH1.0 speaker socket pin 1 (SPK+) | EXT |
| analog | NEG → Board SH1.0 speaker socket pin 2 (SPK−) | EXT |
7. Connections between "battery_18650" and "ESP32"
| Function | battery_18650 | ESP32 |
|---|---|---|
| power | +V → Board MX1.25 battery socket pin 1 (BAT+, red) | EXT |
| ground | GND → Board MX1.25 battery socket pin 2 (BAT−, black) | EXT |
Deploy the firmware
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/i2c_master.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_netif.h"
#include "nvs_flash.h"
#include "board_pins.h"
void input_handler_init(void);
void audio_capture_init(void);
void audio_playback_init(void);
void display_renderer_init(void);
void display_renderer_set_mood(unsigned mood);
void ws_client_start(void);
void power_mgr_init(void);
static const char *TAG = "home_companion";
static void i2c0_init(void)
{
i2c_master_bus_config_t cfg = {
.i2c_port = I2C_NUM_0, .sda_io_num = PIN_I2C0_SDA,
.scl_io_num = PIN_I2C0_SCL, .clk_source = I2C_CLK_SRC_DEFAULT,
.glitch_ignore_cnt = 7, .flags.enable_internal_pullup = true,
};
i2c_master_bus_handle_t bus = NULL;
ESP_ERROR_CHECK(i2c_new_master_bus(&cfg, &bus));
ESP_LOGI(TAG, "I2C0 ready: CST816=0x%02X TCA9554=0x%02X RTC=0x%02X IMU=0x%02X ES8311=0x%02X ES7210=0x%02X", I2C_ADDR_CST816, I2C_ADDR_TCA9554, I2C_ADDR_PCF85063, I2C_ADDR_QMI8658, I2C_ADDR_ES8311, I2C_ADDR_ES7210);
}
static void network_init(void)
{
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
/* Provision Wi-Fi credentials into encrypted NVS before field deployment. */
}
void app_main(void)
{
ESP_ERROR_CHECK(nvs_flash_init());
i2c0_init();
power_mgr_init();
input_handler_init();
audio_capture_init();
audio_playback_init();
display_renderer_init();
display_renderer_set_mood(0);
network_init();
ws_client_start();
ESP_LOGI(TAG, "Home Companion v0.3 POC initialized");
for (;;) vTaskDelay(pdMS_TO_TICKS(1000));
}Remix this project
Make it yours in one click
Open a full copy of this project in your own Schematik workspace — diagram, code, parts, and assembly steps included. Swap the sensor, add features, or redesign the whole thing with AI. The author's original stays untouched.




