Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 34 additions & 0 deletions .github/workflows/esp-idf.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
name: ESP-IDF

on: [push, pull_request]

concurrency:
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
cancel-in-progress: true

jobs:

build:
name: "ESP-IDF ${{ matrix.idf_ver }}"
runs-on: ubuntu-latest
timeout-minutes: 10

strategy:
fail-fast: false
matrix:
#idf_ver: ["v4.4.7", "v5.1.4", "v5.3.2"]
idf_ver: ["v5.4.1"]
idf_target: ["esp32"]

steps:
- uses: actions/checkout@v4
with:
path: ${{ github.workspace }}/app

- name: Compile
uses: espressif/esp-idf-ci-action@v1
with:
esp_idf_version: ${{ matrix.idf_ver }}
target: ${{ matrix.idf_target }}
path: app/examples/knx-demo-esp-idf
command: apt-get update && apt-get install -y python3-venv && idf.py build
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# knx

This projects provides a knx-device stack for arduino (ESP8266, ESP32, SAMD21, RP2040, STM32), CC1310 and linux. (more are quite easy to add)
This projects provides a knx-device stack for Arduino (ESP8266, ESP32, SAMD21, RP2040, STM32), CC1310, ESP IDF and Linux. (more are quite easy to add)
It implements most of System-B specification and can be configured with ETS.
The necessary knxprod-files can be generated with the [Kaenx-Creator](https://github.com/OpenKNX/Kaenx-Creator) tool.

Expand Down
14 changes: 14 additions & 0 deletions examples/knx-demo-esp-idf/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 3.16)
include($ENV{IDF_PATH}/tools/cmake/project.cmake)

# require for knx components
add_definitions(
-Wno-unknown-pragmas
-DMASK_VERSION=0x07B0
-DKNX_NO_AUTOMATIC_GLOBAL_INSTANCE
-DKNX_FLASH_SIZE=4096
#-DKNX_NO_PRINT
#-Wno-stringop-truncation
)

project(knx-demo-diy-idf)
29 changes: 29 additions & 0 deletions examples/knx-demo-esp-idf/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# KNX Demo DIY (ESP-IDF 5.x Native)

This is a native ESP-IDF 5.x example project for KNX, based on the Arduino `knx-demo-diy` example but using the new `Esp32IdfPlatform` for direct ESP-IDF support.

## Features
- Uses the native ESP-IDF APIs (no Arduino layer)
- Demonstrates KNX stack integration on ESP32
- Based on the logic of the Arduino `knx-demo-diy.ino` example

## How to Build

1. Install [ESP-IDF 5.x](https://docs.espressif.com/projects/esp-idf/en/latest/esp32/get-started/)
2. Open a terminal in this directory (`examples/knx-demo-esp-idf`)
3. Run:
```sh
idf.py set-target esp32
idf.py build
idf.py -p /dev/ttyUSB0 flash monitor
```
(Replace `/dev/ttyUSB0` with your ESP32 serial port)

## Project Structure
- `main.c` — Main application file (C++ code, but named .c for ESP-IDF compatibility)
- `CMakeLists.txt` — ESP-IDF build configuration

## Notes
- This project uses the new `Esp32IdfPlatform` class for native ESP-IDF support.
- You may need to adapt pin numbers and KNX configuration for your hardware.
- The logic is adapted from the Arduino `knx-demo-diy.ino` example.
11 changes: 11 additions & 0 deletions examples/knx-demo-esp-idf/components/knx/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
# Define the directory containing your source files
set(SOURCE_DIR "../../../../src")
set(SOURCE_DIR_1 "../../../../src/knx")

# Use file(GLOB) to find all .cpp files in the 'src' directory
file(GLOB SOURCE_FILES "${SOURCE_DIR}/*.cpp")
file(GLOB SOURCE_FILES_1 "${SOURCE_DIR_1}/*.cpp")

idf_component_register(SRCS ${SOURCE_FILES} ${SOURCE_FILES_1}
INCLUDE_DIRS "../../../../src" "../../../../src/knx"
REQUIRES esp_netif driver esp_timer esp_wifi freertos nvs_flash esp_system)
12 changes: 12 additions & 0 deletions examples/knx-demo-esp-idf/main/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
idf_component_register(
SRCS "main.cpp"
INCLUDE_DIRS "."
REQUIRES
knx
esp_timer
nvs_flash
esp_wifi
esp_event
esp_netif
mdns
)
2 changes: 2 additions & 0 deletions examples/knx-demo-esp-idf/main/idf_component.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
dependencies:
espressif/mdns: ^1.8.2
162 changes: 162 additions & 0 deletions examples/knx-demo-esp-idf/main/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,162 @@
#include "esp32_idf_platform.h"
#include "knx_facade.h"
#include "knx/bau07B0.h"
#include "knx/group_object.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "esp_log.h"
#include <esp_timer.h>
#include <freertos/FreeRTOS.h>
#include <freertos/task.h>
#include <cstring>
#include <stdlib.h>
#include <limits.h>

#define WIFI_SSID "your_ssid"
#define WIFI_PASS "your_password"
#define MASK_VERSION 0x07B0

static const char *TAG = "knx-demo";

// --- KNX Group Object Shortcuts ---
#define goCurrent knx.getGroupObject(1)
#define goMax knx.getGroupObject(2)
#define goMin knx.getGroupObject(3)
#define goReset knx.getGroupObject(4)

// --- Global Variables ---
float currentValue = 0;
float maxValue = 0;
float minValue = RAND_MAX;
int64_t lastsend = 0;

// --- KNX Stack Instance (migrated pattern) ---
Esp32IdfPlatform knxPlatform(UART_NUM_1); // Use UART_NUM_1, change if needed
Bau07B0 knxBau(knxPlatform);
KnxFacade<Esp32IdfPlatform, Bau07B0> knx(knxBau);

// --- WiFi event handler ---
static esp_netif_t* s_wifi_netif = nullptr;
static void wifi_event_handler(void* arg, esp_event_base_t event_base,
int32_t event_id, void* event_data) {
if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) {
esp_wifi_connect();
} else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
esp_wifi_connect();
ESP_LOGI(TAG, "Retrying connection to the WiFi AP");
} else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
ip_event_got_ip_t* event = (ip_event_got_ip_t*) event_data;
ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));
if (s_wifi_netif) {
knxPlatform.setNetif(s_wifi_netif);
}
}
}

