ESP32-C3 and ESP32-S2, LED for C3-Mini

This commit is contained in:
MichaelDvP
2022-10-10 14:13:43 +02:00
parent b6d8e55b00
commit 6fd3e567cd
28 changed files with 4891 additions and 116 deletions

View File

@@ -129,10 +129,14 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::COUNTER) {
LOG_DEBUG("Adding analog I/O Counter sensor on GPIO%d", sensor.gpio());
pinMode(sensor.gpio(), INPUT_PULLUP);
#ifndef ARDUINO_LOLIN_C3_MINI
#if CONFIG_IDF_TARGET_ESP32
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
dacWrite(sensor.gpio(), 255);
}
#elif CONFIG_IDF_TARGET_ESP32S2
if (sensor.gpio() == 23 || sensor.gpio() == 24) {
dacWrite(sensor.gpio(), 255);
}
#endif
sensor.polltime_ = 0;
sensor.poll_ = digitalRead(sensor.gpio());
@@ -157,17 +161,28 @@ void AnalogSensor::reload() {
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
LOG_DEBUG("Adding analog Write sensor on GPIO%d", sensor.gpio());
pinMode(sensor.gpio(), OUTPUT);
#if CONFIG_IDF_TARGET_ESP32
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
if (sensor.offset() > 255) {
sensor.set_offset(255);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
#ifndef ARDUINO_LOLIN_C3_MINI
dacWrite(sensor.gpio(), sensor.offset());
#endif
sensor.set_value(sensor.offset());
} else {
} else
#elif CONFIG_IDF_TARGET_ESP32S2
if (sensor.gpio() == 23 || sensor.gpio() == 24) {
if (sensor.offset() > 255) {
sensor.set_offset(255);
} else if (sensor.offset() < 0) {
sensor.set_offset(0);
}
dacWrite(sensor.gpio(), sensor.offset());
sensor.set_value(sensor.offset());
} else
#endif
{
digitalWrite(sensor.gpio(), sensor.offset() > 0 ? 1 : 0);
sensor.set_value(digitalRead(sensor.gpio()));
}
@@ -337,9 +352,9 @@ void AnalogSensor::publish_sensor(const Sensor & sensor) const {
if (Mqtt::publish_single()) {
char topic[Mqtt::MQTT_TOPIC_MAX_SIZE];
if (Mqtt::publish_single2cmd()) {
snprintf(topic, sizeof(topic), "%s/%s", (F_(analogsensor)), sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s/%s", F_(analogsensor), sensor.name().c_str());
} else {
snprintf(topic, sizeof(topic), "%s%s/%s", (F_(analogsensor)), "_data", sensor.name().c_str());
snprintf(topic, sizeof(topic), "%s%s/%s", F_(analogsensor), "_data", sensor.name().c_str());
}
char payload[10];
Mqtt::publish(topic, Helpers::render_value(payload, sensor.value(), 2)); // always publish as floats
@@ -575,16 +590,26 @@ bool AnalogSensor::command_setvalue(const char * value, const int8_t gpio) {
return true;
} else if (sensor.type() == AnalogType::DIGITAL_OUT) {
uint8_t v = val;
if (sensor.gpio() == 25 || sensor.gpio() == 26) {
#if CONFIG_IDF_TARGET_ESP32
if ((sensor.gpio() == 25 || sensor.gpio() == 26) && v <= 255) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);
#ifndef ARDUINO_LOLIN_C3_MINI
dacWrite(sensor.gpio(), sensor.offset());
#endif
publish_sensor(sensor);
return true;
} else if (v == 0 || v == 1) {
} else
#elif CONFIG_IDF_TARGET_ESP32S2
if ((sensor.gpio() == 23 || sensor.gpio() == 24) && v <= 255) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);
dacWrite(sensor.gpio(), sensor.offset());
publish_sensor(sensor);
return true;
} else
#endif
if (v == 0 || v == 1) {
sensor.set_offset(v);
sensor.set_value(v);
pinMode(sensor.gpio(), OUTPUT);

View File

@@ -38,6 +38,10 @@
#include "../rom/rtc.h"
#endif
#endif
#ifdef ARDUINO_LOLIN_C3_MINI
#include <Adafruit_NeoPixel.h>
Adafruit_NeoPixel pixels(1, 7, NEO_GRB + NEO_KHZ800);
#endif
namespace emsesp {
@@ -348,27 +352,24 @@ void System::wifi_tweak() {
#endif
}
#ifdef ARDUINO_LOLIN_C3_MINI
// https://www.wemos.cc/en/latest/c3/c3_mini.html
bool System::is_valid_gpio(uint8_t pin) {
if ((pin >= 11 && pin <= 19) || (pin > 21)) {
return false; // bad pin
}
return true;
}
#else
// check for valid ESP32 pins. This is very dependent on which ESP32 board is being used.
// Typically you can't use 1, 6-11, 12, 14, 15, 20, 24, 28-31 and 40+
// we allow 0 as it has a special function on the NodeMCU apparently
// See https://diyprojects.io/esp32-how-to-use-gpio-digital-io-arduino-code/#.YFpVEq9KhjG
// and https://nodemcu.readthedocs.io/en/dev-esp32/modules/gpio/
bool System::is_valid_gpio(uint8_t pin) {
#if CONFIG_IDF_TARGET_ESP32
if ((pin == 1) || (pin >= 6 && pin <= 12) || (pin >= 14 && pin <= 15) || (pin == 20) || (pin == 24) || (pin >= 28 && pin <= 31) || (pin > 40)) {
#elif CONFIG_IDF_TARGET_ESP32S2
if ((pin >= 19 && pin <= 20) || (pin >= 22 && pin <= 32) || (pin > 40)) {
#elif CONFIG_IDF_TARGET_ESP32C3
// https://www.wemos.cc/en/latest/c3/c3_mini.html
if ((pin >= 11 && pin <= 19) || (pin > 21)) {
#endif
return false; // bad pin
}
return true;
}
#endif
// Starts up the UART Serial bridge
void System::start() {
@@ -379,6 +380,7 @@ void System::start() {
setCpuFrequencyMhz(160);
}
fstotal_ = LittleFS.totalBytes() / 1024; // read only once, it takes 500 ms to read
psram_ = ESP.getPsramSize() / 1024;
appused_ = ESP.getSketchSize() / 1024;
appfree_ = ESP.getFreeSketchSpace() / 1024 - appused_;
#endif
@@ -457,8 +459,18 @@ void System::led_init(bool refresh) {
}
if ((led_gpio_ != 0) && is_valid_gpio(led_gpio_)) {
#ifdef ARDUINO_LOLIN_C3_MINI
// rgb LED WS2812B, use Adafruit Neopixel
// Adafruit_NeoPixel pixels(1, 7, NEO_GRB + NEO_KHZ800);
pixels.begin();
pixels.setPin(led_gpio_);
// pixels.setBrightness(0);
pixels.Color(0, 0, 0, 0);
pixels.show();
#else
pinMode(led_gpio_, OUTPUT); // 0 means disabled
digitalWrite(led_gpio_, !LED_ON); // start with LED off
#endif
}
}
@@ -551,8 +563,9 @@ bool System::heartbeat_json(JsonObject & output) {
output["txfails"] = EMSESP::txservice_.telegram_read_fail_count() + EMSESP::txservice_.telegram_write_fail_count();
if (Mqtt::enabled()) {
output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails();
output["mqttcount"] = Mqtt::publish_count();
output["mqttfails"] = Mqtt::publish_fails();
output["mqttconnects"] = Mqtt::connect_count();
}
output["apicalls"] = WebAPIService::api_count(); // + WebAPIService::api_fails();
output["apifails"] = WebAPIService::api_fails();
@@ -687,7 +700,7 @@ void System::commands_init() {
// uses LED to show system health
void System::led_monitor() {
// we only need to run the LED healthcheck if there are errors
if (!healthcheck_) {
if (!healthcheck_ || !led_gpio_) {
return; // all good
}
@@ -715,7 +728,12 @@ void System::led_monitor() {
// Serial.println("resetting flash check");
led_long_timer_ = uuid::get_uptime();
led_flash_step_ = 0;
digitalWrite(led_gpio_, !LED_ON); // LED off
#ifdef ARDUINO_LOLIN_C3_MINI
pixels.setPixelColor(0, 0, 0, 0);
pixels.show();
#else
digitalWrite(led_gpio_, !LED_ON); // LED off
#endif
} else if (led_flash_step_ % 2) {
// handle the step events (on odd numbers 3,5,7,etc). see if we need to turn on a LED
// 1 flash is the EMS bus is not connected
@@ -736,13 +754,23 @@ void System::led_monitor() {
led_on_ = true;
}
if (led_on_ && led_gpio_) {
digitalWrite(led_gpio_, LED_ON);
if (led_on_) {
#ifdef ARDUINO_LOLIN_C3_MINI
pixels.setPixelColor(0, 0, 0, 128);
pixels.show();
#else
digitalWrite(led_gpio_, LED_ON); // LED off
#endif
}
} else {
// turn the led off after the flash, on even number count
if (led_on_ && led_gpio_) {
digitalWrite(led_gpio_, !LED_ON);
if (led_on_) {
#ifdef ARDUINO_LOLIN_C3_MINI
pixels.setPixelColor(0, 0, 0, 0);
pixels.show();
#else
digitalWrite(led_gpio_, !LED_ON); // LED off
#endif
led_on_ = false;
}
}
@@ -811,7 +839,7 @@ void System::show_system(uuid::console::Shell & shell) {
shell.printfln(" Network: connected");
shell.printfln(" SSID: %s", WiFi.SSID().c_str());
shell.printfln(" BSSID: %s", WiFi.BSSIDstr().c_str());
shell.printfln((" RSSI: %d dBm (%d %%)"), WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
shell.printfln(" RSSI: %d dBm (%d %%)", WiFi.RSSI(), wifi_quality(WiFi.RSSI()));
shell.printfln(" MAC address: %s", WiFi.macAddress().c_str());
shell.printfln(" Hostname: %s", WiFi.getHostname());
shell.printfln(" IPv4 address: %s/%s", uuid::printable_to_string(WiFi.localIP()).c_str(), uuid::printable_to_string(WiFi.subnetMask()).c_str());
@@ -965,9 +993,10 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
JsonObject node;
// System
node = output.createNestedObject("System Status");
node["version"] = EMSESP_APP_VERSION;
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
node = output.createNestedObject("System Status");
node["version"] = EMSESP_APP_VERSION;
node["platform"] = EMSESP_PLATFORM;
node["uptime"] = uuid::log::format_timestamp_ms(uuid::get_uptime_ms(), 3);
// node["uptime (seconds)"] = uuid::get_uptime_sec();
#ifndef EMSESP_STANDALONE
node["freemem"] = ESP.getFreeHeap() / 1024; // kilobytes
@@ -979,7 +1008,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
// Network Status
node = output.createNestedObject("Network Status");
if (WiFi.status() == WL_CONNECTED) {
node["connection"] = ("WiFi");
node["connection"] = "WiFi";
node["hostname"] = WiFi.getHostname();
// node["SSID"] = WiFi.SSID();
// node["BSSID"] = WiFi.BSSIDstr();
@@ -992,7 +1021,7 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node["IPv6 address"] = uuid::printable_to_string(WiFi.localIPv6());
}
} else if (EMSESP::system_.ethernet_connected()) {
node["connection"] = ("Ethernet");
node["connection"] = "Ethernet";
node["hostname"] = ETH.getHostname();
node["MAC"] = ETH.macAddress();
node["IPv4 address"] = uuid::printable_to_string(ETH.localIP()) + "/" + uuid::printable_to_string(ETH.subnetMask());
@@ -1048,7 +1077,9 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node["MQTT status"] = Mqtt::connected() ? F_(connected) : F_(disconnected);
if (Mqtt::enabled()) {
node["MQTT publishes"] = Mqtt::publish_count();
node["MQTT queued"] = Mqtt::publish_queued();
node["MQTT publish fails"] = Mqtt::publish_fails();
node["MQTT connects"] = Mqtt::connect_count();
}
EMSESP::esp8266React.getMqttSettingsService()->read([&](MqttSettings & settings) {
node["enabled"] = settings.enabled;
@@ -1106,20 +1137,20 @@ bool System::command_info(const char * value, const int8_t id, JsonObject & outp
node = output.createNestedObject("Bus Status");
switch (EMSESP::bus_status()) {
case EMSESP::BUS_STATUS_OFFLINE:
node["bus status"] = ("disconnected");
node["bus status"] = "disconnected";
break;
case EMSESP::BUS_STATUS_TX_ERRORS:
node["bus status"] = ("connected, tx issues - try a different Tx Mode");
node["bus status"] = "connected, tx issues - try a different Tx Mode";
break;
case EMSESP::BUS_STATUS_CONNECTED:
node["bus status"] = ("connected");
node["bus status"] = "connected";
break;
default:
node["bus status"] = ("unknown");
node["bus status"] = "unknown";
break;
}
if (EMSESP::bus_status() != EMSESP::BUS_STATUS_OFFLINE) {
node["bus protocol"] = EMSbus::is_ht3() ? ("HT3") : ("Buderus");
node["bus protocol"] = EMSbus::is_ht3() ? "HT3" : "Buderus";
node["bus telegrams received (rx)"] = EMSESP::rxservice_.telegram_count();
node["bus reads (tx)"] = EMSESP::txservice_.telegram_read_count();
node["bus writes (tx)"] = EMSESP::txservice_.telegram_write_count();
@@ -1230,7 +1261,9 @@ bool System::load_board_profile(std::vector<int8_t> & data, const std::string &
} else if (board_profile == "OLIMEXPOE") {
data = {0, 0, 36, 4, 34, PHY_type::PHY_TYPE_LAN8720, 12, 0, 3}; // Olimex ESP32-POE
} else if (board_profile == "C3MINI") {
data = {7, 2, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini
data = {7, 1, 4, 5, 9, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; // Lolin C3 Mini
} else if (board_profile == "S2MINI") {
data = {15, 7, 11, 12, 0, PHY_type::PHY_TYPE_NONE, 0, 0, 0}; //Lolin S2 Mini
} else if (board_profile == "CUSTOM") {
// send back current values
data = {(int8_t)EMSESP::system_.led_gpio_,
@@ -1267,6 +1300,9 @@ bool System::command_restart(const char * value, const int8_t id) {
return true;
}
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch"
std::string System::reset_reason(uint8_t cpu) const {
#ifndef EMSESP_STANDALONE
switch (rtc_get_reset_reason(cpu)) {
@@ -1275,11 +1311,11 @@ std::string System::reset_reason(uint8_t cpu) const {
// case 2 :reset pin not on esp32
case 3:
return ("Software reset");
case 4:
case 4: // not on S2, C3
return ("Legacy watch dog reset");
case 5:
return ("Deep sleep reset");
case 6:
case 6: // not on S2, C3
return ("Reset by SDIO");
case 7:
return ("Timer group0 watch dog reset");
@@ -1295,7 +1331,7 @@ std::string System::reset_reason(uint8_t cpu) const {
return ("Software reset CPU");
case 13:
return ("RTC watch dog reset: CPU");
case 14:
case 14: // not on S2, C3
return ("APP CPU reset by PRO CPU");
case 15:
return ("Brownout reset");
@@ -1307,11 +1343,12 @@ std::string System::reset_reason(uint8_t cpu) const {
#endif
return ("Unkonwn");
}
#pragma GCC diagnostic pop
// set NTP status
void System::ntp_connected(bool b) {
if (b != ntp_connected_) {
LOG_INFO(b ? ("NTP connected") : ("NTP disconnected"));
LOG_INFO(b ? "NTP connected" : "NTP disconnected");
}
ntp_connected_ = b;
ntp_last_check_ = b ? uuid::get_uptime_sec() : 0;

View File

@@ -29,8 +29,8 @@
#ifndef EMSESP_STANDALONE
#include <esp_wifi.h>
#ifndef ARDUINO_LOLIN_S2_MINI
#include <esp_bt.h>
#if CONFIG_IDF_TARGET_ESP32
// #include <esp_bt.h>
#endif
#include <ETH.h>
#include <uuid/syslog.h>
@@ -225,6 +225,9 @@ class System {
uint32_t FStotal() {
return fstotal_;
}
uint32_t PSram() {
return psram_;
}
uint32_t appFree() {
return appfree_;
}
@@ -307,6 +310,7 @@ class System {
uint8_t eth_clock_mode_;
uint32_t fstotal_;
uint32_t psram_;
uint32_t appused_;
uint32_t appfree_;
};

View File

@@ -82,9 +82,9 @@ void EMSuart::start(const uint8_t tx_mode, const uint8_t rx_gpio, const uint8_t
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE,
.source_clk = UART_SCLK_APB,
};
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_param_config(EMSUART_NUM, &uart_config);
uart_set_pin(EMSUART_NUM, tx_gpio, rx_gpio, UART_PIN_NO_CHANGE, UART_PIN_NO_CHANGE);
uart_driver_install(EMSUART_NUM, 129, 0, (EMS_MAXBUFFERSIZE + 1) * 2, &uart_queue, 0); // buffer must be > fifo
uart_set_rx_full_threshold(EMSUART_NUM, 1);
uart_set_rx_timeout(EMSUART_NUM, 0); // disable
xTaskCreate(uart_event_task, "uart_event_task", 2048, NULL, configMAX_PRIORITIES - 1, NULL);

View File

@@ -26,12 +26,8 @@
#define EMS_MAXBUFFERSIZE 33 // max size of the buffer. EMS packets are max 32 bytes, plus extra for BRK
#if (defined(ARDUINO_LOLIN_C3_MINI)) || (defined(ARDUINO_LOLIN_S2_MINI))
#define EMSUART_NUM UART_NUM_1 // on C3 and S2 we're using UART1
#else
#define EMSUART_NUM UART_NUM_2 // on the ESP32 we're using UART2
#endif
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMSUART_NUM UART_NUM_1 // on C3 and S2 there is no UART2, use UART1 for all
#define EMSUART_BAUD 9600 // uart baud rate for the EMS circuit
#define EMS_TXMODE_DEFAULT 1
#define EMS_TXMODE_EMSPLUS 2

View File

@@ -1 +1,11 @@
#define EMSESP_APP_VERSION "3.5.0b6"
#if CONFIG_IDF_TARGET_ESP32C3
#define EMSESP_PLATFORM "ESP32-C3";
#elif CONFIG_IDF_TARGET_ESP32S2
#define EMSESP_PLATFORM "ESP32-S2";
#elif CONFIG_IDF_TARGET_ESP32
#define EMSESP_PLATFORM "ESP32";
#else
#error Target CONFIG_IDF_TARGET is not supported
#endif

View File

@@ -75,15 +75,18 @@ void WebSettings::read(WebSettings & settings, JsonObject & root) {
root["eth_power"] = settings.eth_power;
root["eth_phy_addr"] = settings.eth_phy_addr;
root["eth_clock_mode"] = settings.eth_clock_mode;
root["platform"] = EMSESP_PLATFORM;
}
// call on initialization and also when settings are updated via web or console
StateUpdateResult WebSettings::update(JsonObject & root, WebSettings & settings) {
// load default GPIO configuration based on board profile
std::vector<int8_t> data; // // led, dallas, rx, tx, button, phy_type, eth_power, eth_phy_addr, eth_clock_mode
#ifdef ARDUINO_LOLIN_C3_MINI
settings.board_profile = "C3MINI";
#else
#if CONFIG_IDF_TARGET_ESP32C3
settings.board_profile = root["board_profile"] | "C3MINI";
#elif CONFIG_IDF_TARGET_ESP32S2
settings.board_profile = root["board_profile"] | "S2MINI";
#elif CONFIG_IDF_TARGET_ESP32
settings.board_profile = root["board_profile"] | EMSESP_DEFAULT_BOARD_PROFILE;
#endif
if (!System::load_board_profile(data, settings.board_profile.c_str())) {