From d8de1505056e02225c21ae7df7e444abfd80577a Mon Sep 17 00:00:00 2001 From: sfja Date: Fri, 27 Mar 2026 18:21:35 +0100 Subject: [PATCH] add skateboard --- skateboard/.clang-format | 15 +++++ skateboard/.clangd | 9 +++ skateboard/.gitignore | 6 ++ skateboard/CMakeLists.txt | 6 ++ skateboard/dependencies.lock | 77 ++++++++++++++++++++++ skateboard/main/CMakeLists.txt | 5 ++ skateboard/main/Kconfig.projbuild | 43 +++++++++++++ skateboard/main/idf_component.yml | 17 +++++ skateboard/main/skateboard.c | 102 ++++++++++++++++++++++++++++++ skateboard/main/wifi.c | 101 +++++++++++++++++++++++++++++ skateboard/main/wifi.h | 10 +++ skateboard/sdkconfig.defaults | 4 ++ 12 files changed, 395 insertions(+) create mode 100644 skateboard/.clang-format create mode 100644 skateboard/.clangd create mode 100644 skateboard/.gitignore create mode 100644 skateboard/CMakeLists.txt create mode 100644 skateboard/dependencies.lock create mode 100644 skateboard/main/CMakeLists.txt create mode 100644 skateboard/main/Kconfig.projbuild create mode 100644 skateboard/main/idf_component.yml create mode 100644 skateboard/main/skateboard.c create mode 100644 skateboard/main/wifi.c create mode 100644 skateboard/main/wifi.h create mode 100644 skateboard/sdkconfig.defaults diff --git a/skateboard/.clang-format b/skateboard/.clang-format new file mode 100644 index 0000000..859ab4c --- /dev/null +++ b/skateboard/.clang-format @@ -0,0 +1,15 @@ +BasedOnStyle: WebKit +IndentWidth: 4 +ColumnLimit: 80 + +IndentCaseLabels: true +InsertNewlineAtEOF: true +AllowShortFunctionsOnASingleLine: None + +BinPackArguments: false +BinPackLongBracedList: false +BinPackParameters: OnePerLine + +AllowAllArgumentsOnNextLine: true +AllowAllParametersOfDeclarationOnNextLine: true + diff --git a/skateboard/.clangd b/skateboard/.clangd new file mode 100644 index 0000000..f2f32f2 --- /dev/null +++ b/skateboard/.clangd @@ -0,0 +1,9 @@ +CompileFlags: + Remove: + [ + "-mlongcalls", + "-fno-shrink-wrap", + "-fstrict-volatile-bitfields", + "-fno-tree-switch-conversion", + ] + diff --git a/skateboard/.gitignore b/skateboard/.gitignore new file mode 100644 index 0000000..4da4f7b --- /dev/null +++ b/skateboard/.gitignore @@ -0,0 +1,6 @@ +build/ +managed_components/ +sdkconfig +sdkconfig.old +.cache/ + diff --git a/skateboard/CMakeLists.txt b/skateboard/CMakeLists.txt new file mode 100644 index 0000000..d9465e7 --- /dev/null +++ b/skateboard/CMakeLists.txt @@ -0,0 +1,6 @@ +# The following five lines of boilerplate have to be in your project's +# CMakeLists in this exact order for cmake to work correctly +cmake_minimum_required(VERSION 3.16) + +include($ENV{IDF_PATH}/tools/cmake/project.cmake) +project(skateboard) diff --git a/skateboard/dependencies.lock b/skateboard/dependencies.lock new file mode 100644 index 0000000..469c011 --- /dev/null +++ b/skateboard/dependencies.lock @@ -0,0 +1,77 @@ +dependencies: + esp-idf-lib/esp_idf_lib_helpers: + component_hash: 689853bb8993434f9556af0f2816e808bf77b5d22100144b21f3519993daf237 + dependencies: [] + source: + registry_url: https://components.espressif.com + type: service + targets: + - esp32 + - esp32c2 + - esp32c3 + - esp32c5 + - esp32c6 + - esp32c61 + - esp32h2 + - esp32p4 + - esp32s2 + - esp32s3 + version: 1.4.0 + esp-idf-lib/i2cdev: + component_hash: 9e22a91420695242ceac2c00788820ae45826224d38ef003a1a894367c55ede4 + dependencies: + - name: esp-idf-lib/esp_idf_lib_helpers + registry_url: https://components.espressif.com + require: private + version: '*' + source: + registry_url: https://components.espressif.com + type: service + targets: + - esp32 + - esp32c2 + - esp32c3 + - esp32c5 + - esp32c6 + - esp32c61 + - esp32h2 + - esp32p4 + - esp32s2 + - esp32s3 + version: 2.1.1 + esp-idf-lib/mpu6050: + component_hash: 2d4c6db42322162aeadded002cb811028f05115d969e143bad6470822cc75a8a + dependencies: + - name: esp-idf-lib/esp_idf_lib_helpers + registry_url: https://components.espressif.com + require: private + version: '*' + - name: esp-idf-lib/i2cdev + registry_url: https://components.espressif.com + require: private + version: '*' + source: + registry_url: https://components.espressif.com/ + type: service + targets: + - esp32 + - esp32c2 + - esp32c3 + - esp32c5 + - esp32c6 + - esp32c61 + - esp32h2 + - esp32p4 + - esp32s2 + - esp32s3 + version: 2.1.9 + idf: + source: + type: idf + version: 5.5.3 +direct_dependencies: +- esp-idf-lib/mpu6050 +- idf +manifest_hash: 555befbc35f7160bcfad0b8961e2bbca4bfb6b90242eecc7749fe036d221aa41 +target: esp32s3 +version: 2.0.0 diff --git a/skateboard/main/CMakeLists.txt b/skateboard/main/CMakeLists.txt new file mode 100644 index 0000000..7fbd8bb --- /dev/null +++ b/skateboard/main/CMakeLists.txt @@ -0,0 +1,5 @@ +idf_component_register( + SRCS skateboard.c wifi.c + PRIV_REQUIRES nvs_flash esp_wifi + INCLUDE_DIRS ".") + diff --git a/skateboard/main/Kconfig.projbuild b/skateboard/main/Kconfig.projbuild new file mode 100644 index 0000000..bb8c6cf --- /dev/null +++ b/skateboard/main/Kconfig.projbuild @@ -0,0 +1,43 @@ +menu "Skateboard config" + + config SKATEBOARD_WIFI_SSID + string "WIFI SSID" + default "myssid" + + config SKATEBOARD_WIFI_PASSWORD + string "WIFI password" + default "mypassword" + + config SKATEBOARD_WIFI_MAXIMUM_RETRIES + int "WIFI maximum connection retries" + default 5 + + choice MPU6050_I2C_ADDRESS + prompt "Select I2C address" + default MPU6050_I2C_ADDRESS_LOW + help + Select I2C address + + config MPU6050_I2C_ADDRESS_LOW + bool "MPU6050_I2C_ADDRESS_LOW" + help + Choose this when ADDR pin is disconnected or connected to ground + config MPU6050_I2C_ADDRESS_HIGH + bool "MPU6050_I2C_ADDRESS_HIGH" + help + Choose this when ADDR pin is connected to VCC + endchoice + + config MPU6050_SCL_GPIO + int "MPU6050 SCL GPIO Number" + default 12 + help + GPIO number for I2C Master clock line. + + config MPU6050_SDA_GPIO + int "MPU6050 SDA GPIO Number" + default 11 + help + GPIO number for I2C Master data line. + +endmenu diff --git a/skateboard/main/idf_component.yml b/skateboard/main/idf_component.yml new file mode 100644 index 0000000..97b2d96 --- /dev/null +++ b/skateboard/main/idf_component.yml @@ -0,0 +1,17 @@ +## IDF Component Manager Manifest File +dependencies: + ## Required IDF version + idf: + version: '>=4.1.0' + # # Put list of dependencies here + # # For components maintained by Espressif: + # component: "~1.0.0" + # # For 3rd party components: + # username/component: ">=1.0.0,<2.0.0" + # username2/component2: + # version: "~1.0.0" + # # For transient dependencies `public` flag can be set. + # # `public` flag doesn't have an effect dependencies of the `main` component. + # # All dependencies of `main` are public by default. + # public: true + esp-idf-lib/mpu6050: '*' diff --git a/skateboard/main/skateboard.c b/skateboard/main/skateboard.c new file mode 100644 index 0000000..7242a36 --- /dev/null +++ b/skateboard/main/skateboard.c @@ -0,0 +1,102 @@ +#include "esp_log.h" +#include "esp_wifi.h" +#include "freertos/idf_additions.h" +#include "i2cdev.h" +#include "mpu6050.h" +#include "nvs_flash.h" +#include "wifi.h" +#include + +const char* TAG = "skateboard"; + +#ifdef CONFIG_MPU6050_I2C_ADDRESS_LOW +#define MPU6050_I2C_ADDRESS MPU6050_I2C_ADDRESS_LOW +#else +#define MPU6050_I2C_ADDRESS MPU6050_I2C_ADDRESS_HIGH +#endif + +#define MPU6050_SDA_GPIO CONFIG_MPU6050_SDA_GPIO +#define MPU6050_SCL_GPIO CONFIG_MPU6050_SCL_GPIO + +typedef struct App { + AppWifi wifi; +} App; + +void app_main(void) +{ + ESP_LOGI(TAG, "Initializing"); + ESP_LOGI(TAG, "IDF version: %s", esp_get_idf_version()); + + esp_err_t status = nvs_flash_init(); + if (status == ESP_ERR_NVS_NO_FREE_PAGES + || status == ESP_ERR_NVS_NEW_VERSION_FOUND) { + ESP_ERROR_CHECK(nvs_flash_erase()); + status = nvs_flash_init(); + } + ESP_ERROR_CHECK(status); + + App app = { + .wifi = { + .wifi_event_group = 0, + .wifi_retries = 0, + }, + }; + + app_wifi_init(&app.wifi); + + ESP_ERROR_CHECK(i2cdev_init()); + + mpu6050_dev_t mpu = { 0 }; + + ESP_ERROR_CHECK(mpu6050_init_desc( + &mpu, MPU6050_I2C_ADDRESS, 0, MPU6050_SDA_GPIO, MPU6050_SCL_GPIO)); + ESP_LOGI(TAG, + "Initializing MPU6050 device. Address: 0x%02x, SDA %d, SCL: %d", + MPU6050_I2C_ADDRESS, + MPU6050_SDA_GPIO, + MPU6050_SCL_GPIO); + + while (true) { + esp_err_t res = i2c_dev_probe(&mpu.i2c_dev, I2C_DEV_WRITE); + if (res == ESP_OK) { + ESP_LOGI(TAG, "Found MPU6050 device"); + break; + } + ESP_LOGE(TAG, "MPU6050 not found"); + vTaskDelay(pdMS_TO_TICKS(1000)); + } + + ESP_ERROR_CHECK(mpu6050_init(&mpu)); + + ESP_LOGI(TAG, "Acceleration range: %d", mpu.ranges.accel); + ESP_LOGI(TAG, "Gyroscope range: %d", mpu.ranges.gyro); + + ESP_LOGI(TAG, "Initialized"); + ESP_LOGI(TAG, "Free memory: %" PRIu32 " bytes", esp_get_free_heap_size()); + + while (true) { + float temp; + mpu6050_acceleration_t accel = { 0 }; + mpu6050_rotation_t rotation = { 0 }; + + ESP_ERROR_CHECK(mpu6050_get_temperature(&mpu, &temp)); + ESP_ERROR_CHECK(mpu6050_get_motion(&mpu, &accel, &rotation)); + + ESP_LOGI(TAG, + "******************************************************************" + "****"); + ESP_LOGI(TAG, + "Acceleration: x=%.4f y=%.4f z=%.4f", + accel.x, + accel.y, + accel.z); + ESP_LOGI(TAG, + "Rotation: x=%.4f y=%.4f z=%.4f", + rotation.x, + rotation.y, + rotation.z); + ESP_LOGI(TAG, "Temperature: %.1f", temp); + + vTaskDelay(pdMS_TO_TICKS(100)); + } +} diff --git a/skateboard/main/wifi.c b/skateboard/main/wifi.c new file mode 100644 index 0000000..2e05dd4 --- /dev/null +++ b/skateboard/main/wifi.c @@ -0,0 +1,101 @@ +#include "wifi.h" +#include "esp_log.h" +#include "esp_wifi.h" +#include "freertos/idf_additions.h" + +extern const char* TAG; + +#define WIFI_SSID CONFIG_SKATEBOARD_WIFI_SSID +#define WIFI_PASSWORD CONFIG_SKATEBOARD_WIFI_PASSWORD +#define WIFI_MAXIMUM_RETRIES CONFIG_SKATEBOARD_WIFI_MAXIMUM_RETRIES + +enum { + Ev_Connected = 1 << 0, + Ev_Failed = 1 << 1, +}; + +static void event_handler( + void* arg, esp_event_base_t base, int32_t id, void* data) +{ + AppWifi* app = arg; + + if (base == WIFI_EVENT && id == WIFI_EVENT_STA_START) { + esp_wifi_connect(); + return; + } + + if (base == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) { + esp_wifi_connect(); + + if (app->wifi_retries < WIFI_MAXIMUM_RETRIES) { + esp_wifi_connect(); + app->wifi_retries += 1; + ESP_LOGE(TAG, + "WIFI connection failed. Retrying (%d/%d)", + app->wifi_retries + 1, + WIFI_MAXIMUM_RETRIES); + return; + } + + xEventGroupSetBits(app->wifi_event_group, Ev_Failed); + return; + } + + if (base == IP_EVENT && id == IP_EVENT_STA_GOT_IP) { + ip_event_got_ip_t* ip_event = (ip_event_got_ip_t*)data; + app->wifi_retries = 0; + ESP_LOGI(TAG, + "WIFI connected with IP " IPSTR, + IP2STR(&ip_event->ip_info.ip)); + xEventGroupSetBits(app->wifi_event_group, Ev_Connected); + return; + } +} + +void app_wifi_init(AppWifi* wifi) +{ + wifi->wifi_event_group = xEventGroupCreate(); + + ESP_ERROR_CHECK(esp_netif_init()); + ESP_ERROR_CHECK(esp_event_loop_create_default()); + esp_netif_create_default_wifi_sta(); + + wifi_init_config_t init_config = WIFI_INIT_CONFIG_DEFAULT(); + ESP_ERROR_CHECK(esp_wifi_init(&init_config)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register( + WIFI_EVENT, ESP_EVENT_ANY_ID, &event_handler, wifi, NULL)); + + ESP_ERROR_CHECK(esp_event_handler_instance_register( + IP_EVENT, IP_EVENT_STA_GOT_IP, &event_handler, wifi, NULL)); + + wifi_config_t config = { + .sta = { + .ssid = WIFI_SSID, + .password = WIFI_PASSWORD, + .threshold.authmode = WIFI_AUTH_WPA2_PSK, + }, + }; + ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA)); + ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &config)); + ESP_ERROR_CHECK(esp_wifi_start()); + + ESP_LOGI(TAG, "WIFI started"); + + EventBits_t event_bits = xEventGroupWaitBits(wifi->wifi_event_group, + Ev_Connected | Ev_Failed, + pdFALSE, + pdFALSE, + portMAX_DELAY); + + if (event_bits & Ev_Connected) { + ESP_LOGI(TAG, "WIFI connected to %s / '%s'", WIFI_SSID, WIFI_PASSWORD); + } else if (event_bits & Ev_Failed) { + ESP_LOGE(TAG, + "WIFI failed connecting to %s / '%s'", + WIFI_SSID, + WIFI_PASSWORD); + } else { + ESP_LOGE(TAG, "Unexpected event"); + } +} diff --git a/skateboard/main/wifi.h b/skateboard/main/wifi.h new file mode 100644 index 0000000..98ce5a0 --- /dev/null +++ b/skateboard/main/wifi.h @@ -0,0 +1,10 @@ +#pragma once + +#include "freertos/idf_additions.h" + +typedef struct AppWifi { + EventGroupHandle_t wifi_event_group; + int wifi_retries; +} AppWifi; + +void app_wifi_init(AppWifi* wifi); diff --git a/skateboard/sdkconfig.defaults b/skateboard/sdkconfig.defaults new file mode 100644 index 0000000..9f63114 --- /dev/null +++ b/skateboard/sdkconfig.defaults @@ -0,0 +1,4 @@ +# This file was generated using idf.py save-defconfig. It can be edited manually. +# Espressif IoT Development Framework (ESP-IDF) 5.5.3 Project Minimal Configuration +# +CONFIG_IDF_TARGET="esp32s3"