diff --git a/.gitignore b/.gitignore index 4de822f..4b9f1da 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,8 @@ .vscode/launch.json .vscode/ipch .DS_Store +upload_params.ini + +# projectplan and design +*.kanban +*.excalidraw diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..901dd8b --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,23 @@ +{ + "files.associations": { + "*.json": "json", + "array": "cpp", + "deque": "cpp", + "string": "cpp", + "unordered_map": "cpp", + "unordered_set": "cpp", + "vector": "cpp", + "string_view": "cpp", + "initializer_list": "cpp", + "span": "cpp", + "*.tcc": "cpp", + "system_error": "cpp", + "regex": "cpp", + "compare": "cpp", + "functional": "cpp", + "tuple": "cpp", + "type_traits": "cpp", + "utility": "cpp", + "limits": "cpp" + } +} \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 18c1792..61654f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,5 @@ CHANGELOG -## v0.0.0 +## v1.0.0 -PLEASE WRITE YOUR CHANGES BEFORE YOU CREATE A RELEASE IN THE CHANGELOG.MD FILE! +Add RGB NeoPixel example. \ No newline at end of file diff --git a/README.md b/README.md index b77605e..5d48e70 100644 --- a/README.md +++ b/README.md @@ -1,91 +1,19 @@ -# ESP32 project template +# ESP32-C6 examples ## Description -This is a project template to create microcontroller apps with automatized firmware builds for [esp32](https://www.espressif.com/en/products/socs/esp32), [esp32s2](https://www.espressif.com/en/products/socs/esp32-s2) and [esp32s3](https://www.espressif.com/en/products/socs/esp32-s3) microcontroller boards. It uses for that [GitHub Actions](https://github.com/features/actions) and [platformio](https://platformio.org/). Use this repository as a template for your own esp32 projects. +Uncomment `src_dir=` in the `platform.ini` file. -## Requirements - -- [GitHub Actions](https://github.com/features/actions) -- [platformio](https://platformio.org/) -- [python](https://www.python.org/) - -## GitHub Actions - Workflow - -The release build happens in the `build & release` workflow: [build_release.yml](.github/workflows/build_release.yml). -It creates a release, after creation of a new git tag (named it like `v1.0.0`). - -If you want to test the build on all merge w/o creating a tag then the `build` workflow is what you looking for: [build.yml](.github/workflows/build.yml) - -## PlatformIO - -[PlatformIO](https://platformio.org/) is a tool to create microcontroller apps for arduino platforms and compatibles (esp32). You can install the [Visual Studio Code extension](https://platformio.org/install/ide?install=vscode) in the [Visual Studio Code](https://code.visualstudio.com/) IDE. - -## Python - -There is a tiny python script needed to customize the firmware filenames within platformio, see documentation: https://docs.platformio.org/en/stable/scripting/examples/custom_program_name.html - -The [extra_script.py](extra_script.py) script gets the platformio env (e.g. lolin32) and the git-tag for the firmware filename. -This is required to publish several firmware names in the github artifacts of a release. - -## Get Started - - - -1. Login to github - -2. Click on `Use this template` to create a new git repository -3. Implement your application in the [src/main.cpp](src/main.cpp) -4. Comment your new change in the [CHANGELOG.md](CHANGELOG.md) file -5. Push your changes - -```sh -git add . -``` - -```sh -git commit -am "my app" -``` - -```sh -git push -u origin main -``` - -5. Create a new tag to trigger a release, e.g. for v1.0.0 - -```sh -git tag v1.0.0 -``` - -```sh -git push origin v1.0.0 -``` - -6. You can find your firmwares under `Releases` after the CI build finished - -## CHANGELOG - -You can write your changes in the [CHANGELOG.md](CHANGELOG.md) before you create a release. It will be shown under the release page. - -## Example Release - -see [Releases](https://github.com/mcuw/esp-ghbuild-template/releases) on the right sidemenu. - -## Customize your project - -You can reduce and adapt your required boards in the [platformio.ini](platformio.ini). +## Supported boards -Update the [CHANGELOG.md](CHANGELOG.md) file before you are creating a new release. By creating a new git tag you trigger a new release which generate for you the firmwares. +- [NanoESP32-C6](https://s.click.aliexpress.com/e/_ooBtUih) (affiliate link) with up to 16MB flash [datasheet](doc/nanoESP32C6.pdf) -## Supported boards +- [Super Mini ESP32-C6](https://s.click.aliexpress.com/e/_DeLjVMb) (affiliate link) with 4MB flash and W2812 RGB LED -- ESP32 (buy with affiliate link: [LILYGO T-Beam](https://s.click.aliexpress.com/e/_DBzslDV) with LoRA, lolin32, lolin D32 pro) -- ESP32 S2 -- ESP32 S3 (buy with affiliate link: [LILYGO T-Display S3](https://s.click.aliexpress.com/e/_DBmOMkn), [LILYGO T-Display-S3 AMOLED](https://s.click.aliexpress.com/e/_DmboYpZ), [LILYGO T-Display-S3 Touch](https://s.click.aliexpress.com/e/_DCBgPlV), [LILYGO T-Display S3 Long](https://s.click.aliexpress.com/e/_Dl6UVMx)) -- ESP32 C6 with WiFi 6 and BT-5 LE (buy with affiliate link: [UICPAL nanoESP32-C6](https://s.click.aliexpress.com/e/_DdZ83IB) with up to 16MB flash, [ESP32-C6](https://s.click.aliexpress.com/e/_DeLjVMb) with 4MB flash and W2812 RGB LED) +- [LilyGo T-QT-C6](https://github.com/mcuw/esp32-t-qt-c6-sdk): use Arduino SDK https://github.com/mcuw/esp32-t-qt-c6-sdk ## Disclaimer -Contribution and help ... if you find an issue or wants to contribute then please do not hesitate to create a merge request or an issue. +Contribution and help ... if you find an issue or wants to contribute then please do not hesitate to create a pull request or an issue. We provide our build template as is, and we make no promises or guarantees about this code. diff --git a/boards/esp32-c6-n16.json b/boards/esp32-c6-n16.json index 287f5e4..2bf4036 100644 --- a/boards/esp32-c6-n16.json +++ b/boards/esp32-c6-n16.json @@ -7,10 +7,11 @@ "mcu": "esp32c6", "variant": "esp32c6", "extra_flags": [ - "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_ESP32C6_DEV", "-DARDUINO_USB_MODE=1", "-DARDUINO_USB_CDC_ON_BOOT=1" - ] + ], + "partitions": "default_16MB.csv" }, "connectivity": [ "wifi", diff --git a/doc/nanoESP32C6.pdf b/doc/nanoESP32C6.pdf new file mode 100644 index 0000000..6b3ca9d Binary files /dev/null and b/doc/nanoESP32C6.pdf differ diff --git a/examples/mac/main.cpp b/examples/mac/main.cpp new file mode 100644 index 0000000..bb3926c --- /dev/null +++ b/examples/mac/main.cpp @@ -0,0 +1,14 @@ +#include +#include + +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + WiFi.mode(WIFI_STA); + Serial.println(WiFi.macAddress()); + delay(1000); +} \ No newline at end of file diff --git a/examples/ota-manager-rtos/credentials.h b/examples/ota-manager-rtos/credentials.h new file mode 100644 index 0000000..d5b84e8 --- /dev/null +++ b/examples/ota-manager-rtos/credentials.h @@ -0,0 +1,3 @@ +#ifndef AP_PSK +#define AP_PSK "12345678" +#endif diff --git a/examples/ota-manager-rtos/main.cpp b/examples/ota-manager-rtos/main.cpp new file mode 100644 index 0000000..51ec389 --- /dev/null +++ b/examples/ota-manager-rtos/main.cpp @@ -0,0 +1,257 @@ +#include +#include +#include +#include +#include +#include + +#include "credentials.h" +#include + +#define PREF_KEY "config" +#define PREF_SSID_KEY "ssid" +#define PREF_PASSPHRASE_KEY "passphrase" + +String ap_default_psk(AP_PSK); // Set your default PSK in credentials.h if you want +ESPTelnetStream telnet; + +WebServer server(80); +Preferences prefs; + +TaskHandle_t OTATask, TelnetTask, UiTask, SleepTask; +OTA ota; + +// sleep modes, see +// https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-reference/system/sleep_modes.html + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + // init RGB-LED + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); + + // you can initialize the dev board here ... +} + +void handleRoot() +{ + if (server.hasArg(PREF_SSID_KEY) && server.arg(PREF_SSID_KEY).length() && server.hasArg(PREF_PASSPHRASE_KEY) && server.arg(PREF_PASSPHRASE_KEY).length()) + { + const String ssid(server.arg(PREF_SSID_KEY)); + prefs.begin(PREF_KEY, false); + prefs.putString(PREF_SSID_KEY, ssid); + prefs.putString(PREF_PASSPHRASE_KEY, server.arg(PREF_PASSPHRASE_KEY)); + prefs.end(); + + serialPrint("Credentials saved for: "); + serialPrintln(ssid); + telnet.print("Credentials saved for: "); + telnet.println(ssid); + + char success[150]; + snprintf( + success, 148, + "\ +\ + ESP32-C6 OTA with webserver\ + \ +\ +\ +\ +"); + server.send(200, F("text/html"), success); + + return; + } + + prefs.begin(PREF_KEY, true); + const String ssid(prefs.isKey(PREF_SSID_KEY) ? prefs.getString(PREF_SSID_KEY) : ""); + prefs.end(); + + char temp[740]; + snprintf( + temp, 740, + "\ + \ + ESP32-C6 OTA with webserver\ + \ + \ + \ +

