erste Programe von Gemini übernehmen
This commit is contained in:
+125
@@ -0,0 +1,125 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <BleKeyboard.h>
|
||||||
|
|
||||||
|
// --- Pin-Konfiguration ---
|
||||||
|
const int PIN_HOOK = 25; // Gabelumschalter (Hörer abgenommen)
|
||||||
|
const int PIN_NSA = 26; // Wählscheibe dreht sich (Arbeitskontakt)
|
||||||
|
const int PIN_NSI = 27; // Wählscheibe Impulse
|
||||||
|
|
||||||
|
// --- BLE Keyboard ---
|
||||||
|
BleKeyboard bleKeyboard("Retro Phone", "Custom", 100);
|
||||||
|
|
||||||
|
// --- Variablen ---
|
||||||
|
String phoneNumber = "";
|
||||||
|
int pulseCount = 0;
|
||||||
|
bool isDialing = false;
|
||||||
|
bool lastNsiState = HIGH;
|
||||||
|
unsigned long lastDebounceTime = 0;
|
||||||
|
const unsigned long debounceDelay = 20; // 20ms Entprellung für alte Mechanik
|
||||||
|
|
||||||
|
// Timer für den automatischen Anruf nach Eingabe der letzten Ziffer
|
||||||
|
unsigned long lastDigitTime = 0;
|
||||||
|
const unsigned long dialTimeout = 4000; // 4 Sekunden warten nach der letzten Ziffer
|
||||||
|
bool callPending = false;
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
|
||||||
|
// Interne Pull-Ups aktivieren. (Bei stark oxidierten Kontakten des
|
||||||
|
// alten Telefons externe 10k Widerstände gegen 3.3V verwenden!)
|
||||||
|
pinMode(PIN_HOOK, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_NSA, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_NSI, INPUT_PULLUP);
|
||||||
|
|
||||||
|
Serial.println("Starte BLE Keyboard...");
|
||||||
|
bleKeyboard.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
void triggerShortcutAndCall(String number) {
|
||||||
|
if (!bleKeyboard.isConnected()) {
|
||||||
|
Serial.println("Fehler: iPhone nicht über BLE verbunden.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.println("Wähle Nummer: " + number);
|
||||||
|
|
||||||
|
// 1. Kurzbefehl auslösen (Beispiel: Option + Command + C)
|
||||||
|
// Passe diese Kombination an das an, was du im iPhone eingestellt hast.
|
||||||
|
bleKeyboard.press(KEY_LEFT_ALT); // Option
|
||||||
|
bleKeyboard.press(KEY_LEFT_GUI); // Command
|
||||||
|
bleKeyboard.press('c');
|
||||||
|
delay(100);
|
||||||
|
bleKeyboard.releaseAll();
|
||||||
|
|
||||||
|
// 2. Warten, bis das iOS-Eingabefeld des Kurzbefehls erscheint
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
// 3. Nummer eintippen
|
||||||
|
bleKeyboard.print(number);
|
||||||
|
|
||||||
|
// 4. Mit Enter bestätigen, um den Anruf zu starten
|
||||||
|
delay(200);
|
||||||
|
bleKeyboard.write(KEY_RETURN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
bool hookState = digitalRead(PIN_HOOK); // LOW = Hörer abgenommen (je nach Verdrahtung)
|
||||||
|
bool nsaState = digitalRead(PIN_NSA); // LOW = Scheibe dreht
|
||||||
|
bool nsiState = digitalRead(PIN_NSI); // Wechselt LOW/HIGH bei Impulsen
|
||||||
|
|
||||||
|
// Nur aktiv, wenn der Hörer abgenommen ist
|
||||||
|
if (hookState == LOW) {
|
||||||
|
|
||||||
|
// Wählscheibe wird gerade gedreht
|
||||||
|
if (nsaState == LOW) {
|
||||||
|
isDialing = true;
|
||||||
|
callPending = false; // Anruf-Timer abbrechen, solange gewählt wird
|
||||||
|
|
||||||
|
// Impulse zählen (Entprellt)
|
||||||
|
if (nsiState != lastNsiState) {
|
||||||
|
if (millis() - lastDebounceTime > debounceDelay) {
|
||||||
|
lastDebounceTime = millis();
|
||||||
|
if (nsiState == LOW) { // Flanke je nach Schalterart anpassen
|
||||||
|
pulseCount++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Wählscheibe ist in Ruheposition zurückgekehrt
|
||||||
|
else if (isDialing) {
|
||||||
|
isDialing = false;
|
||||||
|
|
||||||
|
// 10 Impulse bedeuten die Ziffer 0
|
||||||
|
int digit = (pulseCount == 10) ? 0 : pulseCount;
|
||||||
|
phoneNumber += String(digit);
|
||||||
|
|
||||||
|
Serial.print("Erkannte Ziffer: ");
|
||||||
|
Serial.println(digit);
|
||||||
|
|
||||||
|
pulseCount = 0;
|
||||||
|
lastDigitTime = millis();
|
||||||
|
callPending = true; // Timer für automatischen Anruf starten
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wenn 4 Sekunden nach der letzten Ziffer nichts passiert ist -> Anrufen
|
||||||
|
if (callPending && (millis() - lastDigitTime > dialTimeout)) {
|
||||||
|
if (phoneNumber.length() > 0) {
|
||||||
|
triggerShortcutAndCall(phoneNumber);
|
||||||
|
phoneNumber = ""; // Nummernspeicher leeren
|
||||||
|
callPending = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// Hörer ist aufgelegt -> Alles zurücksetzen
|
||||||
|
if (phoneNumber.length() > 0 || callPending) {
|
||||||
|
Serial.println("Hörer aufgelegt, setze zurück.");
|
||||||
|
}
|
||||||
|
phoneNumber = "";
|
||||||
|
pulseCount = 0;
|
||||||
|
isDialing = false;
|
||||||
|
callPending = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastNsiState = nsiState;
|
||||||
|
}
|
||||||
@@ -0,0 +1,163 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <BleKeyboard.h>
|
||||||
|
|
||||||
|
// --- Pin-Definitionen ---
|
||||||
|
#define PIN_HOOK 18 // GRÜN: HIGH = Hörer abgehoben, LOW = aufgelegt
|
||||||
|
#define PIN_DIAL 19 // WEISS: HIGH bei Drehung, fallende Flanken = Impulse
|
||||||
|
|
||||||
|
// --- Hardware & Timing-Konstanten ---
|
||||||
|
#define DEBOUNCE_MS 30 // Entprellzeit für Impulse (ms)
|
||||||
|
#define DIGIT_TIMEOUT_MS 350 // Pause nach Drehung, bis Ziffer erkannt ist (ms)
|
||||||
|
#define COMPLETE_DIAL_TIMEOUT 2500 // Pause nach letzter Ziffer, bis Rufnummer komplett ist (ms)
|
||||||
|
|
||||||
|
// --- BLE Keyboard Instanz ---
|
||||||
|
BleKeyboard bleKeyboard("FeTAp 791 Telefon", "Deutsche Bundespost", 100);
|
||||||
|
|
||||||
|
// --- Interrupt-Variablen (müssen volatile sein!) ---
|
||||||
|
volatile int pulseCount = 0;
|
||||||
|
volatile unsigned long lastPulseTime = 0;
|
||||||
|
volatile bool isDialing = false;
|
||||||
|
|
||||||
|
// --- Hauptprogramm-Variablen ---
|
||||||
|
bool bleConnectedLastState = false;
|
||||||
|
bool hookLastState = false;
|
||||||
|
|
||||||
|
String dialedNumber = "";
|
||||||
|
unsigned long lastDigitCompletedTime = 0;
|
||||||
|
bool waitingForCompleteNumber = false;
|
||||||
|
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// Interrupt Service Routine (ISR) für die fallende Flanke
|
||||||
|
// -------------------------------------------------------------------
|
||||||
|
// 'IRAM_ATTR' sorgt dafür, dass dieser Code im schnellen RAM des ESP32 liegt
|
||||||
|
void IRAM_ATTR handleDialPulse() {
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
// Entprellung direkt im Interrupt:
|
||||||
|
// Nur zählen, wenn der letzte Impuls länger als DEBOUNCE_MS her ist
|
||||||
|
if ((currentMillis - lastPulseTime) > DEBOUNCE_MS) {
|
||||||
|
pulseCount++;
|
||||||
|
isDialing = true;
|
||||||
|
lastPulseTime = currentMillis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Serial.begin(115200);
|
||||||
|
delay(1000);
|
||||||
|
|
||||||
|
Serial.println("\n=========================================");
|
||||||
|
Serial.println("FeTAp 791 - ESP32 mit Hardware-Interrupt");
|
||||||
|
Serial.println("=========================================");
|
||||||
|
|
||||||
|
pinMode(PIN_HOOK, INPUT_PULLDOWN);
|
||||||
|
pinMode(PIN_DIAL, INPUT_PULLDOWN);
|
||||||
|
|
||||||
|
// --- Hardware-Interrupt konfigurieren ---
|
||||||
|
// Löst 'handleDialPulse()' EXAKT beim Übergang von HIGH nach LOW aus!
|
||||||
|
attachInterrupt(digitalPinToInterrupt(PIN_DIAL), handleDialPulse, FALLING);
|
||||||
|
|
||||||
|
bleKeyboard.begin();
|
||||||
|
Serial.println("[BLE] Warte auf Verbindung zum iPhone...");
|
||||||
|
}
|
||||||
|
|
||||||
|
void triggerIphoneShortcut(String number) {
|
||||||
|
if (!bleKeyboard.isConnected()) {
|
||||||
|
Serial.println("[BLE] Nicht verbunden – Kurzbefehl kann nicht gesendet werden!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.printf("[Kurzbefehl] Starte Aktion für Rufnummer: %s\n", number.c_str());
|
||||||
|
|
||||||
|
// Nummer eintippen und mit 'Enter' bestätigen
|
||||||
|
bleKeyboard.print(number);
|
||||||
|
delay(100);
|
||||||
|
bleKeyboard.write(KEY_RETURN);
|
||||||
|
}
|
||||||
|
|
||||||
|
void processDialedDigit(int pulses) {
|
||||||
|
char digitChar;
|
||||||
|
if (pulses == 10) {
|
||||||
|
digitChar = '0';
|
||||||
|
} else if (pulses >= 1 && pulses <= 9) {
|
||||||
|
digitChar = '0' + pulses;
|
||||||
|
} else {
|
||||||
|
Serial.printf("[Wahl] Ungültige Impulsanzahl (%d) ignoriert.\n", pulses);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialedNumber += digitChar;
|
||||||
|
lastDigitCompletedTime = millis();
|
||||||
|
waitingForCompleteNumber = true;
|
||||||
|
|
||||||
|
Serial.printf("[Wahl] Ziffer: %c | Aktuelle Nummer: %s\n", digitChar, dialedNumber.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
unsigned long currentMillis = millis();
|
||||||
|
|
||||||
|
// 1. Bluetooth-Verbindungsstatus
|
||||||
|
bool isConnectedNow = bleKeyboard.isConnected();
|
||||||
|
if (isConnectedNow && !bleConnectedLastState) {
|
||||||
|
Serial.println("\n[BLE] >>> iPhone erfolgreich VERBUNDEN! <<<");
|
||||||
|
bleConnectedLastState = true;
|
||||||
|
} else if (!isConnectedNow && bleConnectedLastState) {
|
||||||
|
Serial.println("\n[BLE] >>> Verbindung zum iPhone VERLOREN! <<<");
|
||||||
|
bleConnectedLastState = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 2. Gabelumschalter (Hook)
|
||||||
|
bool currentHookState = digitalRead(PIN_HOOK);
|
||||||
|
if (currentHookState != hookLastState) {
|
||||||
|
delay(20); // Entprellen der Gabel
|
||||||
|
currentHookState = digitalRead(PIN_HOOK);
|
||||||
|
|
||||||
|
if (currentHookState != hookLastState) {
|
||||||
|
hookLastState = currentHookState;
|
||||||
|
|
||||||
|
if (currentHookState == HIGH) {
|
||||||
|
Serial.println("\n[Hörer] ABGEHOBEN");
|
||||||
|
dialedNumber = "";
|
||||||
|
waitingForCompleteNumber = false;
|
||||||
|
|
||||||
|
// Interrupt aktivieren / Zähler nullen
|
||||||
|
pulseCount = 0;
|
||||||
|
isDialing = false;
|
||||||
|
} else {
|
||||||
|
Serial.println("\n[Hörer] AUFGELEGT");
|
||||||
|
dialedNumber = "";
|
||||||
|
waitingForCompleteNumber = false;
|
||||||
|
pulseCount = 0;
|
||||||
|
isDialing = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 3. Auswertung der Ziffern & Rufnummer (nur bei abgehobenem Hörer)
|
||||||
|
if (hookLastState == HIGH) {
|
||||||
|
|
||||||
|
// A) Ist die Ziffern-Drehung beendet? (Timeout seit letztem Interrupt-Impuls)
|
||||||
|
if (isDialing && (currentMillis - lastPulseTime > DIGIT_TIMEOUT_MS)) {
|
||||||
|
|
||||||
|
// Für die sichere Übergabe aus der ISR kurz Interrupts pausieren oder Wert kopieren
|
||||||
|
noInterrupts();
|
||||||
|
int currentPulses = pulseCount;
|
||||||
|
pulseCount = 0;
|
||||||
|
isDialing = false;
|
||||||
|
interrupts();
|
||||||
|
|
||||||
|
if (currentPulses > 0) {
|
||||||
|
processDialedDigit(currentPulses);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// B) Ist die komplette Rufnummer fertig gewählt? (Pause nach letzter Ziffer)
|
||||||
|
if (waitingForCompleteNumber && (currentMillis - lastDigitCompletedTime > COMPLETE_DIAL_TIMEOUT)) {
|
||||||
|
waitingForCompleteNumber = false;
|
||||||
|
Serial.printf("\n[Wahl abgeschlossen] Vollständige Nummer: %s\n", dialedNumber.c_str());
|
||||||
|
|
||||||
|
// Kurzbefehl am iPhone ausführen
|
||||||
|
triggerIphoneShortcut(dialedNumber);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
[env:esp32dev]
|
||||||
|
platform = espressif32
|
||||||
|
board = esp32dev
|
||||||
|
framework = arduino
|
||||||
|
monitor_speed = 115200
|
||||||
|
lib_deps =
|
||||||
|
t-vk/ESP32 BLE Keyboard @ ^0.3.2
|
||||||
Reference in New Issue
Block a user