// --- Button ISR (simulate with a function call or GPIO interrupt in real use) ---
void myButtonPressed() {
static int64_t lastpressed = 0;
int64_t now = esp_timer_get_time() / 1000; // ms
if (now - lastpressed > 200) {
knx.toggleProgMode();
lastpressed = now;
}
}

// --- KNX Reset Callback ---
void resetCallback(GroupObject& go) {
if (go.value()) {
maxValue = 0;
minValue = 10000;
}
}

// --- Simulate temperature measurement ---
void measureTemp() {
int64_t now = esp_timer_get_time() / 1000; // ms
if ((now - lastsend) < 2000)
return;

lastsend = now;
int r = rand();
currentValue = (r * 1.0) / (RAND_MAX * 1.0);
currentValue *= 100 * 100;

goCurrent.value(currentValue);

if (currentValue > maxValue) {
maxValue = currentValue;
goMax.value(maxValue);
}
if (currentValue < minValue) {
minValue = currentValue;
goMin.value(minValue);
}
}

extern "C" void app_main(void) {
// Initialize NVS
esp_err_t ret = nvs_flash_init();
if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
ESP_ERROR_CHECK(nvs_flash_erase());
ret = nvs_flash_init();
}
ESP_ERROR_CHECK(ret);

// Initialize TCP/IP and WiFi
ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
s_wifi_netif = esp_netif_create_default_wifi_sta();

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));
ESP_ERROR_CHECK(esp_event_handler_instance_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL, NULL));
ESP_ERROR_CHECK(esp_event_handler_instance_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL, NULL));

wifi_config_t wifi_config = {};
strcpy((char*)wifi_config.sta.ssid, WIFI_SSID);
strcpy((char*)wifi_config.sta.password, WIFI_PASS);

ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());

ESP_LOGI(TAG, "WiFi initialization finished.");

// Set UART pins (example: RX=16, TX=17)
knxPlatform.knxUartPins(16, 17);
knxPlatform.setupUart();

// Set button ISR
knx.setButtonISRFunction(myButtonPressed);

// Read KNX memory (address table, etc.)
knx.readMemory();

// Register group object callbacks and types if configured
if (knx.configured()) {
goReset.callback(resetCallback);
goReset.dataPointType(DPT_Trigger);
goCurrent.dataPointType(DPT_Value_Temp);
goMin.dataPointType(DPT_Value_Temp);
goMax.dataPointType(DPT_Value_Temp);

ESP_LOGI(TAG, "Timeout: %d", knx.paramByte(0));
ESP_LOGI(TAG, "Cyclic send: %d", knx.paramByte(1));
ESP_LOGI(TAG, "Min/Max send: %d", knx.paramByte(2));
ESP_LOGI(TAG, "Send on change: %d", knx.paramByte(3));
ESP_LOGI(TAG, "Alignment: %d", knx.paramByte(4));
}

// Start KNX stack
knx.start();

// Main loop
while (1) {
knx.loop();
if (knx.configured()) {
measureTemp();
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
4 changes: 4 additions & 0 deletions src/arduino_platform.cpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#ifdef ARDUINO

#include "arduino_platform.h"
#include "knx/bits.h"

Expand Down Expand Up @@ -309,3 +311,5 @@ void println(void)
ArduinoPlatform::SerialDebug->println();
}
#endif // KNX_NO_PRINT

#endif // ARDUINO
3 changes: 3 additions & 0 deletions src/arduino_platform.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#pragma once

#ifdef ARDUINO

#include "knx/platform.h"

#include "Arduino.h"
Expand Down Expand Up @@ -42,3 +44,4 @@ class ArduinoPlatform : public Platform
protected:
HardwareSerial* _knxSerial;
};
#endif // ARDUINO
Loading
Loading