OTA and webserver example

\ +
\ +
\ +
\ + \ +
\ +
\ +
\ + \ +
\ +
\ + \ + \ +
\ +
\ + \ +", + ssid); + server.send(200, F("text/html"), temp); +} + +void handleSaved() +{ + char success[330]; + + snprintf( + success, 324, + "\ +\ + ESP32-C6 OTA with webserver\ + \ +\ +\ +

OTA and webserver example

\ +
Credentials saved. ESP is restarting and will be available under a new IP.
\ +\ +"); + server.send(200, F("text/html"), success); + + delay(2000); + ESP.restart(); +} + +void handleNotFound() +{ + String message("File Not Found\n\n"); + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + + for (uint8_t i = 0; i < server.args(); i++) + { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + + server.send(404, "text/plain", message); +} + +void otaTask(void *parameters) +{ + for (;;) + { + ota.handle(); + vTaskDelay(portTICK_PERIOD_MS); + } +} + +void telnetTask(void *parameters) +{ + for (;;) + { + telnet.loop(); + vTaskDelay(portTICK_PERIOD_MS); + } +} + +void uiTask(void *parameters) +{ + for (;;) + { + server.handleClient(); + vTaskDelay(portTICK_PERIOD_MS); + } +} + +void sleepTask(void *parameters) +{ + esp_err_t err = esp_sleep_enable_timer_wakeup(10 * 1000000); + if (err == ESP_ERR_INVALID_ARG) + { + telnet.print("sleep timer wakeup value is too high"); + telnet.println(err); + } + + for (;;) + { + if (ota.isLoading()) + { + vTaskDelay(1000 / portTICK_PERIOD_MS); + continue; + } + // TODO test this: + // esp_err_t err = esp_sleep_enable_wifi_wakeup(); + // telnet.println("enable wifi wakeup..."); + // telnet.println(err); + + // esp_now_deinit();x + neopixelWrite(PIN_NEOPIXEL, 0, 0, 0); + telnet.println("sleep ..."); + telnet.flush(); + serialFlush(); + err = esp_light_sleep_start(); // ESP_OK or ESP_ERR_INVALID_STATE + if (err == ESP_OK) + { + neopixelWrite(PIN_NEOPIXEL, 0, 255, 0); + + // wake up or failed + // err = esp_now_init(); + delay(100); + telnet.println("wake up ..."); + } + else + { + neopixelWrite(PIN_NEOPIXEL, 255, 0, 0); + telnet.println(err); + } + + // give other tasks time + vTaskDelay(10000 / portTICK_PERIOD_MS); + } +} + +void setup() +{ + serialBegin(115200); + + initDevBoard(0, 255, 0); + + prefs.begin(PREF_KEY, true); + String ssid(prefs.getString(PREF_SSID_KEY).c_str()); + String passphrase(prefs.getString(PREF_PASSPHRASE_KEY).c_str()); + prefs.end(); + serialPrint("SSID: "); + serialPrintln(ssid); + + ota.begin(ap_default_psk, ssid.c_str(), passphrase.c_str()); + telnet.begin(); + + server.on("/", handleRoot); + server.on("/saved", handleSaved); + server.onNotFound(handleNotFound); + server.begin(); + + xTaskCreatePinnedToCore(otaTask, "ota", 4096, NULL, 3, &OTATask, 0); + + xTaskCreatePinnedToCore(telnetTask, "debug", 4096, NULL, 2, &TelnetTask, 0); + + xTaskCreatePinnedToCore(uiTask, "ui", 4096, NULL, 2, &UiTask, 0); + + xTaskCreatePinnedToCore(sleepTask, "sleep", 2048, NULL, 1, &SleepTask, 0); +} + +void loop() +{ + // telnet.print("core: "); + // telnet.println(xPortGetCoreID()); + // delay(1000); + + // run only tasks w/o the non priorized loop task + vTaskDelete(NULL); +} diff --git a/examples/ota-manager/credentials.h b/examples/ota-manager/credentials.h new file mode 100644 index 0000000..d5b84e8 --- /dev/null +++ b/examples/ota-manager/credentials.h @@ -0,0 +1,3 @@ +#ifndef AP_PSK +#define AP_PSK "12345678" +#endif diff --git a/examples/ota-manager/main.cpp b/examples/ota-manager/main.cpp new file mode 100644 index 0000000..48e0acd --- /dev/null +++ b/examples/ota-manager/main.cpp @@ -0,0 +1,169 @@ +#include +#include +#include +#include +#include +#include + +#include "credentials.h" + +#define PREF_KEY "config" +#define PREF_SSID_KEY "ssid" +#define PREF_PASSPHRASE_KEY "passphrase" + +OTA ota; +String ap_default_psk(AP_PSK); // Set your default PSK in credentials.h if you want +ESPTelnetStream telnet; + +WebServer server(80); +Preferences prefs; + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + // init RGB-LED + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); + + // you can initialize the dev board here ... +} + +void handleRoot() +{ + if (server.hasArg(PREF_SSID_KEY) && server.arg(PREF_SSID_KEY).length() && server.hasArg(PREF_PASSPHRASE_KEY) && server.arg(PREF_PASSPHRASE_KEY).length()) + { + const String ssid(server.arg(PREF_SSID_KEY)); + prefs.begin(PREF_KEY, false); + prefs.putString(PREF_SSID_KEY, ssid); + prefs.putString(PREF_PASSPHRASE_KEY, server.arg(PREF_PASSPHRASE_KEY)); + prefs.end(); + + serialPrint("Credentials saved for: "); + serialPrintln(ssid); + telnet.print("Credentials saved for: "); + telnet.println(ssid); + + char success[150]; + snprintf( + success, 148, + "\ +\ + ESP32-C6 OTA with webserver\ + \ +\ +\ +\ +"); + server.send(200, F("text/html"), success); + + return; + } + + prefs.begin(PREF_KEY, true); + const String ssid(prefs.isKey(PREF_SSID_KEY) ? prefs.getString(PREF_SSID_KEY) : ""); + prefs.end(); + + char temp[740]; + snprintf( + temp, 740, + "\ + \ + ESP32-C6 OTA with webserver\ + \ + \ + \ +

OTA and webserver example

\ +
\ +
\ +
\ + \ +
\ +
\ +
\ + \ +
\ +
\ + \ + \ +
\ +
\ + \ +", + ssid); + server.send(200, F("text/html"), temp); +} + +void handleSaved() +{ + char success[330]; + + snprintf( + success, 324, + "\ +\ + ESP32-C6 OTA with webserver\ + \ +\ +\ +

OTA and webserver example

\ +
Credentials saved. ESP is restarting and will be available under a new IP.
\ +\ +"); + server.send(200, F("text/html"), success); + + delay(2000); + ESP.restart(); +} + +void handleNotFound() +{ + String message("File Not Found\n\n"); + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + + for (uint8_t i = 0; i < server.args(); i++) + { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + + server.send(404, "text/plain", message); +} + +void setup() +{ + serialBegin(115200); + delay(5000); + + initDevBoard(255, 0, 0); + + prefs.begin(PREF_KEY, true); + String ssid(prefs.getString(PREF_SSID_KEY).c_str()); + String passphrase(prefs.getString(PREF_PASSPHRASE_KEY).c_str()); + prefs.end(); + serialPrint("SSID: "); + serialPrintln(ssid); + + ota.begin(ap_default_psk, ssid.c_str(), passphrase.c_str()); + telnet.begin(); + + server.on("/", handleRoot); + server.on("/saved", handleSaved); + server.onNotFound(handleNotFound); + + server.begin(); +} + +void loop() +{ + ota.handle(); + telnet.loop(); + server.handleClient(); + delay(2); // give cpu time to do things +} diff --git a/examples/ota-telnet/credentials.h b/examples/ota-telnet/credentials.h new file mode 100644 index 0000000..d5b84e8 --- /dev/null +++ b/examples/ota-telnet/credentials.h @@ -0,0 +1,3 @@ +#ifndef AP_PSK +#define AP_PSK "12345678" +#endif diff --git a/examples/ota-telnet/main.cpp b/examples/ota-telnet/main.cpp new file mode 100644 index 0000000..8587e24 --- /dev/null +++ b/examples/ota-telnet/main.cpp @@ -0,0 +1,53 @@ +#include +#include +#include +#include +#include "credentials.h" + +OTA ota; +ESPTelnetStream telnet; + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + // reset RGB-LED + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); +} + +void setup() +{ + serialBegin(115200); + initDevBoard(0, 0, 0); + + ota.begin(AP_PSK); + // or use this for an existing WLAN: + // ota.begin(ap_default_psk, MY_SSID, PASSPHRASE); + + telnet.begin(); +} + +void loop() +{ + ota.handle(); + telnet.loop(); + + if (telnet.available() > 0) + { + int message = telnet.read(); + + switch (message) + { + case 'a': + neopixelWrite(PIN_NEOPIXEL, 0, 0, 255); + telnet.println("light"); + break; + + case 'o': + neopixelWrite(PIN_NEOPIXEL, 0, 0, 0); + telnet.println("dark"); + break; + } + } + + telnet.println("loop"); + delay(200); +} \ No newline at end of file diff --git a/examples/ota-webserver/credentials.h b/examples/ota-webserver/credentials.h new file mode 100644 index 0000000..d5b84e8 --- /dev/null +++ b/examples/ota-webserver/credentials.h @@ -0,0 +1,3 @@ +#ifndef AP_PSK +#define AP_PSK "12345678" +#endif diff --git a/examples/ota-webserver/main.cpp b/examples/ota-webserver/main.cpp new file mode 100644 index 0000000..4a8821d --- /dev/null +++ b/examples/ota-webserver/main.cpp @@ -0,0 +1,122 @@ +#include +#include +#include +#include + +#include "credentials.h" + +OTA ota; +String ap_default_psk(AP_PSK); // Set your default PSK in credentials.h if you want +ESPTelnetStream telnet; + +WebServer server(80); + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + // init RGB-LED + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); +} + +void handleRoot() +{ + if (server.hasArg("name")) + { + char success[350]; + const String message(F("\ +\ + ESP32-C6 OTA with webserver\ + \ +\ +\ +
Hello %s
\ +\ +")); + snprintf( + success, message.length(), + message.c_str(), + server.arg("name")); + server.send(200, F("text/html"), success); + + return; + } + + char temp[540]; + snprintf( + temp, 536, + "\ + \ + ESP32-C6 OTA with webserver\ + \ + \ + \ +

