Skip to content
  • The version using deep sleep does currently not connect via Bluetooth:

    #include <BleKeyboard.h>
    #include "esp_sleep.h"
    
    BleKeyboard bleKeyboard("Justus Music Page Turner");
    
    #define BUTTON_PIN 2                // Analog-capable pin for pressure/button input
    const int threshold = 3000;        // Analog threshold
    const int time_pressed = 300;      // Time in ms to switch between 'A' and 'B'
    
    bool isAboveThreshold = false;
    unsigned long pressStartTime = 0;
    bool hasSentKey = false;
    
    void setup() {
      Serial.begin(115200);
    
      pinMode(BUTTON_PIN, INPUT_PULLUP);  // Can stay for analog-capable pin
    
      // Allow wake every 50 ms to poll
      esp_sleep_enable_timer_wakeup(50 * 1000);  // microseconds
    
      bleKeyboard.begin();
    }
    
    void loop() {
      // Light sleep allows BLE to stay connected
      esp_light_sleep_start();
    
      int analogValue = analogRead(BUTTON_PIN);
      // Serial.println(analogValue); 
    
      if (!bleKeyboard.isConnected()) return;
    
      if (analogValue > threshold) {
        if (!isAboveThreshold) {
          isAboveThreshold = true;
          pressStartTime = millis();
          hasSentKey = false;
        } else if (!hasSentKey) {
          unsigned long heldTime = millis() - pressStartTime;
          if (heldTime >= time_pressed) {
            bleKeyboard.write('B');
            Serial.println("Sent 'B'");
            hasSentKey = true;
          }
        }
      } else {
        if (isAboveThreshold && !hasSentKey) {
          unsigned long heldTime = millis() - pressStartTime;
          if (heldTime < time_pressed) {
            bleKeyboard.write('A');
            Serial.println("Sent 'A'");
          }
        }
    
        // Reset for next input
        isAboveThreshold = false;
        hasSentKey = false;
      }
    }
    Edited by Simon Markus Haller-Seeber
  • Folgendes hat mir mal ChatGPT nach eingiem hin und her zum probieren vorgeschlagen

    #include <NimBLEDevice.h>
    #include "HIDTypes.h"
    #include "BLEHIDDevice.h"
    
    BLEHIDDevice* hid;
    BLECharacteristic* input;
    
    class MyCallbacks : public NimBLEServerCallbacks {
      void onConnect(NimBLEServer* pServer) {
        Serial.println("Device connected");
      }
    
      void onDisconnect(NimBLEServer* pServer) {
        Serial.println("Device disconnected");
        NimBLEDevice::startAdvertising();
      }
    };
    
    void setup() {
      Serial.begin(115200);
    
      // Init BLE
      NimBLEDevice::init("Page-Turner");
    
      // Disable BLE security
      NimBLEDevice::setSecurityAuth(false, false, false);
      NimBLEDevice::setSecurityIOCap(BLE_HS_IO_NO_INPUT_OUTPUT);
    
      NimBLEServer* pServer = NimBLEDevice::createServer();
      pServer->setCallbacks(new MyCallbacks());
    
      hid = new BLEHIDDevice(pServer);
      input = hid->inputReport(1); // ID = 1
    
      // Basic HID descriptor for a keyboard (can also be adapted to presenter)
      const uint8_t reportMap[] = {
        0x05, 0x01,       // Usage Page (Generic Desktop)
        0x09, 0x06,       // Usage (Keyboard)
        0xA1, 0x01,       // Collection (Application)
        0x05, 0x07,       //   Usage Page (Key Codes)
        0x19, 0xe0,       //   Usage Minimum (224)
        0x29, 0xe7,       //   Usage Maximum (231)
        0x15, 0x00,       //   Logical Minimum (0)
        0x25, 0x01,       //   Logical Maximum (1)
        0x75, 0x01,       //   Report Size (1)
        0x95, 0x08,       //   Report Count (8)
        0x81, 0x02,       //   Input (Data, Variable, Absolute) ;Modifier byte
        0x95, 0x01,       //   Report Count (1)
        0x75, 0x08,       //   Report Size (8)
        0x81, 0x01,       //   Input (Constant)                 ;Reserved byte
        0x95, 0x05,       //   Report Count (5)
        0x75, 0x01,       //   Report Size (1)
        0x05, 0x08,       //   Usage Page (LEDs)
        0x19, 0x01,       //   Usage Minimum (1)
        0x29, 0x05,       //   Usage Maximum (5)
        0x91, 0x02,       //   Output (Data, Variable, Absolute) ;LED report
        0x95, 0x01,       //   Report Count (1)
        0x75, 0x03,       //   Report Size (3)
        0x91, 0x01,       //   Output (Constant)                 ;LED report padding
        0x95, 0x06,       //   Report Count (6)
        0x75, 0x08,       //   Report Size (8)
        0x15, 0x00,       //   Logical Minimum (0)
        0x25, 0x65,       //   Logical Maximum(101)
        0x05, 0x07,       //   Usage Page (Key codes)
        0x19, 0x00,       //   Usage Minimum (0)
        0x29, 0x65,       //   Usage Maximum (101)
        0x81, 0x00,       //   Input (Data, Array)
        0xC0              // End Collection
      };
    
      hid->manufacturer()->setValue("ESP Manufacturer");
      hid->pnp(0x02, 0xe502, 0xa111, 0x0210); // vendorID source, vendorID, productID, version
      hid->hidInfo(0x00, 0x01);
    
      hid->reportMap((uint8_t*)reportMap, sizeof(reportMap));
      hid->startServices();
    
      NimBLEAdvertising* advertising = NimBLEDevice::getAdvertising();
      advertising->setAppearance(HID_GENERIC);
      advertising->addServiceUUID(hid->hidService()->getUUID());
      advertising->start();
    
      Serial.println("BLE HID ready!");
    }
    
    void loop() {
      // Simulate "Next Slide" (Right Arrow) every 10 seconds
      delay(10000);
      Serial.println("Sending RIGHT ARROW");
    
      uint8_t key[] = { 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x00, 0x00 }; // Right Arrow
      input->setValue(key, sizeof(key));
      input->notify();
    
      delay(20); // key press duration
    
      uint8_t release[] = { 0x00 };
      input->setValue(release, 1); // release
      input->notify();
    }
    Edited by Simon Markus Haller-Seeber
  • #include <BleKeyboard.h>
    
    // ==== BLE Keyboard Settings ====
    BleKeyboard bleKeyboard("Music-Page-Turner", "JP", 100);
    
    // ==== Pin Assignments ====
    #define BUTTON_PIN 2
    #define BATTERY_PIN 35
    
    // ==== ADC Settings ====
    const float ADC_MAX = 4095.0;       // 12-bit ADC
    const float ADC_REF_VOLTAGE = 3.3;  // ESP32 ADC reference
    const int pressThreshold = 30;      // pressed if analog < this
    const int releaseThreshold = 80;    // must rise above to count as released
    const int time_pressed = 300;       // long press threshold (ms)
    const int debounceTime = 50;        // debounce time (ms)
    
    // ==== Button State ====
    bool isPressed = false;
    unsigned long pressStartTime = 0;
    bool hasSentKey = false;
    unsigned long lastChangeTime = 0;
    
    // ==== Battery Percentage Calculation (rounded to nearest 5%) ====
    int batteryPercentRounded(float volts) {
      int pct;
      if (volts >= 3.95) pct = 100;
      else if (volts <= 3.2) pct = 0;
      else pct = (int)((volts - 3.2) / (3.95 - 3.2) * 100);
    
      int remainder = pct % 5;
      if (remainder >= 3) pct += (5 - remainder);
      else pct -= remainder;
    
      return constrain(pct, 0, 100);
    }
    
    // ==== Battery Voltage Reading with Averaging ====
    float readBatteryVoltage() {
      long sum = 0;
      const int samples = 20;
      for (int i = 0; i < samples; i++) {
        sum += analogRead(BATTERY_PIN);
        delay(2);
      }
      int raw = sum / samples;
      float voltageAtPin = (raw / ADC_MAX) * ADC_REF_VOLTAGE;
      return voltageAtPin * 2; // voltage divider correction
    }
    
    // ==== Button Handling ====
    void handleButton() {
      int analogValue = analogRead(BUTTON_PIN);
      unsigned long now = millis();
    
      // Debounce
      if (now - lastChangeTime < debounceTime) return;
    
      if (!isPressed && analogValue < pressThreshold) {
        // Button just pressed
        isPressed = true;
        pressStartTime = now;
        hasSentKey = false;
        lastChangeTime = now;
        Serial.println("Pressed");
      }
      else if (isPressed && analogValue > releaseThreshold) {
        // Button just released
        unsigned long heldTime = now - pressStartTime;
        if (!hasSentKey && heldTime < time_pressed) {
          bleKeyboard.write(KEY_RIGHT_ARROW);
          Serial.println("Short press");
        }
        isPressed = false;
        lastChangeTime = now;
        Serial.println("Released");
      }
      else if (isPressed && !hasSentKey) {
        // Still held, check for long press
        unsigned long heldTime = now - pressStartTime;
        if (heldTime >= time_pressed) {
          bleKeyboard.write(KEY_LEFT_ARROW);
          Serial.println("Long press");
          hasSentKey = true;
        }
      }
    }
    
    void setup() {
      Serial.begin(115200);
      pinMode(BUTTON_PIN, INPUT_PULLUP);
      pinMode(BATTERY_PIN, INPUT);
      analogReadResolution(12);
      analogSetPinAttenuation(BATTERY_PIN, ADC_11db);
    
      // Start BLE
      bleKeyboard.begin();
    }
    
    void loop() {
      if (!bleKeyboard.isConnected()) {
        delay(50);
        return;
      }
    
      // ---- Battery Reporting ----
      static unsigned long lastBatteryPrint = 0;
      if (millis() - lastBatteryPrint >= 1000) {
        float batteryVoltage = readBatteryVoltage();
        int batteryPct = batteryPercentRounded(batteryVoltage);
        bleKeyboard.setBatteryLevel(batteryPct);
    
        Serial.print("Battery Voltage: ");
        Serial.print(batteryVoltage, 1);
        Serial.print(" V (");
        Serial.print(batteryPct);
        Serial.println("%)");
        lastBatteryPrint = millis();
      }
    
      // ---- Button Handling ----
      handleButton();
      delay(20);
    }
    Edited by Simon Markus Haller-Seeber
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment