Keyboard functional and first sending of PGN 127502

This commit is contained in:
2026-01-04 19:28:21 +01:00
parent 12687b17ab
commit c953340362
5 changed files with 501 additions and 165 deletions

74
README
View File

@@ -2,11 +2,10 @@ OBP Keypad
==========
- Stromversorgung über M12-Anschluß über NMEA2000
Eingangsbereich 6~21V
- Ein- und Ausschalten durch langen Tastendruck auf DST/ ONOFF
- Eingangsbereich 6~21V
- Konfigurationsmodus durch langen Tastendruck auf DST
- Tiefschlaf und Reset aus Konfigmodus heraus auswählbar
- Konfiguration über Web-Interface
- PWR leuchtet grün wen NMEA2000-Verbindung etabliert
- PWR leuchtet rot wenn nur Stromversorgung aktiv ist
- Buzzer für Tastendruck-Feedback
passiv, damit können die Töne mit PWM programmiert werden
- I²C Temp/Hum-Sensor SHT31
@@ -25,14 +24,15 @@ Optionen für später
bedeutet auch: viel komplizierteres Gehäuse
Damit die LEDs nicht stören, kann umgeschaltet werden zwischen
permanentem Leuchten und nur kurzem Aufblinken bei Betätigung.
permanentem Leuchten und nur kurzem Aufblinken bei Betätigung:
Tag- und Nachtmodus
Einschaltvorgang
----------------
Es erfolgt ein "Lampentest": Alle LEDs werden einmal durchgeschaltet.
Sind alle Tests erfolgreich ertönt ein Buzzer-Signal.
- Status leuchtet kurz rot auf
- Es erfolgt ein "Lampentest": Alle LEDs werden einmal durchgeschaltet.
- Sind alle Tests erfolgreich ertönt ein Buzzer-Signal.
Beschreibung
------------
@@ -44,31 +44,29 @@ Die Destination-LEDs leuchten nur, wenn ein entsprechendes
N2K-Zielgerät konfiguriert und erkannt wurde.
Gehäuse
-------
Bohrung Taster: 12mm
Taster Außenmaß: 17.5mm
Verbindungskabel CPU-Platine
JST 2.54 XH 6 Pin Steckverbinder -> LED
JST 2.54 XH 7 Pin Steckverbinder -> LEDs + GND
Anschlußmöglichkeiten
---------------------
für Stromversorgung +12V und NMEA2000
4pin Terminalblock steck-/schraubbar +12V, DNG, CAN-L, CAN-H
2pin Terminalblock
für I²C-Module
2x 4pin Buchsenleiste weibl.
1x QWIIC-Buchse (JST_SH_BM04B-SRSS-TB_04x1.00mm)
1x qwiic-Buchse (JST_SH_BM04B-SRSS-TB_04x1.00mm)
für CAN-Transceiver-Modul: 4fach buchse liegend
für mechanische Taster
1x JST 2.54 XH 7 Pin Steckverbinder -> Tasten
Masseverbindung über einzelnes getrenntes Kabel
in eine 8-fach WAGO-Klemme
für LEDs
TBD
1x Terminalblock 8fach, 7 Tasten und GND
Bemerkungen
@@ -77,6 +75,10 @@ Bemerkungen
Bei den aktuell verwendeten Tasten sind die Anschlußdrähte extrem
filigran. Leichtes Brechen und schlechte Verarbeitung.
Es gibt verschiedene Varianten mit unterschiedlicher Federkraft.
Auswahl muß noch erfolgen
Beschaltung MCU Nano
--------------------
@@ -94,7 +96,7 @@ werden!
Die Pins für SPI (D11, D12, D13) sind absichtlich
nicht belegt um frei für Erweiterungen zu sein. An SPI kann
ggf. ein Epaper angeschlossen werden.
ggf. ein E-Paper angeschlossen werden.
Key Color Pin Remarks
@@ -124,27 +126,35 @@ ggf. ein Epaper angeschlossen werden.
BUZZER
TBD
Bauteilliste
Bauteilliste (WIP)
------------
1x ESP32-S3 Nano (Waveshare)
berrybase.de
eckstein-shop.de
5x Taster schwarz
2x Taster gelb
1x M12 Einbaubuchse
1x RGB LED (gemeinsame Anode), diffus
6x Taster schwarz (1-6)
1x Taster farbig (DST)
1x M12 Micro-C Einbaubuchse
1x RGB LED (gemeinsame Kathode), diffus
3x LED grün, diffus
6x Widerstand 330 Ohm
1x SN65HVD230 CAN Transceiver
1x Buzzer, passiv
1x Kabelsatz
1x Terminalblock 4pol. 2,54mm schraubbar
1x Gehäuse 150x60x40 bestehend auf Front- und Rückseite
4x Befestigungsschraube M4
4x Gehäuseschraube M2,5
1x Buzzer 12V, passiv
1x MOSFET 2N7000
1x Widerstand 150 Ohm
1x Kabelsatz für Tasten, 0,25 bis 0,5 mm²
1x Terminalblock 2pol. 2,54mm schraubbar
1x 3D-Gehäuse bestehend auf Front- und Rückseite
1x Mutternwerkzeug 3D-Druck
4x Befestigungsschraube M4 Senkkopf
4x Gehäuseschraube M2,5, lang
8x Platinenschraube M2,5, kurz
1x Silikondichtschnur 2mm
1x SHT31 I²C-Modul
Buchsenleiste 2,54 mm
Stiftleiste 2,54mm
2x Jumper
1x Polyfuse
Konfiguration
-------------

View File

@@ -6,6 +6,7 @@
// NMEA2000 defaults
#define N2K_DEFAULT_NODEID 124
#define NMEA2000_HEARTBEAT_INTERVAL 5000 // milliseconds
// Keys
#define KEY_1 GPIO_NUM_5 // D2
@@ -54,3 +55,24 @@
#define SPI_MISO GPIO_NUM_47 // D12
#define SPI_SCK GPIO_NUM_48 // D13
#define SPI_CS GPIO_NUM_46 // B0
// Button indices
#define BUTTON_1 0
#define BUTTON_2 1
#define BUTTON_3 2
#define BUTTON_4 3
#define BUTTON_5 4
#define BUTTON_6 5
#define BUTTON_DST 6
enum class ButtonPressType : uint8_t
{
SHORT, // < 1 second
MEDIUM, // >= 1 second and < 3 seconds
LONG // >= 3 seconds
};
struct ButtonEvent
{
uint8_t buttonId;
ButtonPressType pressType;
};

View File

@@ -41,10 +41,9 @@ build_unflags =
[env:esp32-s3-nano]
build_type = release # debug | release
# board = esp32-s3-devkitc-1
board = esp32_s3_nano
#board = arduino_nano_esp32 # ATTENTION! Pin numbering scheme changes
board_upload.flash_size = 16MB
board_build.partitions = default.csv
board_build.partitions = default_16MB.csv #ESP32-S3 N16, 16MB flash
upload_port = /dev/ttyACM0
upload_protocol = esptool

View File