OTA and webserver example

\ +
\ +
\ +
\ + \ +
\ +
\ + \ + \ +
\ +
\ + \ +"); + server.send(200, "text/html", temp); +} + +void handleNotFound() +{ + String message("File Not Found\n\n"); + message += "URI: "; + message += server.uri(); + message += "\nMethod: "; + message += (server.method() == HTTP_GET) ? "GET" : "POST"; + message += "\nArguments: "; + message += server.args(); + message += "\n"; + + for (uint8_t i = 0; i < server.args(); i++) + { + message += " " + server.argName(i) + ": " + server.arg(i) + "\n"; + } + + server.send(404, "text/plain", message); +} + +void setup() +{ + initDevBoard(255, 0, 0); + + const char *MY_SSID = ""; + const char *PASSPHRASE = ""; + + // how to setup credentials (SSID, PASSPHRASE), + // see ota-manager example + ota.begin(ap_default_psk, MY_SSID, PASSPHRASE); + telnet.begin(); + + server.on("/", handleRoot); + server.onNotFound(handleNotFound); + + server.begin(); +} + +void loop() +{ + ota.handle(); + telnet.loop(); + server.handleClient(); + delay(2); // give cpu time to do things +} diff --git a/examples/ota/credentials.h b/examples/ota/credentials.h new file mode 100644 index 0000000..d5b84e8 --- /dev/null +++ b/examples/ota/credentials.h @@ -0,0 +1,3 @@ +#ifndef AP_PSK +#define AP_PSK "12345678" +#endif diff --git a/examples/ota/main.cpp b/examples/ota/main.cpp new file mode 100644 index 0000000..8ba635e --- /dev/null +++ b/examples/ota/main.cpp @@ -0,0 +1,34 @@ +#include +#include +#include +#include "credentials.h" + +OTA ota; + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + // reset RGB-LED + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); +} + +void setup() +{ + serialBegin(115200); + initDevBoard(0, 0, 0); + + ota.begin(AP_PSK); + // or use this for an existing WLAN: + // ota.begin(ap_default_psk, MY_SSID, PASSPHRASE); +} + +void loop() +{ + ota.handle(); + + // blink example + // neopixelWrite(PIN_NEOPIXEL, 0, 0, 255); + // delay(200); + + // neopixelWrite(PIN_NEOPIXEL, 0, 0, 0); + // delay(100); +} \ No newline at end of file diff --git a/examples/rgb/main.cpp b/examples/rgb/main.cpp new file mode 100644 index 0000000..0ceda06 --- /dev/null +++ b/examples/rgb/main.cpp @@ -0,0 +1,26 @@ +#include +#include + +// pinouts: https://github.com/espressif/arduino-esp32/blob/master/variants/esp32c6/pins_arduino.h + +// see https://github.com/wuxx/nanoESP32-C6 + +void setup() +{ + serialBegin(115200); +} + +void loop() +{ + serialPrintln("red"); + neopixelWrite(PIN_NEOPIXEL, 255, 0, 0); + delay(1000); + + serialPrintln("green"); + neopixelWrite(PIN_NEOPIXEL, 0, 255, 0); + delay(1000); + + serialPrintln("blue"); + neopixelWrite(PIN_NEOPIXEL, 0, 0, 255); + delay(1000); +} \ No newline at end of file diff --git a/examples/serial/main.cpp b/examples/serial/main.cpp new file mode 100644 index 0000000..a959396 --- /dev/null +++ b/examples/serial/main.cpp @@ -0,0 +1,12 @@ +#include + +void setup() +{ + Serial.begin(115200); +} + +void loop() +{ + Serial.println("loop"); + delay(2000); +} \ No newline at end of file diff --git a/examples/wifi-ap/main.cpp b/examples/wifi-ap/main.cpp new file mode 100644 index 0000000..4825009 --- /dev/null +++ b/examples/wifi-ap/main.cpp @@ -0,0 +1,21 @@ +#include +#include + +void setup() +{ + // Go into software AP mode. + WiFi.mode(WIFI_AP); + delay(10); + int channel = 1; + int ssid_hidden = 0; + int max_connection = 4; + WiFi.softAP("ESP32-c6", "passphrase", channel, ssid_hidden, max_connection, false, WIFI_AUTH_WPA3_PSK); +} + +void loop() +{ + neopixelWrite(PIN_NEOPIXEL, 255, 0, 0); + delay(200); + neopixelWrite(PIN_NEOPIXEL, 0, 0, 255); + delay(200); +} \ No newline at end of file diff --git a/include/DebugUtils.h b/include/DebugUtils.h new file mode 100644 index 0000000..33b42a3 --- /dev/null +++ b/include/DebugUtils.h @@ -0,0 +1,26 @@ +#ifndef DEBUG_UTILS_H + +/** + * Currently facing an issue that + * when using serial prints over the USB Serial + * the ESP32 is not working w/o an open USB Serial terminal/ monitor + * activate serial in platform.ini if needed: + +[env] +build_flags = + '-DSERIAL_DEBUG' +*/ + +#ifdef SERIAL_DEBUG +#define serialBegin(x) Serial.begin(x) +#define serialPrint(x) Serial.print(x) +#define serialPrintln(x) Serial.println(x) +#define serialFlush() Serial.flush() +#else +#define serialBegin(x) +#define serialPrint(x) +#define serialPrintln(x) +#define serialFlush() +#endif + +#endif diff --git a/lib/OTA/OTA.cpp b/lib/OTA/OTA.cpp new file mode 100644 index 0000000..0e35cc6 --- /dev/null +++ b/lib/OTA/OTA.cpp @@ -0,0 +1,169 @@ +#include +#include +#include "./OTA.h" + +#define HOSTNAME_PREFIX "ESP32-" + +bool loading = false; + +OTA::OTA() +{ +} + +// get MAC of STA-, Serial- and ESPNow-MAC +String OTA::getHostname() +{ + String hostname(HOSTNAME_PREFIX); + if (WiFi.getMode() != WIFI_STA) + { + WiFi.mode(WIFI_STA); + delay(10); + } + hostname += WiFi.macAddress(); + hostname.replace(":", ""); + WiFi.disconnect(true); + return hostname; +} + +void OTA::startAP(const String &passphrase) +{ + String hostname(getHostname()); + WiFi.mode(WIFI_AP); + delay(10); + int channel = 1; + int ssid_hidden = 0; + int max_connection = 4; + if (WiFi.softAP(hostname, passphrase, channel, ssid_hidden, max_connection, false, WIFI_AUTH_WPA3_PSK)) + { + // Start OTA server. + ArduinoOTA.setHostname(hostname.c_str()); // open http://esp32-XX.local + ArduinoOTA.setPassword(passphrase.c_str()); + ArduinoOTA.begin(); + } + else + { + neopixelWrite(PIN_NEOPIXEL, 255, 0, 0); + } +} + +boolean OTA::startSTA(const char *station_ssid, const char *station_passphrase, const String &passphrase) +{ + if (strcmp(station_ssid, "") == 0 || strcmp(station_passphrase, "") == 0) + { + return false; + } + + String hostname(getHostname()); + // Serial.println(hostname); + + // Check Wifi mode + if (WiFi.getMode() != WIFI_STA) + { + WiFi.mode(WIFI_STA); + delay(10); + } + + // Compare file config with sdk config + if (strcmp(WiFi.SSID().c_str(), station_ssid) == 0 && strcmp(WiFi.psk().c_str(), station_passphrase) == 0) + { + // Begin with sdk config + WiFi.begin(); + } + else + { + // Serial.println(F("WiFi config changed")); + + // Connect to WiFi station + WiFi.begin(station_ssid, station_passphrase); + + // Serial.print("New SSID: "); + // Serial.println(WiFi.SSID()); + } + + // Give ESP 10 seconds to connect to station + unsigned long startTime = millis(); + while (WiFi.status() != WL_CONNECTED && millis() - startTime < 10000) + { + // Serial.print("."); + // Serial.print(WiFi.status()); + delay(500); + } + // Serial.println(); + + // Check connection + if (WiFi.status() != WL_CONNECTED) + { + // Serial.println("Failed to connect to WiFi station"); + return false; + } + + // print IP Address + // Serial.print("STA IP address: "); + // Serial.println(WiFi.localIP()); + + // Start OTA server + ArduinoOTA.setHostname(hostname.c_str()); // open http://esp32-XX.local + ArduinoOTA.setPassword(passphrase.c_str()); + + ArduinoOTA + .onStart([]() + { + loading = true; + // Serial.println("Start updating "); + neopixelWrite(PIN_NEOPIXEL, 255, 255, 255); }) + .onEnd([]() + { + loading = false; + // Serial.println("\nEnd"); + }); + // .onProgress([](unsigned int progress, unsigned int total) + // { + // // Serial.printf("Progress: %u%%\r", (progress / (total / 100))); + // }) + // .onError([](ota_error_t error) + // { + // Serial.printf("Error[%u]: ", error); + // // if (error == OTA_AUTH_ERROR) + // // { + // // Serial.println("Auth Failed"); + // // } + // // else if (error == OTA_BEGIN_ERROR) + // // { + // // Serial.println("Begin Failed"); + // // } + // // else if (error == OTA_CONNECT_ERROR) + // // { + // // Serial.println("Connect Failed"); + // // } + // // else if (error == OTA_RECEIVE_ERROR) + // // { + // // Serial.println("Receive Failed"); + // // } + // // else if (error == OTA_END_ERROR) + // // { + // // Serial.println("End Failed"); + // // } + // }); + + ArduinoOTA.begin(); + + return true; +} + +void OTA::begin(const String &password, const char *station_ssid, const char *station_psk) +{ + if (!startSTA(station_ssid, station_psk, password)) + { + startAP(password); + } +} + +void OTA::handle() +{ + ArduinoOTA.handle(); +} + +bool OTA::isLoading() +{ + return loading; +} diff --git a/lib/OTA/OTA.h b/lib/OTA/OTA.h new file mode 100644 index 0000000..ea2fcdf --- /dev/null +++ b/lib/OTA/OTA.h @@ -0,0 +1,19 @@ +#ifndef OTA_H +#define OTA_H + +class OTA +{ +public: + OTA(); + virtual ~OTA(){}; + void begin(const String &password, const char *station_ssid = "", const char *station_passphrase = ""); + void handle(); + bool isLoading(); + +private: + void startAP(const String &passphrase); + boolean startSTA(const char *station_ssid, const char *station_passphrase, const String &password); + String getHostname(); +}; + +#endif \ No newline at end of file diff --git a/platformio.ini b/platformio.ini index bc7f086..558231d 100644 --- a/platformio.ini +++ b/platformio.ini @@ -1,203 +1,94 @@ -; https://docs.platformio.org/en/latest/platforms/espressif32.html +; PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html [platformio] boards_dir = ./boards +extra_configs = upload_params.ini +; examples +; src_dir = ./examples/serial +; src_dir = ./examples/mac +; src_dir = ./examples/rgb +; src_dir = ./examples/wifi-ap +; src_dir = ./examples/ota +; src_dir = ./examples/ota-telnet +; src_dir = ./examples/ota-webserver +; src_dir = ./examples/ota-manager-rtos [env] -build_flags = - ; to use e.g. as part of the firmware name - '-DPIOENV="${PIOENV}"' - - ; coding_standards - -Wno-unused-variable - -Wno-unused-but-set-variable - -Wunreachable-code - - ; debug level 5=VERBOSE https://docs.platformio.org/en/latest/platforms/espressif32.html#debug-level - ; -DCORE_DEBUG_LEVEL=5 +build_flags = + '-DPIOENV="${PIOENV}"' + '-DSERIAL_DEBUG' + -DCORE_DEBUG_LEVEL=5 + -Wno-unused-variable + -Wno-unused-but-set-variable + -Wunreachable-code extra_scripts = pre:extra_script.py framework = arduino -lib_deps = - ; place global libs here or under extra.lib_deps_external (see below) +lib_deps = monitor_speed = 115200 +; uncomment when using multiple ESPs +; monitor_port = /dev/cu.usbmodem5 platform = espressif32 upload_speed = 921600 -; CUSTOM options -; You need manually inject these options into a section -; using ${extra.} (see below) [extra] -; https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/external-ram.html build_flags_psram = - -DBOARD_HAS_PSRAM - -mfix-esp32-psram-cache-issue ; https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/external-ram.html#esp32-rev-v1 lib_deps_builtin = - SPI - Wire + SPI + Wire lib_deps_external = - ; extend libs for all platforms here + lennarthennigs/ESP Telnet @ ^2.2.1 [esp32] -build_flags = - ${env.build_flags} -lib_deps = - ${env.lib_deps} - ${extra.lib_deps_builtin} - ${extra.lib_deps_external} - ; extend libs only for esp32 based modules here +build_flags = + ${env.build_flags} +lib_deps = + ${env.lib_deps} + ${extra.lib_deps_builtin} + ${extra.lib_deps_external} [esp32c6] -build_flags = - ${env.build_flags} +build_flags = + ${env.build_flags} lib_deps = - ${env.lib_deps} - ${extra.lib_deps_builtin} - ${extra.lib_deps_external} - ; extend libs only for esp32c6 based modules here + ${env.lib_deps} + ${extra.lib_deps_builtin} + ${extra.lib_deps_external} platform = https://github.com/platformio/platform-espressif32.git -platform_packages = - platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git - platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 - -[esp32s2] -build_flags = - ${env.build_flags} -lib_deps = - ${env.lib_deps} - ${extra.lib_deps_builtin} - ${extra.lib_deps_external} - ; extend libs only for esp32s2 based modules here - -[esp32s3] -build_flags = - ${env.build_flags} -lib_deps = - ${env.lib_deps} - ${extra.lib_deps_builtin} - ${extra.lib_deps_external} - ; extend libs only for esp32s3 based modules here - +platform_packages = + platformio/framework-arduinoespressif32 @ https://github.com/espressif/arduino-esp32.git + platformio/framework-arduinoespressif32-libs @ https://github.com/espressif/esp32-arduino-libs.git#idf-release/v5.1 -; ********* -; * ESP32 * -; ********* - -; pio board config: https://docs.platformio.org/en/latest/platforms/espressif32.html -[env:esp32dev] -extends = esp32 -board = esp32dev -build_flags = - ${esp32.build_flags} -lib_deps = - ${esp32.lib_deps} - -; pio board config: https://docs.platformio.org/en/latest/boards/espressif32/lolin32.html -[env:lolin32] -extends = esp32 -board = lolin32 -build_flags = - ${esp32.build_flags} -lib_deps = - ${esp32.lib_deps} - -; Wemos https://www.wemos.cc/en/latest/d32/d32_pro.html -; pio board config: https://docs.platformio.org/en/latest/boards/espressif32/lolin_d32_pro.html -[env:lolin-d32-pro] -extends = esp32 -board = lolin_d32_pro -build_flags = - ${esp32.build_flags} - ${extra.build_flags_psram} ; 4MB PSRAM -lib_deps = - ${esp32.lib_deps} - -; LILYGO https://www.lilygo.cc/products/t-beam-v1-1-esp32-lora-module -[env:ttgo-t-beam] -extends = esp32 -board = ttgo-t-beam -build_flags = - ${esp32.build_flags} - ${extra.build_flags_psram} ; 8MB PSRAM -lib_deps = - ${esp32.lib_deps} - -; ************ -; * ESP32-C6 * -; ************ -; devkitc-1: https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html -; devkitm-1: https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitm-1/index.html +[esp32c6-ota] +upload_speed = 2000000 +upload_protocol = espota +; change upload_port after connected to your network instead of the ESP AP +; upload_port = 192.168.4.1 +upload_port = 192.168.50.105 [env:esp32-c6-n16] extends = esp32c6 board = esp32-c6-n16 +[env:esp32-c6-n16-ota] +extends = env:esp32-c6-n16 +upload_speed = ${esp32c6-ota.upload_speed} +upload_protocol = ${esp32c6-ota.upload_protocol} +upload_port = ${esp32c6-ota.upload_port} + [env:esp32-c6-n4] extends = esp32c6 board = esp32-c6-n4 -; ************ -; * ESP32-S2 * -; ************ - -; TODO http://www.lilygo.cn/prod_view.aspx?TypeId=50033&Id=1321 with psram -; repository: https://github.com/Xinyuan-LilyGO/LilyGo-T-Display-S2 -[env:lilygo-t-display-s2] -extends = esp32s2 -board = esp32dev ; what about platformio board support and an own? - -; ************ -; * ESP32-S3 * -; ************ - -; pio board config: https://docs.platformio.org/en/latest/boards/espressif32/esp32s3box.html -[env:esp32s3box] -extends = esp32s3 -board = esp32s3box -build_flags = - ${esp32s3.build_flags} -lib_deps = - ${esp32s3.lib_deps} - -; pio board config: https://docs.platformio.org/en/latest/boards/espressif32/esp32-s3-devkitc-1.html -[env:esp32-s3-devkitc-1] -extends = esp32s3 -board = esp32-s3-devkitc-1 -build_flags = - ${esp32s3.build_flags} - ; PSRAM is optional -lib_deps = - ${esp32s3.lib_deps} - -; LILYGO: https://www.lilygo.cc/products/t-display-s3 -; repository: https://github.com/Xinyuan-LilyGO/T-Display-S3 -; pio board config: https://docs.platformio.org/en/latest/boards/espressif32/lilygo-t-display-s3.html -; Buy and support mcuw (affiliate link): https://s.click.aliexpress.com/e/_DE2TNqz -[env:lilygo-t-display-s3] -board = lilygo-t-display-s3 -build_flags = - ${esp32s3.build_flags} - ${extra.build_flags_psram} ; 8MB PSRAM -lib_deps = - ${esp32s3.lib_deps} - -; LILYGO: https://www.lilygo.cc/products/t-display-s3-long -; repository: https://github.com/Xinyuan-LilyGO/T-Display-S3-Long -; Buy and support mcuw on aliexpress (affiliate link): https://s.click.aliexpress.com/e/_DEv67TX -[env:lilygo-t-display-s3-long] -board = lilygo-t-display-s3-long -board_build.partitions = huge_app.csv -build_flags = - ${esp32s3.build_flags} - ${extra.build_flags_psram} ; 8MB PSRAM -lib_deps = - ${esp32s3.lib_deps} - -; SeeedStudio: https://www.seeedstudio.com/WT32-3-5-Inch-Display-p-5542.html -; Antratek: https://www.antratek.com/wt32-sco1-plus -; repository: https://github.com/wireless-tag-com/lv_port_esp32 -; ESP32-TUX - github: https://github.com/sukesh-ak/ESP32-TUX -[env:wt32-sc01-plus] -extends = env:esp32-s3-devkitc-1 -build_flags = - ${env:esp32-s3-devkitc-1.build_flags} - ${extra.build_flags_psram} ; 2MB PSRAM +[env:esp32-c6-n4-ota] +extends = env:esp32-c6-n4 +upload_speed = ${esp32c6-ota.upload_speed} +upload_protocol = ${esp32c6-ota.upload_protocol} +upload_port = ${esp32c6-ota.upload_port} diff --git a/src/main.cpp b/src/main.cpp index e73b4d2..114a368 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,12 +1,31 @@ #include +#include +#include -void setup() { - Serial.begin(115200); - while (!Serial); - +// pinouts: https://github.com/espressif/arduino-esp32/blob/master/variants/esp32c6/pins_arduino.h + +// see https://github.com/wuxx/nanoESP32-C6 + +void initDevBoard(uint8_t redValue = 0, uint8_t greenValue = 0, uint8_t blueValue = 0) +{ + neopixelWrite(PIN_NEOPIXEL, redValue, greenValue, blueValue); // default off RGB-LED if (0, 0, 0) + + // The ESP32-C6 has an attenuator on the ADC, which defaults to 11dB. This causes the resolution to be reduced + analogSetAttenuation(ADC_0db); } -void loop() { - Serial.println("Hello World"); - delay(2000); +void setup() +{ + serialBegin(115200); +} + +void loop() +{ + // reset RGB-LED, ... + initDevBoard(0, 0, 0); + + // // blink + // serialPrintln("green"); + // neopixelWrite(PIN_NEOPIXEL, 0, 255, 0); + // delay(1000); } \ No newline at end of file diff --git a/upload_params_example.ini b/upload_params_example.ini new file mode 100644 index 0000000..f39666d --- /dev/null +++ b/upload_params_example.ini @@ -0,0 +1,8 @@ +[env:esp32-c6-n16-ota] +upload_flags = + ; replace 12345678 with yours the same as AP_PSK in cred.h + --auth=12345678 + +[env:esp32-c6-n16-ota] +upload_flags = + --auth=12345678