OPtimization on cores, netc, setup

This commit is contained in:
Heuideog Yi @ PC RnD1 2026-04-16 06:17:22 +09:00
parent 8415d83a6c
commit fd5298b691
8 changed files with 123 additions and 162 deletions

BIN
.gitignore vendored

Binary file not shown.

View File

@ -20,6 +20,7 @@
#ifndef DEBUG
#define DEBUG 1 // Set to 0 to disable debug output
#endif
#undef DEBUG
//#define BLE_DEBUG

View File

@ -53,10 +53,10 @@ MY_IRAM_ATTR void loop() {
// Un-Conditional Loop
{
//ESP_LOGI(TAG_MAIN,"Checking WiFi2");
checkWiFi(tickMillis);
//checkWiFi(tickMillis);
//ESP_LOGI(TAG_MAIN,"Host Loop");
host.Loop(tickMillis);
//host.Loop(tickMillis);
// UI Button Check
ui.loopButton(tickMillis);

View File

@ -61,67 +61,76 @@ const int16_t temp_C[] = {
20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30,
35, 40, 45, 50, 55, 60, 65, 70, 75, 80, 85, 90, 95, 100,
105, 110, 115, 120, 125, 130, 135, 140, 145, 150 };
NTC_10K ntc;
void NTC_10K::setup(bool bNegativePolarity) {
m_bNegativePolarity = bNegativePolarity;
_vRef = 3.3f;
_RESO = 4095;
for (int i = 0; i < 16; i++) temps[i] = 0;
temp_idx = 0;
temp_sum = 0;
m_nTemp = -9999;
m_fTemp = -9999.0;
m_fLastTemp = 0.0f;
pinMode(PIN_NTC, INPUT); // Set PIN_NTC as input
analogReadResolution(12); // Set ADC resolution to 12 bits (0-4095)
analogSetAttenuation(ADC_11db); // Set attenuation for full-scale 3.3V
}
/**
* @brief Reads NTC sensor, calculates temperature via interpolation,
* and applies an Exponential Moving Average (EMA) filter.
* * History:
* - 2026-04-16: Refactored from Simple Moving Average (SMA) to EMA with float buffer.
* - 2026-04-16: Optimized interpolation to reduce CPU cycles.
* - 2026-04-16: Implemented aggressive alpha (0.01) to mitigate 5°C PWM noise.
* - 2026-04-16: Upgraded lastTemp to float (m_fLastTemp) for total precision.
*/
void NTC_10K::readSensor() {
float Vin;
int16_t temp;
static int16_t lastTemp = 0;
float currentInstantTemp; // High-precision intermediate
int adcValue = analogRead(PIN_NTC); // Read ADC value from PIN_NTC
// 1. Hardware Acquisition
int adcValue = constrain(analogRead(PIN_NTC), 1, 4094);
// Calculate the input voltage from the ADC reading
// 2. Voltage and Resistance Calculation
Vin = (float)adcValue * _vRef / _RESO;
float r;
if (m_bNegativePolarity) {
r = (Vin / (_vRef - Vin)) * rRef;
} else {
r = ((_vRef - Vin) / Vin) * rRef;
}
// Calculate the resistance of the thermistor
// Calculate the resistance of the thermistor (adjusted for inverted ADC behavior)
float r;
if (m_bNegativePolarity) {
// NTC is connected to Negative
r = (Vin / (_vRef - Vin)) * rRef;
} else {
// NTC is connected to Positive
r = ((_vRef - Vin) / Vin) * rRef;
}
// Find the index of the resistance in the table where r is between resistance[i-1] and resistance[i]
// 3. Table Lookup
int i = 0;
while (i < sizeof(resistance) / sizeof(resistance[0]) - 1 && resistance[i] > r) {
int tableSize = sizeof(resistance) / sizeof(resistance[0]);
while (i < tableSize - 1 && resistance[i] > r) {
i++;
}
// If r is out of range, return the closest extreme temperature
if (i == 0 || i == sizeof(resistance) / sizeof(resistance[0]) - 1) {
if (lastTemp != 0) temp = lastTemp;
else temp = 0;
// 4. Interpolation Logic (Precise Float Math)
if (i == 0 || i == tableSize - 1) {
// Use last known good float value if out of bounds
currentInstantTemp = (m_fLastTemp != 0.0f) ? m_fLastTemp : 0.0f;
}
else {
// Faster Slope Calculation: y = y0 + m * (r - r0)
float m = (temp_C[i] - temp_C[i - 1]) / (resistance[i] - resistance[i - 1]);
currentInstantTemp = temp_C[i - 1] + m * (r - resistance[i - 1]);
}
else {
// Interpolate between resistance[i-1] and resistance[i]
float m = (temp_C[i] - temp_C[i - 1]) / (resistance[i] - resistance[i - 1]); // Slope
float b = temp_C[i - 1] - (m * resistance[i - 1]); // Intercept
temp = (int16_t) roundf((m * r + b) * 10.0f);
}
// Return the temperature as an integer scaled by 10 (e.g., 25.3°C => 253)
temp_sum -= temps[temp_idx];
temps[temp_idx++] = temp;
temp_idx &= NTC_MASK;
temp_sum += temp;
lastTemp = temp;
m_nTemp = temp_sum / NTC_COUNT;
}
// 5. Exponential Moving Average (EMA) Filtering
if (m_fTemp < -5000.0f) {
m_fTemp = currentInstantTemp;
} else {
// 0.01f Alpha: The 5°C PWM noise now only moves the buffer by 0.05°C per hit.
const float alpha = 0.05f;
m_fTemp = (currentInstantTemp * alpha) + (m_fTemp * (1.0f - alpha));
}
// 6. Update Outputs
m_fLastTemp = currentInstantTemp; // Store precise float for next loop
m_nTemp = (int16_t)roundf(m_fTemp * 10.0f); // Final integer output (e.g., 25.34 -> 253)
}

View File

@ -21,6 +21,8 @@ private:
int _RESO;
bool m_bNegativePolarity;
int16_t m_nTemp;
float m_fTemp;
float m_fLastTemp;
public:
void setup(bool bNegativePolarity);

20
OTA.cpp
View File

@ -17,10 +17,10 @@
// OTA
//
// ==============================================================
const char *HC__VERSION = "20260413001";
const char *HC__VERSION = "20250415001";
#define UPDATE_PORT ((uint16_t) 443)
String url = "visionsoft.kr";
String uri = "/hc/hc_firmware_update.php";
const char *url = "visionsoft.kr";
const char *uri = "/sc/pages/firmware_download.php";
const char *HTTPUPDATE_USERAGRENT = "ESP32-http-Update";
const char *COMPANY_NAME = "VisionSoft";
const char *SERVICE_NAME = "HermitCrab";
@ -78,13 +78,13 @@ bool checkOTA(bool bForceUpdate)
// result: POSITIVE (HTTP/Status), NEGATIVE (Network Error)
int result = ESPUpdate.update(
client,
"visionsoft.kr", // Server Host
443, // Server Port HTTPS,
"/sc/pages/firmware_download.php", // phpUri,
HC__VERSION, // Current Version string
"HCesp", // Project Tag
bForceUpdate, // bForceUpdate
true // bRebootAfterInstall
url, // Server Host
443, // Server Port HTTPS,
uri, // phpUri,
HC__VERSION, // Current Version string
SERVICE_NAME, // Project Tag
bForceUpdate, // bForceUpdate
true // bRebootAfterInstall
);
// ======================================================================

View File

@ -56,24 +56,15 @@ void setup() {
g_nSecond = 0;
bShowSensor = false;
DPRINTLN("1");
setupConfig();
DPRINTLN("2");
setupStatus();
DPRINTLN("3");
setupPins();
DPRINTLN("4");
scanI2C();
DPRINTLN("5");
setupSensor();
DPRINTLN("6");
ui.setup();
DPRINTLN("7");
ui.message(0, (char *) "WiFi...");
DPRINTLN("8");
setupWiFi();
DPRINTLN("9");
if (aht25.sensor() || aht10_0x39.sensor()) {
ui.message(4, (char *) "Sensor... OK!");
@ -97,7 +88,7 @@ void setup() {
xTaskCreatePinnedToCore(
core0Task, // Function to run as a task
"Task0", // Task name
10240, // Stack size in words
20480, // Stack size in words
NULL, // Task input parameter
1, // Priority of the task
&TaskHandle_0, // Task handle
@ -126,7 +117,7 @@ void setupWiFi() {
// Connect WiFi for OTA
if (config.ssid[0] && config.pw[0]) {
#if defined(ESP32)
esp_wifi_set_max_tx_power(84);
esp_wifi_set_max_tx_power(74);
#elif defined(ESP8266)
WiFi.setOutputPower(20.5f);
pinMode(16,OUTPUT);
@ -198,8 +189,6 @@ void setupPostWiFi(bool bBoot = false) {
}
}
#include "driver/ledc.h"
void setupPins() {
// --- Basic Digital Pin Initialization ---
pinMode(PIN_HEATER1, OUTPUT);
@ -219,39 +208,11 @@ void setupPins() {
ledcAttachChannel(PIN_LED_HEATER2, PWM_1KHZ_FREQ, PWM_RESOLUTION, PWM_HEATER2_CHANNEL);
// --- 3. Low Speed Group: Mist & WiFi LED (1.19Hz) ---
// Initialized at 32Hz to bypass the slow divider calculation/WDT panic.
// Initialized at 1Hz to bypass the slow divider calculation/WDT panic.
// Must be ESP32 coer version 3.0.2 in ordre to set 1Hz
ledcAttachChannel(PIN_MIST, PWM_1HZ_FREQ, PWM_RESOLUTION, PWM_MIST_CHANNEL);
ledcAttachChannel(PIN_LED_WIFI, PWM_1HZ_FREQ, PWM_RESOLUTION, PWM_WIFI_LED_CHANNEL);
// MANUALLY RECONFIGURE TIMER FOR 1.19Hz
// Source: LEDC_REF_TICK (1MHz)
// Divider: 819 (Integer part)
// Result: 1,000,000 / (819 * 1024) ≈ 1.192 Hz
// Note: On Core 2.0.17, LEDC_USE_REF_TICK is the correct constant.
/*
ledc_timer_set(
LEDC_LOW_SPEED_MODE,
LEDC_TIMER_0,
(uint32_t)(819 << 8), // 18.8 bit register: 819 integer, 0 fractional
(uint32_t)PWM_RESOLUTION,
LEDC_REF_TICK
);
*/
/*
ledc_timer_config_t mist_timer_conf = {
.speed_mode = LEDC_LOW_SPEED_MODE,
.duty_resolution = LEDC_TIMER_8_BIT,
.timer_num = LEDC_TIMER_0,
.freq_hz = 2, // The driver will target 1Hz
.clk_cfg = LEDC_USE_REF_TICK, // Forces the 1MHz source
.deconfigure = false
};
esp_err_t err = ledc_timer_config(&mist_timer_conf);
if (err == ESP_OK) {
// Apply the change and reset the counter
ledc_timer_rst(LEDC_LOW_SPEED_MODE, LEDC_TIMER_0);
}
*/
// --- Initial State Writes ---
ledcWrite(PIN_MOTOR, PWM_OFF);
ledcWrite(PIN_FAN, PWM_OFF);
@ -320,7 +281,7 @@ void setupSensor() {
if (aht25.setup()) {
delay(82);
aht25.readSensor(millis());
DPRINTF("AHTx0 initialized successfully at 0x38. Temp: %.2f, Humid: %.2f%%\n",
DPRINTF("AHT25 initialized successfully at 0x38. Temp: %.2f, Humid: %.2f%%\n",
aht25.getTemperature() / 100.0f, aht25.getHumidity() / 100.0f);
}

118
Task0.ino
View File

@ -27,97 +27,85 @@ MY_IRAM_ATTR void core0Task(void *pvParameters) {
wl_status_t lastWiFiStatus = WL_DISCONNECTED;
unsigned long tickMillis = millis();
unsigned long tickSecond;
unsigned long lastTick = tickMillis / 1000;
unsigned long lastTickMillis = tickMillis;
unsigned long lastSensorUpdate1 = tickMillis;
unsigned long lastSensorUpdate2 = tickMillis + 2500;
uint16_t tick1000, lastTick1000 = tickMillis % 1000;;
uint16_t tick250, lastTick250 = tickMillis % 250;
uint8_t slot;
uint8_t lastSlot = tickMillis / 50;
uint8_t lastSlot = 255;
esp_task_wdt_add(NULL); // NULL for the current task
ui.start();
ble.setupScan();
while (true) {
esp_task_wdt_reset();
tickMillis = millis();
tick250 = tickMillis % 250;
tick1000 = tickMillis % 1000;
tickSecond = tickMillis / 1000;
slot = tick1000 / 50;
slot = (tickMillis % 1000) / 50;
//===============================================================================
// Loop top
// Once in a second loop
if (tick1000 != lastTick1000) {
if (slot != lastSlot) {
switch (slot) {
case 1:
case 6:
case 11:
case 16: // UI Display
ui.updateDisplayTop(tickSecond);
break;
case 2:
case 7:
case 12:
case 17: // NTC Temp Sensor
ntc.readSensor();
break;
// Loop top: Once in a second loop
if (slot != lastSlot) {
lastSlot = slot;
switch (slot) {
case 1:
case 6:
case 11:
case 16: // UI Display
ui.updateDisplayTop(tickSecond);
break;
case 2:
case 4:
case 7:
case 9:
case 12:
case 14:
case 17: // NTC Temp Sensor
case 19:
ble.loop(tickMillis);
break;
case 3: // NTP - Time
if (isWiFiConnected()) {
if (timeManager.getTime(tickMillis)) {
ESP_LOGI(TAG_TASK0,"NTP time loaded: %s", printTime());
}
if (isWiFiConnected()) {
if (timeManager.getTime(tickMillis)) {
ESP_LOGI(TAG_TASK0,"NTP time loaded: %s", printTime());
}
break;
case 4:
case 9:
case 14:
case 19:
ntc.readSensor();
break;
}
break;
case 5: // Heartbeat
if (isWiFiConnected()) {
host.SendHeartBeat(tickMillis);
}
break;
if (isWiFiConnected()) {
host.SendHeartBeat(tickMillis);
}
break;
case 8: // BLE
ble.loop(tickMillis);
break;
case 13: // ATH2x - 0x38
aht25.readSensor(tickMillis);
break;
case 8: // NTC
ntc.readSensor();
break;
case 13: // ATH2x - 0x38
aht25.readSensor(tickMillis);
break;
case 15: // ATH0x - 0x39
aht10_0x39.readSensor(tickMillis);
break;
case 15: // ATH0x - 0x39
aht10_0x39.readSensor(tickMillis);
break;
case 18: // UI Bottom
ui.updateDisplayBottom(tickSecond);
break;
default: // 0 10
break;
}
lastSlot = slot;
case 18: // UI Bottom
ui.updateDisplayBottom(tickSecond);
break;
default: // 0 10
break;
}
lastTick1000 = tick1000;
lastTick250 = tick250;
} // end of - if (tick1000 != lastTick1000)
}
// =====================================================
// Unconditional Loop
checkWiFi(tickMillis);
host.Loop(tickMillis);
host.MonitorUDP();
// Loop end
//==========================================================================
lastTickMillis = tickMillis;
esp_task_wdt_reset();
} // end of - While(True)