ESP32 Remote

Description:

Transmits fixed-code SubGHz Flipper Zero raw signals. Based on the ESP32 microcontroller and CC1101 transceiver.

  • Compatible with Flipper Zero SubGHz raw recordings.
  • Rechargeable lithium battery.
  • Battery charge indicator: Green indicates more than 10%, red indicates less than 10% battery remaining.

Schematic

Footprint

3D Model

Source Code

#include <Adafruit_NeoPixel.h>
#include "driver/rtc_io.h"
#include <ELECHOUSE_CC1101_SRC_DRV.h>
//SPI Connection
byte sck = 5;
byte miso = 21;
byte mosi = 19;
byte ss = 33;
//TX & RX Pins
#define GDO0 32
#define GDO2 4
//Button
#define btn 38
//Battery Voltage Pin
#define VBATPIN 35
//Neopixel Config
#define neoPixelPin 0
#define numPixels 1
Adafruit_NeoPixel pixels(numPixels, neoPixelPin, NEO_GRB + NEO_KHZ800);
int rawRecording[] = { -5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -5000, 1000, -5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -2000, 1000, -8000, 1000, -2000, 1000, -8000, 1000, -2000, 1000, -9000,
-5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -5000, 1000, -5000, 1000, -5000, 1000, -2000, 1000, -5000, 1000, -5000, 1000,
-8000, 1000, -2000, 1000, -8000, 1000, -2000, 1000, -8000, 1000, -2000, 1000, -9000 };
int lengthOfRec = sizeof(rawRecording) / sizeof(rawRecording[0]);
void initCC1101(float mhz) {
ELECHOUSE_cc1101.setSpiPin(sck, miso, mosi, ss); //Set custom SPI pins
ELECHOUSE_cc1101.setGDO(GDO0, GDO2); //Set custom GDO0 GDO2 pins
ELECHOUSE_cc1101.Init();
ELECHOUSE_cc1101.setClb(1, 0, 0);
ELECHOUSE_cc1101.setMHZ(mhz);
ELECHOUSE_cc1101.SetTx();
ELECHOUSE_cc1101.setModulation(2); // OOK modulation
ELECHOUSE_cc1101.setDRate(2.4); // Set data rate to 2.4 kBaud
ELECHOUSE_cc1101.setPktFormat(3); // Asynchronous serial mode
ELECHOUSE_cc1101.setPA(10); // Set TxPower
if (ELECHOUSE_cc1101.getCC1101()) { // Check the CC1101 Spi connection.
Serial.println("Connection OK");
} else {
Serial.println("Connection Error");
}
}
void sendSamples(int rawRecording[], int arrayLength) {
Serial.println("Starting Transmission of " + String(arrayLength) + " samples");
for (int i = 0; i < arrayLength; i++) {
bool txState;
int timing = abs(rawRecording[i]);
if (rawRecording[i] > 0) {
txState = HIGH;
} else {
txState = LOW;
}
digitalWrite(GDO0, txState);
delayMicroseconds(timing);
}
Serial.println("Transmission Completed");
digitalWrite(GDO0, LOW);
ELECHOUSE_cc1101.goSleep();
}
double readBattery() {
float measuredvbat = analogReadMilliVolts(VBATPIN);
measuredvbat *= 2; // we divided by 2, so multiply back
measuredvbat /= 1000; // convert to volts!
double batteryPercentage = 105 - (105 / (1 + pow(1.724 * (measuredvbat - 3.2) / (4.2 - 3.2), 5.5)));
Serial.print("Battery voltage is ");
Serial.print(measuredvbat);
Serial.print(" (");
Serial.print(batteryPercentage);
Serial.println("%)");
return batteryPercentage;
}
void controlNeoPixel(double percentage) {
pixels.begin();
pixels.setBrightness(80);
if (percentage > 10.0) {
// Turn NeoPixel green
pixels.setPixelColor(0, pixels.Color(0, 255, 0)); // Green
} else {
// Turn NeoPixel red
pixels.setPixelColor(0, pixels.Color(255, 0, 0)); // Red
Serial.println("Battery Low");
}
pixels.show();
// Keep the NeoPixel on for 2 seconds
delay(2000);
// Turn off the NeoPixel
pixels.clear();
pixels.show();
}
void setup() {
Serial.begin(115200);
// Pin Setup
pinMode(GDO0, OUTPUT);
pinMode(btn, INPUT);
pinMode(VBATPIN, INPUT);
// Deep Sleep Setup
esp_sleep_enable_ext0_wakeup(GPIO_NUM_38, LOW);
rtc_gpio_pullup_dis(GPIO_NUM_38);
rtc_gpio_pulldown_en(GPIO_NUM_38);
// Initialize CC1101
initCC1101(318);
// Handle Transmission and Battery Management
sendSamples(rawRecording, lengthOfRec);
double batteryPercentage = readBattery();
controlNeoPixel(batteryPercentage);
Serial.println("Entering deep sleep...");
esp_deep_sleep_start(); // ESP32 will enter deep sleep here
}
void loop() {
}