Micro Remote Control

by Markus Opitz in Circuits > Arduino

4482 Views, 54 Favorites, 0 Comments

Micro Remote Control

MicroRemoteControl_Titel.jpg
LED2.gif

I often need a remote control for many of my projects: vehicles, robots, cameras...

But a large remote control is often unnecessary and too big. Funny when the remote control is bigger than the racing car. And you constantly need new batteries.

This is the further development of my first remote control, this time with a small XIAO ESP32-C6. It is tiny, has WiFi and BLE on board, and also a LiPo charging circuit.

ESP32 + joystick + battery = a super-small recharchable remote control with direction and a button

In a simple quick test, I was able to transmit a signal over 95 meters!


ESP-NOW

It is a radio communication protocol by Espressif that allows different ESP32 or ESP8266 boards to exchange small packets of data without using regular Wi-Fi or Bluetooth. ESP-NOW does not need a WiFi station like a router, making it ideal for us to transmit and receive remote control signals. It usually needs less energy and has a longer range than WiFi.


Please note: Basic knowledge of Arduino IDE is required.

Supplies

1-IMG_20260128_221235_HDR.jpg

XIAO ESP32-C6 (or ESP32-C3) + Antenna

Joystick KY-023

LiPo battery (110mAH)

switch

3D printed case

The Circuit

Circuit2.jpg
3-IMG_20260129_214222.jpg
4-IMG_20260129_214234.jpg
2-IMG_20260129_213816_HDR.jpg

The circuit is quite simple. We solder the battery connections to the underside of the ESP-C6. I use plug contacts. Please never solder the battery connections directly to the ESP to avoid short circuits. The ESP32-C6 also acts as a charge controller for the battery. A switch in front of the battery allows the device to be turned on and off.

Since we are using a battery, there is no power at the 5V connection of the microcontroller. Therefore, we connect the VCC of the joystick to the 3.3V of the controller.

VCC —> 3.3V

GND —> GND

X —> D1

Y —> D2

Button —> A0

The pins can also be assigned differently; please change them accordingly in the software!

The Software

TRANSMITTER


The software establishes an ESP-NOW connection via WiFi. ESP-NOW is a simple communication protocol with a range that is usually greater than normal WiFi with its complex protocols.

In a simple quick test, I was able to achieve more than 95 meters!

Preliminary work: In order to reach the correct receiver, its MAC address must first be determined. The script determines the MAC address on a XIAO ESP32-C6. Determine, note down, and enter it in the transmitter script.

The software measures the values on the joystick and its button and transmits them. In addition, a sleep function could be added to conserve battery power. (Not yet implemented here).

/*
===================
Markus Opitz 2026
instructables.com
===================

ESP-NOW Transmitter
*/


#include <WiFi.h>
#include <esp_now.h>

// ================== adjust! ==================
uint8_t receiverMac[] = { 0x__, 0x__, 0x__, 0x__, 0x__, 0x__ };
// ==============================================


#define JOY_X_PIN A1
#define JOY_Y_PIN A2
#define BTN_PIN D0

// Schwellen
const int center = 1650;
const int deadzone = 100;

// Datenstruktur
typedef struct {
uint16_t servo;
bool left;
bool right;
bool button;
} ControlData;

ControlData data;

void setup() {
Serial.begin(115200);

pinMode(BTN_PIN, INPUT_PULLUP);

WiFi.mode(WIFI_STA);

if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init fail");
return;
}

esp_now_peer_info_t peerInfo = {};
memcpy(peerInfo.peer_addr, receiverMac, 6);
peerInfo.channel = 0;
peerInfo.encrypt = false;

esp_now_add_peer(&peerInfo);

Serial.println("transmitter ready");
}

void loop() {
int x = analogRead(JOY_X_PIN);
int y = analogRead(JOY_Y_PIN);

if (abs(y - center) < deadzone) {
x = center;
}
data.servo = map(y, 0, 3280, 0, 180);
data.servo = constrain(data.servo, 0, 180);

data.left = (x < center - deadzone);
data.right = (x > center + deadzone);
data.button = (digitalRead(BTN_PIN) == LOW);

//Serial.print(x); Serial.print(" ");
Serial.print(y);
if (digitalRead(BTN_PIN) == LOW) Serial.print(" button");
Serial.println("");
/*
if (x<-10) Serial.println(" <--");
if (x>10) Serial.println(" -->");
if (y>10) Serial.println(" ^ ");
if (y<-10) Serial.println(" ~ ");
*/

esp_now_send(receiverMac, (uint8_t*)&data, sizeof(data));

delay(30); // ~33 Hz
}


RECEIVER

The receiver (here also an ESP32-C6) picks up the signals and converts them into corresponding commands. A servo (up/down signals) and an LED with a 220 ohm series resistor are connected here. In addition, all other features of the microcontroller can be used.


/*
===================
Markus Opitz 2026
instructables.com
===================

ESP-NOW Receiver
*/


#include <WiFi.h>
#include <esp_now.h>

// Data structure (MUST be identical!)
typedef struct {
uint16_t servo;
bool left;
bool right;
bool button;
} ControlData;

ControlData data;

#include <ESP32Servo.h>
Servo R1;
const int servoPinR1 = D2;
int currentAngle = 90;
const int LEDpin = D7;
bool lastButtonState = false;


void onReceive(const esp_now_recv_info *info,
const uint8_t *incomingData,
int len) {

ControlData data;
memcpy(&data, incomingData, sizeof(data));

R1.write(data.servo);
Serial.println(data.servo);

if (data.left) {Serial.print("LEFT "); }
if (data.right) {Serial.print("RIGHT "); }
if (data.button && !lastButtonState) {
Serial.println("button");
digitalWrite(LEDpin, HIGH);
}
if (!data.button && lastButtonState) {
digitalWrite(LEDpin, LOW);
}

lastButtonState = data.button;
Serial.println();
}

void setup() {
Serial.begin(115200);

WiFi.mode(WIFI_STA);

if (esp_now_init() != ESP_OK) {
Serial.println("ESP-NOW init failed");
return;
}

esp_now_register_recv_cb(onReceive);

Serial.println("receiver ready");

// ESP32-C6 PWM Setup
R1.setPeriodHertz(50); // 50 Hz for Servos
R1.attach(servoPinR1, 500, 2400);
R1.write(90); delay(10);
Serial.println("servo ready");

pinMode(LEDpin, OUTPUT);
digitalWrite(LEDpin, LOW);
}

void loop() {
// all happens in callback
}

ESP-NOW or BLE?

Alternatively, a connection with BLE signals using the same setup would be possible. However, the range is likely to be somewhat shorter.

The Case & Assembling

9-Haus.jpg
5-IMG_20260201_154434_HDR.jpg


Wood or cardboard would be an alternative for a housing. I opted for a space-saving 3D print, designed with the help of Tinkercad. The lid fits perfectly, but without a fastening device (it stays in place anyway).

First solder all the necessary contacts with wires that are not too long. Since no high currents flow, the wires can be thin. Insert the individual parts, removing the black button from the joystick beforehand. Don't forget to connect the antenna to the ESP32. Secure the individual parts sparingly with hot glue.


Downloads

Bonus: a Smaller Knob

6-IMG_7826.JPG
10-Knopf.jpg

To reduce the size, I designed a smaller, simpler button using TinkerCAD. Just clip it on, glue it down... works perfectly.

Downloads

Universal Usage

Micro Remote Control #shorts