@@ -13,9 +13,9 @@
#include "Nmea2kTwai.h"
#include <map>
#include "mbedtls/md.h" // for SHA256
#include <esp32/clk.h> // for cpu frequency
#include "driver/rtc_io.h" // for wakeup from deep sleep
String get_sha256(String payload) {
byte shaResult[32];
@@ -90,8 +90,10 @@ uint64_t chipid = ESP.getEfuseMac();
const char* wifi_ssid = "OBPKP61";
const char* wifi_pass = "keypad61";
bool apEnabled = false;
AsyncWebServer server(80);
unsigned long firstStart = 0;
unsigned long lastSensor = 0;
unsigned long lastPrint = 0;
unsigned long counter = 0;
@@ -100,12 +102,17 @@ bool rgb_r = false;
bool rgb_g = false;
bool rgb_b = false;
char destination = 'A'; // A | B | C
char mode = 'N'; // (N)ormal | (C)onfig
char ledmode = 'D'; // (D)ay | (N)ight
char audiomode = 'E'; // (E)nabled | (D)isabled
RTC_DATA_ATTR char destination = 'A'; // A | B | C im RTC-Speicher überlebt deep sleep
uint8_t led_brightness = 16; // analog pin: 0 .. 255
uint8_t rgb_brightness = 64;
uint buzzerpower = 50; // TBD make use of this
uint8_t keycode[6]; // configurable keycodes
SHT31 sht(SHT31_ADDRESS);
bool sht_available = false;
float temp = 0.0;
@@ -143,7 +150,7 @@ String uptime_with_unit() {
void ledtest() {
// all led one after another to test functionality
Serial.print("LED test started");
Serial.println("LED test started");
// Onbard RGB LED, inverted mode
digitalWrite(LED_IR, LOW);
@@ -173,9 +180,6 @@ void ledtest() {
analogWrite(LED_C, led_brightness);
delay(500);
analogWrite(LED_C, 0);
// select dst A finally
analogWrite(LED_A, led_brightness);
delay(500);
// enclosure rgb led (common cathode, so low is off)
analogWrite(RGBLED_R, rgb_brightness);
@@ -190,25 +194,126 @@ void ledtest() {
delay(700);
analogWrite(RGBLED_B, 0);
Serial.print("LED test finished");
Serial.println("LED test finished");
}
TaskHandle_t ledTaskHandle = NULL;
TaskHandle_t sensorTaskHandle = NULL;
TaskHandle_t keyTaskHandle = NULL;
QueueHandle_t ledQueue = NULL;
QueueHandle_t keyQueue = NULL;
void ledTask(void *parameter) {
Serial.println("Starting LED task");
for (;;) {
vTaskDelay(5000);
analogWrite(RGBLED_G, 10); // a short activity flash
vTaskDelay(20);
analogWrite(RGBLED_G, 0);
}
}
void sensorTask(void *parameter) {
Serial.println("Starting sensor task");
for (;;) {
vTaskDelay(10000); // nothing yet
}
}
void keyTask(void *parameter) {
// short key press <= 1s
// medium key press >1s and < 3s
// long key press >= 3s
Serial.println("Starting keyboard task");
constexpr uint8_t NUM_BUTTONS = 7;
constexpr gpio_num_t buttonPins[NUM_BUTTONS] = {
KEY_1, KEY_2, KEY_3, KEY_4, KEY_5, KEY_6, KEY_DST
};
constexpr TickType_t DEBOUNCE_TIME = pdMS_TO_TICKS(30);
constexpr TickType_t POLL_INTERVAL = pdMS_TO_TICKS(10); // 100Hz update rate (10ms)
bool lastRead[NUM_BUTTONS];
bool lastStable[NUM_BUTTONS];
TickType_t lastDebounce[NUM_BUTTONS];
TickType_t pressStart[NUM_BUTTONS];
// init
for (int i = 0; i < NUM_BUTTONS; i++) {
lastRead[i]= HIGH;
lastStable[i] = HIGH;
lastDebounce[i]= 0;
pressStart[i] = 0;
}
for (;;) {
TickType_t now = xTaskGetTickCount();
for (int i = 0; i < NUM_BUTTONS; i++) {
bool reading = digitalRead(buttonPins[i]);
if (reading != lastRead[i]) {
lastDebounce[i] = now;
lastRead[i] = reading;
}
if ((now - lastDebounce[i]) > DEBOUNCE_TIME) {
if (reading != lastStable[i]) {
lastStable[i] = reading;
if (reading == LOW) {
// button pressed
pressStart[i] = now;
} else {
// button released: send to queue
TickType_t duration = now - pressStart[i];
ButtonEvent event;
event.buttonId = i;
if (duration < 1000) {
event.pressType = ButtonPressType::SHORT;
} else if (duration < 3000) {
event.pressType = ButtonPressType::MEDIUM;
} else {
event.pressType = ButtonPressType::LONG;
}
xQueueSend(keyQueue, &event, 0);
}
}
}
vTaskDelay(POLL_INTERVAL);
}
}
vTaskDelete(NULL);
}
void cpuFreqTimerCallback(TimerHandle_t xTimer) {
Serial.println("after 3 minutes: set CPU frequency to 160MHz");
setCpuFrequencyMhz(160);
}
void setup() {
Serial.begin(115200);
// while (!Serial) delay(10);
// while (!Serial) delay(10); verhindert Booten ohne USB-Verbindung
delay(500);
preferences.begin("nvs", false);
keycode[0] = preferences.getInt("key1", 1);
keycode[1] = preferences.getInt("key2", 2);
keycode[2] = preferences.getInt("key3", 3);
keycode[3] = preferences.getInt("key4", 4);
keycode[4] = preferences.getInt("key5", 5);
keycode[5] = preferences.getInt("key6", 6);
preferences.end();
// Configure I/O pins
// internal user led (red)
pinMode(LED_USER, OUTPUT);
// Init onbard RGB led
// Init onbard RGB led and switch off
pinMode(LED_IR, OUTPUT);
pinMode(LED_IG, OUTPUT);
pinMode(LED_IB, OUTPUT);
digitalWrite(LED_IR, HIGH);
digitalWrite(LED_IG, HIGH);
digitalWrite(LED_IB, HIGH);
// destination leds
pinMode(LED_A, OUTPUT);
@@ -244,6 +349,13 @@ void setup() {
ESP_LOGI(TAG, "Starting ...");
esp_sleep_wakeup_cause_t cause = esp_sleep_get_wakeup_cause();
if (cause == ESP_SLEEP_WAKEUP_EXT0) {
ESP_LOGI(TAG, " Wake up by key");
} else {
destination = 'A';
}
// N2K basics
nodeid = N2K_DEFAULT_NODEID;
ESP_LOGI(TAG, "N2K default node is %d", nodeid);
@@ -264,6 +376,7 @@ void setup() {
IPAddress ap_subnet(255, 255, 255, 0);
IPAddress ap_gateway(ap_addr);
WiFi.softAPConfig(ap_addr, ap_gateway, ap_subnet);
apEnabled = true;
// Route for root / web page
server.on("/", HTTP_GET, [](AsyncWebServerRequest *request) {
@@ -292,11 +405,29 @@ void setup() {
request->send(200, "application/json", out);
});
server.on("/api/config", HTTP_GET, [](AsyncWebServerRequest *request){
StaticJsonDocument<100> doc;
StaticJsonDocument<512> doc;
doc["systemName"] = "Keypad1";
doc["logLevel"] = 0;
doc["version"] = "0.0";
doc["fwtype"] = "unknown";
doc["salt"] = "secret";
doc["AdminPassword"] = "********";
doc["useAdminPass"] = false;
doc["apIp"] = "192.168.15.1";
doc["apMask"] = "255.255.255.0";
doc["apPassword"] = "********";
doc["stopApTime"] = 0;
doc["cpuSpeed"] = 160;
doc["tempFormat"] = "C";
doc["ledBrightness"] = led_brightness;
doc["ledRgbBrightness"] = rgb_brightness;
doc["tempFormat"] = "C";
doc["key1"] = keycode[BUTTON_1];
doc["key2"] = keycode[BUTTON_2];
doc["key3"] = keycode[BUTTON_3];
doc["key4"] = keycode[BUTTON_4];
doc["key5"] = keycode[BUTTON_5];
doc["key6"] = keycode[BUTTON_6];
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
@@ -334,6 +465,13 @@ void setup() {
serializeJson(doc, out);
request->send(200, "application/json", out);
});
server.on("/api/update", HTTP_POST, [](AsyncWebServerRequest *request){
StaticJsonDocument<100> doc;
doc["status"] = "FAILED";
String out;
serializeJson(doc, out);
request->send(200, "application/json", out);
});
// TODO POST vom Client entgegennehmen
@@ -348,17 +486,37 @@ void setup() {
NMEA2000.SetProductInformation("00000001", // Manufacturer's Model serial code
74, // Manufacturer's product code
"OBPkeypad6/1", // Manufacturer's Model ID
"1.0.0 (2025-11-28)", // Manufacturer's Software version code
"0.1" // Manufacturer's Model version
"0.1.0 (2026-01-04)", // Manufacturer's Software version code
"0.1", // Manufacturer's Model version
1 // LoadEquivalency (LEN)
);
uint32_t uid; // ISO 21bit identity number devived from chipid (MAC)
uid = ((chipid >> 32) ^ (chipid & 0xFFFFFFFF)) & 0x1FFFFF;
// TODO Device unique id stored in preferences
NMEA2000.SetDeviceInformation(1, // Unique number. Use e.g. Serial number.
130, // Device function=Atmospheric
85, // Device class=External Environment
2046
NMEA2000.SetDeviceInformation(uid, // Unique number. Use e.g. Serial number.
130, // Device function=Button Interface (or 190?)
110, // Device class=Human Interface? (or 140?)
2046, // Manufacturer code (custom OBP)
4 // Industrygoup=Marine
);
NMEA2000.SetForwardType(tNMEA2000::fwdt_Text);
// Debug
// NMEA2000.SetForwardStream(&Serial);
// NMEA2000.SetDebugMode(tNMEA2000::dm_2);
NMEA2000.SetMode(tNMEA2000::N2km_ListenAndNode, nodeid);
NMEA2000.SetForwardOwnMessages(false);
NMEA2000.SetHeartbeatIntervalAndOffset(NMEA2000_HEARTBEAT_INTERVAL);
const unsigned long TransmitPGNs[] = {
127502UL,
0
};
NMEA2000.ExtendTransmitMessages(TransmitPGNs);
NMEA2000.Open();
// internal user led (red)
digitalWrite(LED_USER, HIGH);
@@ -369,10 +527,11 @@ void setup() {
ledcSetup(LEDC_CHANNEL, LEDC_BASE_FREQ, LEDC_TIMER_8_BIT);
ledcAttachPin(BUZZER, LEDC_CHANNEL);
// Test tone while booting
// Buzzer 12V, 2500Hz +/- 200Hz, 30mA, ca. 90dB
if (ledcWriteTone(LEDC_CHANNEL, 2300) == 0) {
Serial.println("Error setting buzzer tone");
} else {
delay(750);
delay(50);
ledcWriteTone(LEDC_CHANNEL, 0); // Buzzer off
}
@@ -381,6 +540,19 @@ void setup() {
delay(500);
ledtest();
// select current destination
switch (destination) {
case 'A':
analogWrite(LED_A, led_brightness);
break;
case 'B':
analogWrite(LED_B, led_brightness);
break;
case 'C':
analogWrite(LED_C, led_brightness);
break;
}
// I²C
Serial.print("SHT31_LIB_VERSION: ");
Serial.println(SHT31_LIB_VERSION);
@@ -396,18 +568,47 @@ void setup() {
// Additional tests
String passhash = get_sha256("secretTEST");
xTaskCreatePinnedToCore(
ledTask, // Task function
"LEDTask", // Task name
10000, // Stack size (bytes)
NULL, // Parameters
1, // Priority
&ledTaskHandle, // Task handle
1 // Core 1
);
xTaskCreatePinnedToCore(sensorTask,"SensorTask", 10000, NULL, 1, &sensorTaskHandle, 1);
xTaskCreatePinnedToCore(keyTask,"KeyboardTask", 10000, NULL, 1, &keyTaskHandle, 1);
// Create queues (5 items, each uint16_t)
keyQueue = xQueueCreate(5, sizeof(ButtonEvent));
ledQueue = xQueueCreate(5, sizeof(uint8_t));
if (esp_sleep_is_valid_wakeup_gpio(KEY_DST)) {
Serial.println("DST-Taste ist als Wakeup-Pin konfiguriert");
esp_sleep_enable_ext0_wakeup(KEY_DST, 0);
} else {
Serial.println("Keine Wakeup-Funktion vorhanden! Deep-sleep deaktiviert.");
}
TimerHandle_t cpuFreqTimer = xTimerCreate(
"cpuFreqTimer",
pdMS_TO_TICKS(2 * 60 * 1000),
pdFALSE, // one shot only
nullptr,
cpuFreqTimerCallback
);
xTimerStart(cpuFreqTimer, 0);
}
void shortBeep() {
ledcWriteTone(LEDC_CHANNEL, 2500);
delay(15);
ledcWriteTone(LEDC_CHANNEL, 0);
}
void atariKeyclick() {
/*
* Anderer 12V-fähiger Buzzer!
*
Buzzer + → 12V
Buzzer → IRLZ44N Drain
IRLZ44N Source → GND
ESP32 GPIO43 → 1kΩ resistor → Gate
ESP32 GND must be connected to the same GND as the 12V supply.
* */
ledcWriteTone(LEDC_CHANNEL, 3200);
delayMicroseconds(3000);
ledcWriteTone(LEDC_CHANNEL, 0);
@@ -417,118 +618,161 @@ void atariKeyclick() {
ledcWriteTone(LEDC_CHANNEL, 0);
}
void SendToN2K(uint8_t keycode) {
tN2kMsg N2kMsg;
tN2kBinaryStatus bankstatus;
N2kResetBinaryStatus(bankstatus);
N2kSetStatusBinaryOnStatus(bankstatus, N2kOnOff_On, keycode);
// TODO
// Needs filled N2K device list to map NAME to current address
// N2kMsg.Destination = deviceAddress;
//
SetN2kPGN127502(N2kMsg, 0, bankstatus);
NMEA2000.SendMsg(N2kMsg);
Serial.print("PGN127502 sent: Switch=");
Serial.print(keycode);
Serial.println(" Action=On");
}
void loop() {
// Button pressed? (active low)
uint8_t button = 0;
if (digitalRead(KEY_1) == LOW) {
Serial.println("Button detected: 1");
button = 1;
if (rgb_r) {
rgb_r = false;
analogWrite(RGBLED_R, 255);
} else {
rgb_r = true;
analogWrite(RGBLED_R, 255 - rgb_brightness);
ButtonEvent event;
if (xQueueReceive(keyQueue, &event, 0) == pdPASS) {
Serial.print("Button ");
Serial.print(event.buttonId);
Serial.print(" -> ");
switch (event.pressType) {
case ButtonPressType::SHORT:
Serial.println("SHORT");
break;
case ButtonPressType::MEDIUM:
Serial.println("MEDIUM");
break;
case ButtonPressType::LONG:
Serial.println("LONG");
break;
default:
Serial.print("UNBEKANNT: ");
Serial.println(static_cast<uint8_t>(event.pressType));
break;
}
}
if (digitalRead(KEY_2) == LOW) {
Serial.println("Button detected: 2");
button += 2;
if (rgb_g) {
rgb_g = false;
analogWrite(RGBLED_G, 255);
if (event.buttonId == BUTTON_DST) {
if (event.pressType == ButtonPressType::SHORT) {
if (mode == 'N') {
// switch destination only in normal mode
if (destination == 'A') {
destination = 'B';
analogWrite(LED_A, 0);
analogWrite(LED_B, led_brightness);
} else if (destination == 'B') {
destination = 'C';
analogWrite(LED_B, 0);
analogWrite(LED_C, led_brightness);
} else {
destination = 'A';
analogWrite(LED_C, 0);
analogWrite(LED_A, led_brightness);
}
Serial.print("New destination=");
Serial.println(destination);
}
} else if (event.pressType == ButtonPressType::LONG) {
shortBeep();
// switch config mode
if (mode == 'N') {
mode = 'C';
analogWrite(RGBLED_B, rgb_brightness); // blue status indicator
} else {
mode = 'N';
analogWrite(RGBLED_B, 0);
}
}
} else {
rgb_g = true;
analogWrite(RGBLED_G, 255 - rgb_brightness);
}
}
if (digitalRead(KEY_3) == LOW) {
Serial.println("Button detected: 3");
button += 4;
if (rgb_b) {
rgb_b = false;
analogWrite(RGBLED_B, 255);
} else {
rgb_b = true;
analogWrite(RGBLED_B, 255 - rgb_brightness);
// normal button
if (mode == 'N') {
// TODO send key code to destination
atariKeyclick();
SendToN2K(keycode[event.buttonId]);
} else {
// online config mode
switch (event.buttonId) {
case BUTTON_1: // switch day/night mode
if (ledmode == 'D') {
Serial.println("Night mode enabled");
ledmode = 'N';
} else {
Serial.println("Day mode enabled");
ledmode = 'D';
}
break;
case BUTTON_2: // switch audio on/off
if (audiomode == 'E') {
Serial.println("Disabled audio");
audiomode = 'D';
} else {
Serial.println("Enabled audio");
audiomode = 'E';
}
break;
case BUTTON_3: // switch accesspoint on/off
if (apEnabled) {
Serial.println("Disable Accesspoint");
WiFi.softAPdisconnect(true);
apEnabled = false;
} else {
Serial.println("Enable Accesspoint");
WiFi.softAP(wifi_ssid, wifi_pass);
apEnabled = true;
}
break;
case BUTTON_4: // reserved
break;
case BUTTON_5: // reset
Serial.println("Device reset");
analogWrite(RGBLED_B, 0);
delay(500);
analogWrite(RGBLED_G, 255);
delay(500);
analogWrite(RGBLED_G, 0);
delay(500);
analogWrite(RGBLED_G, 255);
delay(500);
analogWrite(RGBLED_G, 0);
delay(500);
analogWrite(RGBLED_G, 255);
delay(500);
ESP.restart();
break;
case BUTTON_6: // deep sleep
Serial.println("Going into deep sleep");
Serial.flush();
analogWrite(RGBLED_B, 0);
delay(500);
analogWrite(RGBLED_B, 255);
delay(500);
analogWrite(RGBLED_B, 0);
delay(500);
analogWrite(RGBLED_B, 255);
delay(500);
analogWrite(RGBLED_B, 0);
delay(500);
analogWrite(RGBLED_B, 255);
delay(500);
rtc_gpio_pullup_en(KEY_DST);
rtc_gpio_pulldown_dis(KEY_DST);
esp_deep_sleep_start();
break;
}
}
}
}
if (digitalRead(KEY_4) == LOW) {
Serial.println("Button detected: 4");
button += 8;
atariKeyclick();
digitalWrite(LED_USER, HIGH); // Turn LED on
delay(500); // Keep it on 0.5s
digitalWrite(LED_USER, LOW); // Turn LED off
}
if (digitalRead(KEY_5) == LOW) {
Serial.println("Button detected: 5");
button += 16;
ledcWriteTone(LEDC_CHANNEL, 3200);
delay(8);
ledcWriteTone(LEDC_CHANNEL, 0);
digitalWrite(LED_USER, HIGH); // Turn LED on
delay(500); // Keep it on 0.5s
digitalWrite(LED_USER, LOW); // Turn LED off
}
if (digitalRead(KEY_6) == LOW) {
Serial.println("Button detected: 6");
button += 32;
ledcWriteTone(LEDC_CHANNEL, 3200);
delay(8);
ledcWriteTone(LEDC_CHANNEL, 0);
digitalWrite(LED_USER, HIGH); // Turn LED on
delay(500); // Keep it on 0.5s
digitalWrite(LED_USER, LOW); // Turn LED off
}
if (digitalRead(KEY_DST) == LOW) {
Serial.println("Button detected: DST");
button += 64;
if (destination == 'A') {
destination = 'B';
analogWrite(LED_A, 0);
analogWrite(LED_B, led_brightness);
} else if (destination == 'B') {
destination = 'C';
analogWrite(LED_B, 0);
analogWrite(LED_C, led_brightness);
} else {
destination = 'A';
analogWrite(LED_C, 0);
analogWrite(LED_A, led_brightness);
}
Serial.print("Destination=");
Serial.println(destination);
/*
digitalWrite(LED_USER, HIGH); // Turn LED on
delay(500); // Keep it on 0.5s
digitalWrite(LED_USER, LOW); // Turn LED off
*/
}
if (button > 0) {
Serial.print(temp, 1);
Serial.print("\t");
Serial.println(hum, 1);
// Debounce delay to avoid multiple triggers
delay(200);
}
// NMEA2000.loop();
// NMEA2000.ParseMessages();
NMEA2000.loop();
NMEA2000.ParseMessages();
if (millis() - lastSensor >= 5000) {
lastSensor = millis();
@@ -544,4 +788,5 @@ void loop() {
Serial.printf("Loop counter: %lu\n", counter);
}
delay(1); // 1ms für freertos
}

View File

@@ -125,5 +125,65 @@
],
"description": "Temperature format: Kelvin, Celsius or Fahrenheit [K|C|F].",
"category": "Units"
},
{
"name": "key1",
"label": "Key 1 code",
"type": "number",
"default": 1,
"min": 1,
"max": 28,
"description": "The keycode to send for key 1 (leftmost) [1 .. 28]",
"category": "Keys"
},
{
"name": "key2",
"label": "Key 2 code",
"type": "number",
"default": 2,
"min": 1,
"max": 28,
"description": "The keycode to send for key 2 (second from left) [1 .. 28]",
"category": "Keys"
},
{
"name": "key3",
"label": "Key 3 code",
"type": "number",
"default": 3,
"min": 1,
"max": 28,
"description": "The keycode to send for key 3 (third from left) [1 .. 28]",
"category": "Keys"
},
{
"name": "key4",
"label": "Key 4 code",
"type": "number",
"default": 4,
"min": 1,
"max": 28,
"description": "The keycode to send for key 4 (fourth from left) [1 .. 28]",
"category": "Keys"
},
{
"name": "key5",
"label": "Key 5 code",
"type": "number",
"default": 5,
"min": 1,
"max": 28,
"description": "The keycode to send for key 5 (fifth from left) [1 .. 28]",
"category": "Keys"
},
{
"name": "key6",
"label": "Key 6 code",
"type": "number",
"default": 6,
"min": 1,
"max": 28,
"description": "The keycode to send for key 6 (rightmost) [1 .. 28]",
"category": "Keys"
}
]