ble-compteur.ino
The board becomes a BLE peripheral: a custom service exposes a press counter that a phone (nRF Connect) reads and follows by notifications. The simplest radio scenario without an access point.
Hardware required
A classic ESP32 board (ESP32-WROOM-32 module, dual-core Xtensa 240 MHz, Wi-Fi + Bluetooth) such as a DevKitC / DOIT V1, powered over micro-USB. A phone with nRF Connect is enough; button on GPIO4.
Wiring
Button GPIO4-GND. Nothing else: the radio is built in. Keep the antenna clear (no metal enclosure).
How it works
BLEDevice stacks server, service and a READ|NOTIFY characteristic with the BLE2902 descriptor that enables notifications client-side. setValue+notify pushes the value to the subscriber. In the Arduino IDE, install the « esp32 » board package, pick « Dev Module », the port, then Upload (hold BOOT if detection fails). GPIO34-39 are input-only; avoid GPIO6-11 and GPIO12.
Going further
Add battery level (analogReadToMv) to the characteristic, or move to the standard Battery Service profile.
ble-compteur.ino
// BLE : un service « compteur » notifie l'appui sur GPIO4.
// Appairer avec nRF Connect (Android/iOS), service 12AB, caract. 3400.
#include <BLEDevice.h>
#include <BLEServer.h>
#include <BLEUtils.h>
#include <BLE2902.h>
#define SERVICE_UUID "12AB56DA-7B42-11E5-99AC-625662870701"
#define CHAR_UUID "12AB56DB-7B42-11E5-99AC-625662870701"
BLECharacteristic *pChar;
bool diffuse = false;
int compteur = 0;
void setup() {
Serial.begin(115200);
pinMode(4, INPUT_PULLUP);
BLEDevice::init("compteur-ble");
BLEServer *serveur = BLEDevice::createServer();
BLEService *service = serveur->createService(SERVICE_UUID);
pChar = service->createCharacteristic(
CHAR_UUID, BLECharacteristic::PROPERTY_READ | BLECharacteristic::PROPERTY_NOTIFY);
pChar->addDescriptor(new BLE2902());
service->start();
BLEDevice::getAdvertising()->start();
Serial.println("Broadcast — attend un client");
}
void loop() {
if (digitalRead(4) == LOW && millis() % 1000 < 20) {
compteur++;
if (diffuse) {
String v = String(compteur);
pChar->setValue(v.c_str());
pChar->notify();
Serial.printf("notif %d\n", compteur);
}
delay(250);
}
}