diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..cca0272 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,27 @@ +# documentation at https://docs.platformio.org/en/latest/integration/ci/github-actions.html + +name: PlatformIO CI + +on: [push, pull_request] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + - uses: actions/cache@v3 + with: + path: | + ~/.cache/pip + ~/.platformio/.cache + key: ${{ runner.os }}-pio + - uses: actions/setup-python@v4 + with: + python-version: '3.9' + - name: Install PlatformIO Core + run: pip install --upgrade platformio + + - name: Build PlatformIO Project + run: pio run \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..4de822f --- /dev/null +++ b/.gitignore @@ -0,0 +1,6 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch +.DS_Store diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..080e70d --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ], + "unwantedRecommendations": [ + "ms-vscode.cpptools-extension-pack" + ] +} diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..06801d3 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,7 @@ +{ + "files.associations": { + "functional": "cpp", + "tuple": "cpp", + "*._h": "cpp" + } +} \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..a9a3f42 --- /dev/null +++ b/README.md @@ -0,0 +1,62 @@ +ThingPulse ePulse Feather C6 +================= + + +Sample projects for [ThingPulse ePulse Feather C6](https://thingpulse.com/products/epulse-feather-c6/) + ![ePulse C6](assets/img/epulse-c6.jpeg) + +# Sample Projects + +To build and run these sample projects follow these steps: + 1. Install VS Code and install [Platformio](https://platformio.org/install/ide?install=vscode) + 2. Checkout this repository and open it in VS Code + 3. Select the sample project by clicking on env section in the footer: + ![Environment Selector](assets/img/project.png) + 4. Build and flash the sample by clicking on the right arrow in VS Code footer: + ![Build & Flash](assets/img/build-flash.png) + 5. Turn on serial monitor by clicking on the plug symbol: + ![Monitor](assets/img/monitor.png) + +## Fuel Gauge Simple + +This example shows how to use the MAX17048 fuel gauge chip. + +1. Preparation: connect a LiPo battery to the ePulse Feather C6. Make sure polarity of the battery +is correct- +2. Select `env:fuel-gauge-simple` to run this example. The `ESP32-C6` connects to the `MAX17048` chip +and reads battery voltage, state of charge (SoC) and change rate + +### Links +* [MAX 17048 DataSheet](https://www.analog.com/media/en/technical-documentation/data-sheets/max17048-max17049.pdf) + +## Fuel Gauge WiFi + +This example shows how to use the MAX17048 fuel gauge chip. In addition to the previous example this code sends +the battery voltage and the SoC to the given HTTP server. We used a node-red instance with http node to receive +the values + +1. Preparation: connect a LiPo battery to the ePulse Feather C6. Make sure polarity of the battery +is correct- +2. Select `env:fuel-gauge-wifi` to run this example. The `ESP32-C6` connects to the `MAX17048` chip +and reads battery voltage, state of charge (SoC) and change rate +3. Adjust WiFi ssid and password in `main-fuel-gauge-wifi.cpp` +4. Adjust host and port in the same file +5. Setup http server to receive GET requests + +Here is an example flow of node red. It receives requests under /epulsec6, converts them and sends the message to influx: + ![Monitor](assets/img/node-red.png?) + +Content of the `convert message` node + ```js +let payload = {}; + +payload.vBat = Number(msg.req.query.voltage); +payload.soc = Number(msg.req.query.soc); + +let values = payload; +let tags = {}; +tags.name = "epulse feather c6"; +msg.payload = [values, tags]; +return msg; +``` + diff --git a/assets/img/build-flash.png b/assets/img/build-flash.png new file mode 100644 index 0000000..a361811 Binary files /dev/null and b/assets/img/build-flash.png differ diff --git a/assets/img/epulse-c6.jpeg b/assets/img/epulse-c6.jpeg new file mode 100644 index 0000000..6ddeb05 Binary files /dev/null and b/assets/img/epulse-c6.jpeg differ diff --git a/assets/img/monitor.png b/assets/img/monitor.png new file mode 100644 index 0000000..b4bb5c2 Binary files /dev/null and b/assets/img/monitor.png differ diff --git a/assets/img/node-red.png b/assets/img/node-red.png new file mode 100644 index 0000000..5fc4228 Binary files /dev/null and b/assets/img/node-red.png differ diff --git a/assets/img/project.png b/assets/img/project.png new file mode 100644 index 0000000..aa4e541 Binary files /dev/null and b/assets/img/project.png differ diff --git a/include/README b/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..6debab1 --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..23631a1 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,42 @@ +; 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] +;default_envs = deepsleep +default_envs = fuel-gauge-simple +;default_envs = battery-monitor +;default_envs = awake-consumption +;default_envs = charge-pin + + + +[env] +platform = https://github.com/Jason2866/platform-espressif32.git#Arduino/IDF5 + +framework = arduino +board = esp32-c6-devkitc-1 + +monitor_speed = 115200 +upload_speed = 921600 +monitor_filters = esp32_exception_decoder, time +board_build.partitions = no_ota.csv +build_src_filter = +<*.h> + +build_flags = -DCORE_DEBUG_LEVEL=5 + -DARDUINO_USB_CDC_ON_BOOT=1 + -DARDUINO_USB_MODE=1 + +[env:fuel-gauge-simple] +lib_deps = sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library@^1.0.4 + +[env:fuel-gauge-wifi] +lib_deps = sparkfun/SparkFun MAX1704x Fuel Gauge Arduino Library@^1.0.4 + + + + diff --git a/src/main-fuel-gauge-simple.cpp b/src/main-fuel-gauge-simple.cpp new file mode 100644 index 0000000..ea7cdd2 --- /dev/null +++ b/src/main-fuel-gauge-simple.cpp @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: 2024 ThingPulse Ltd., https://thingpulse.com +// SPDX-License-Identifier: MIT + +#include +#include // Needed for I2C +#include +#include "settings.h" + +SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048 + + +double voltage = 0; // Variable to keep track of LiPo voltage +double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC) +bool alert; // Variable to keep track of whether alert has been triggered + +void setup() +{ + Serial.begin(115200); // Start serial, to output debug data + while (!Serial) + ; //Wait for user to open terminal + Serial.println(F("MAX17043 Example")); + + Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL); + + lipo.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // Set up the MAX17043 LiPo fuel gauge: + if (lipo.begin() == false) // Connect to the MAX17043 using the default wire port + { + Serial.println(F("MAX17043 not detected. Please check wiring. Freezing.")); + while (1) + ; + } + + // Quick start restarts the MAX17043 in hopes of getting a more accurate + // guess for the SOC. + lipo.quickStart(); + + // We can set an interrupt to alert when the battery SoC gets too low. + // We can alert at anywhere between 1% - 32%: + lipo.setThreshold(20); // Set alert threshold to 20%. +} + +void loop() +{ + // lipo.getVoltage() returns a voltage value (e.g. 3.93) + voltage = lipo.getVoltage(); + // lipo.getSOC() returns the estimated state of charge (e.g. 79%) + soc = lipo.getSOC(); + // lipo.getAlert() returns a 0 or 1 (0=alert not triggered) + alert = lipo.getAlert(); + + + + // Print the variables: + Serial.print("Voltage: "); + Serial.print(voltage); // Print the battery voltage + Serial.println(" V"); + + Serial.print("Percentage: "); + Serial.print(soc); // Print the battery state of charge + Serial.println(" %"); + + Serial.print("Change Rate: "); + Serial.print(lipo.getChangeRate()); // Print the battery state of charge + Serial.println(" %/h"); + + Serial.print("Alert: "); + Serial.println(alert); + Serial.println(); + + delay(1000); +} \ No newline at end of file diff --git a/src/main-fuel-gauge-wifi.cpp b/src/main-fuel-gauge-wifi.cpp new file mode 100644 index 0000000..1d622a5 --- /dev/null +++ b/src/main-fuel-gauge-wifi.cpp @@ -0,0 +1,124 @@ +/* +MIT License + +Copyright (c) 2024 Daniel Eichhorn, ThingPulse + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + +Description: +This example reads the battery voltage and state of charge (SoC) from a MAX17048 LiPo fuel gauge and sends it to a HTTP server as GET request. +The server can be a Node-RED instance, for example, which can then process the data further. +*/ + +#include +#include +#include // Needed for I2C +#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library + +#include "settings.h" + + +const char* ssid = "yourssid"; // Change this to your WiFi SSID +const char* password = "yourpassw0rd"; // Change this to your WiFi password + +const char* host = "192.168.0.100"; // HTTP Server receiving GET request with data, e.g. Node-RED +const int httpPort = 1880; // Port of HTTP Server + +SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048 + + +void setup() +{ + Serial.begin(115200); + while(!Serial){delay(100);} + + // We start by connecting to a WiFi network + + Serial.println(); + Serial.println("******************************************************"); + Serial.print("Connecting to "); + Serial.println(ssid); + + WiFi.begin(ssid, password); + + while (WiFi.status() != WL_CONNECTED) { + delay(500); + Serial.print("."); + } + + Serial.println(""); + Serial.println("WiFi connected"); + Serial.println("IP address: "); + Serial.println(WiFi.localIP()); + + Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL); + + lipo.enableDebugging(); // Uncomment this line to enable helpful debug messages on Serial + + // Set up the MAX17043 LiPo fuel gauge: + if (lipo.begin() == false) // Connect to the MAX17043 using the default wire port + { + Serial.println(F("MAX17043 not detected. Please check wiring. Freezing.")); + while (1) + ; + } + + // Quick start restarts the MAX17043 in hopes of getting a more accurate + // guess for the SOC. + lipo.quickStart(); + + // We can set an interrupt to alert when the battery SoC gets too low. + // We can alert at anywhere between 1% - 32%: + lipo.setThreshold(20); // Set alert threshold to 20%. +} + +void readResponse(WiFiClient *client){ + unsigned long timeout = millis(); + while(client->available() == 0){ + if(millis() - timeout > 5000){ + Serial.println(">>> Client Timeout !"); + client->stop(); + return; + } + } + + // Read all the lines of the reply from server and print them to Serial + while(client->available()) { + String line = client->readStringUntil('\r'); + Serial.print(line); + } + + Serial.printf("\nClosing connection\n\n"); +} + +void loop(){ + WiFiClient client; + String footer = String(" HTTP/1.1\r\n") + "Host: " + String(host) + "\r\n" + "Connection: close\r\n\r\n"; + + // WRITE -------------------------------------------------------------------------------------------- + if (!client.connect(host, httpPort)) { + return; + } + + float voltage = lipo.getVoltage(); + float soc = lipo.getSOC(); + + client.print("GET /epulsec6?voltage=" + String(voltage, 2) + "&soc=" + String(soc, 2) + footer); + readResponse(&client); +} diff --git a/src/main-zigbee-bulb.cpp b/src/main-zigbee-bulb.cpp new file mode 100644 index 0000000..0bd7e10 --- /dev/null +++ b/src/main-zigbee-bulb.cpp @@ -0,0 +1,191 @@ +// Copyright 2023 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +/** + * @brief This example demonstrates simple Zigbee light bulb. + * + * The example demonstrates how to use ESP Zigbee stack to create a end device light bulb. + * The light bulb is a Zigbee end device, which is controlled by a Zigbee coordinator. + * + * Proper Zigbee mode must be selected in Tools->Zigbee mode + * and also the correct partition scheme must be selected in Tools->Partition Scheme. + * + * Please check the README.md for instructions and more detailed description. + */ + +#ifndef ZIGBEE_MODE_ED +#error "Zigbee end device mode is not selected in Tools->Zigbee mode" +#endif + +#include "esp_zigbee_core.h" +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" +#include "ha/esp_zigbee_ha_standard.h" + +#define LED_PIN RGB_BUILTIN + +/* Default End Device config */ +#define ESP_ZB_ZED_CONFIG() \ + { \ + .esp_zb_role = ESP_ZB_DEVICE_TYPE_ED, \ + .install_code_policy = INSTALLCODE_POLICY_ENABLE, \ + .nwk_cfg = { \ + .zed_cfg = { \ + .ed_timeout = ED_AGING_TIMEOUT, \ + .keep_alive = ED_KEEP_ALIVE, \ + }, \ + }, \ + } + +#define ESP_ZB_DEFAULT_RADIO_CONFIG() \ + { \ + .radio_mode = RADIO_MODE_NATIVE, \ + } + +#define ESP_ZB_DEFAULT_HOST_CONFIG() \ + { \ + .host_connection_mode = HOST_CONNECTION_MODE_NONE, \ + } + +/* Zigbee configuration */ +#define INSTALLCODE_POLICY_ENABLE false /* enable the install code policy for security */ +#define ED_AGING_TIMEOUT ESP_ZB_ED_AGING_TIMEOUT_64MIN +#define ED_KEEP_ALIVE 3000 /* 3000 millisecond */ +#define HA_ESP_LIGHT_ENDPOINT 10 /* esp light bulb device endpoint, used to process light controlling commands */ +#define ESP_ZB_PRIMARY_CHANNEL_MASK ESP_ZB_TRANSCEIVER_ALL_CHANNELS_MASK /* Zigbee primary channel mask use in the example */ + +/********************* Zigbee functions **************************/ +static void bdb_start_top_level_commissioning_cb(uint8_t mode_mask) +{ + ESP_ERROR_CHECK(esp_zb_bdb_start_top_level_commissioning(mode_mask)); +} + +void esp_zb_app_signal_handler(esp_zb_app_signal_t *signal_struct) +{ + uint32_t *p_sg_p = signal_struct->p_app_signal; + esp_err_t err_status = signal_struct->esp_err_status; + esp_zb_app_signal_type_t sig_type = (esp_zb_app_signal_type_t)*p_sg_p; + switch (sig_type) { + case ESP_ZB_ZDO_SIGNAL_SKIP_STARTUP: + log_i("Zigbee stack initialized"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_INITIALIZATION); + break; + case ESP_ZB_BDB_SIGNAL_DEVICE_FIRST_START: + case ESP_ZB_BDB_SIGNAL_DEVICE_REBOOT: + if (err_status == ESP_OK) { + log_i("Start network steering"); + esp_zb_bdb_start_top_level_commissioning(ESP_ZB_BDB_MODE_NETWORK_STEERING); + } else { + /* commissioning failed */ + log_w("Failed to initialize Zigbee stack (status: %s)", esp_err_to_name(err_status)); + } + break; + case ESP_ZB_BDB_SIGNAL_STEERING: + if (err_status == ESP_OK) { + esp_zb_ieee_addr_t extended_pan_id; + esp_zb_get_extended_pan_id(extended_pan_id); + log_i("Joined network successfully (Extended PAN ID: %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x, PAN ID: 0x%04hx, Channel:%d, Short Address: 0x%04hx)", + extended_pan_id[7], extended_pan_id[6], extended_pan_id[5], extended_pan_id[4], + extended_pan_id[3], extended_pan_id[2], extended_pan_id[1], extended_pan_id[0], + esp_zb_get_pan_id(), esp_zb_get_current_channel(), esp_zb_get_short_address()); + } else { + log_i("Network steering was not successful (status: %s)", esp_err_to_name(err_status)); + esp_zb_scheduler_alarm((esp_zb_callback_t)bdb_start_top_level_commissioning_cb, ESP_ZB_BDB_MODE_NETWORK_STEERING, 1000); + } + break; + default: + log_i("ZDO signal: %s (0x%x), status: %s", esp_zb_zdo_signal_to_string(sig_type), sig_type, + esp_err_to_name(err_status)); + break; + } +} + +static esp_err_t zb_action_handler(esp_zb_core_action_callback_id_t callback_id, const void *message) +{ + esp_err_t ret = ESP_OK; + switch (callback_id) { + case ESP_ZB_CORE_SET_ATTR_VALUE_CB_ID: + ret = zb_attribute_handler((esp_zb_zcl_set_attr_value_message_t *)message); + break; + default: + log_w("Receive Zigbee action(0x%x) callback", callback_id); + break; + } + return ret; +} + +static void esp_zb_task(void *pvParameters) +{ + esp_zb_cfg_t zb_nwk_cfg = ESP_ZB_ZED_CONFIG(); + esp_zb_init(&zb_nwk_cfg); + esp_zb_on_off_light_cfg_t light_cfg = ESP_ZB_DEFAULT_ON_OFF_LIGHT_CONFIG(); + esp_zb_ep_list_t *esp_zb_on_off_light_ep = esp_zb_on_off_light_ep_create(HA_ESP_LIGHT_ENDPOINT, &light_cfg); + esp_zb_device_register(esp_zb_on_off_light_ep); + esp_zb_core_action_handler_register(zb_action_handler); + esp_zb_set_primary_network_channel_set(ESP_ZB_PRIMARY_CHANNEL_MASK); + + //Erase NVRAM before creating connection to new Coordinator + //esp_zb_nvram_erase_at_start(true); //Comment out this line to erase NVRAM data if you are conneting to new Coordinator + + ESP_ERROR_CHECK(esp_zb_start(false)); + esp_zb_main_loop_iteration(); +} + +/* Handle the light attribute */ + +static esp_err_t zb_attribute_handler(const esp_zb_zcl_set_attr_value_message_t *message) +{ + esp_err_t ret = ESP_OK; + bool light_state = 0; + + if(!message){ + log_e("Empty message"); + } + if(message->info.status != ESP_ZB_ZCL_STATUS_SUCCESS){ + log_e("Received message: error status(%d)", message->info.status); + } + + log_i("Received message: endpoint(%d), cluster(0x%x), attribute(0x%x), data size(%d)", message->info.dst_endpoint, message->info.cluster, + message->attribute.id, message->attribute.data.size); + if (message->info.dst_endpoint == HA_ESP_LIGHT_ENDPOINT) { + if (message->info.cluster == ESP_ZB_ZCL_CLUSTER_ID_ON_OFF) { + if (message->attribute.id == ESP_ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID && message->attribute.data.type == ESP_ZB_ZCL_ATTR_TYPE_BOOL) { + light_state = message->attribute.data.value ? *(bool *)message->attribute.data.value : light_state; + log_i("Light sets to %s", light_state ? "On" : "Off"); + neopixelWrite(LED_PIN,255*light_state,255*light_state,255*light_state); // Toggle light + } + } + } + return ret; +} + +/********************* Arduino functions **************************/ +void setup() { + // Init Zigbee + esp_zb_platform_config_t config = { + .radio_config = ESP_ZB_DEFAULT_RADIO_CONFIG(), + .host_config = ESP_ZB_DEFAULT_HOST_CONFIG(), + }; + ESP_ERROR_CHECK(esp_zb_platform_config(&config)); + + // Init RMT and leave light OFF + neopixelWrite(LED_PIN,0,0,0); + + // Start Zigbee task + xTaskCreate(esp_zb_task, "Zigbee_main", 4096, NULL, 5, NULL); +} + +void loop() { + //empty, zigbee running in task +} \ No newline at end of file diff --git a/src/settings.h b/src/settings.h new file mode 100644 index 0000000..ff50ed3 --- /dev/null +++ b/src/settings.h @@ -0,0 +1,12 @@ +#pragma once + +#include + +#define MATH_MIN(a,b) ((a)<(b)?(a):(b)) +#define MATH_MAX(a,b) ((a)>(b)?(a):(b)) + +#define PIN_I2C_SDA 2 +#define PIN_I2C_SCL 3 + +#define DEEP_SLEEP_MICROS 5 * 1000 * 1000 + diff --git a/test/README b/test/README new file mode 100644 index 0000000..b94d089 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PlatformIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PlatformIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html