some fixes

This commit is contained in:
2026-01-30 18:36:20 +03:00
parent ba830d61fa
commit 29a1732880
2 changed files with 93 additions and 26 deletions

View File

@@ -50,7 +50,7 @@ W = 100 × (m1 - m0) / (m0 - m)
### Удержание кнопки (4-6 секунд)
Автоматическое тарирование (обнуление весов)
### Удержание кнопки (8-10 секунд)
### Удержание кнопки (8+ секунд)
Калибровка с эталонным грузом 100г
## Режим нагрева

View File

@@ -57,14 +57,13 @@ const unsigned long HEAT_DURATION = 900000; // 15 минут = 900000 мс
bool heating_active = false;
// Циклический нагрев
const unsigned long HEAT_ON_TIME = 30000; // 30 секунд нагрева
const unsigned long HEAT_OFF_TIME = 20000; // 20 секунд паузы
const unsigned long HEAT_ON_TIME = 20000; // 15 секунд нагрева
const unsigned long HEAT_OFF_TIME = 30000; // 30 секунд паузы
unsigned long last_cycle_change = 0; // Время последнего переключения
bool heat_cycle_on = false; // Текущее состояние цикла (вкл/выкл)
// Для постоянного расчета W с фильтрацией
float current_W = 0.0; // Текущее значение влажности (сырое)
float filtered_W = 0.0; // Отфильтрованное значение W для отображения
// Для расчета W (без фильтрации)
float current_W = 0.0; // Текущее значение влажности
float max_W = 0.0; // Максимальное значение W за время нагрева
unsigned long last_W_update = 0;
const unsigned long W_UPDATE_INTERVAL = 500; // Обновлять W каждые 500 мс
@@ -357,12 +356,23 @@ void loop() {
// Обновляем W каждые W_UPDATE_INTERVAL мс
if (millis() - last_W_update > W_UPDATE_INTERVAL) {
current_W = calculateW(); // Вычисляем сырое значение W
filtered_W = w_filter.update(current_W); // Фильтруем для отображения
current_W = calculateW(); // Вычисляем W напрямую (без фильтра)
// DEBUG: выводим все значения для диагностики
Serial.print("m=");
Serial.print(m, 4);
Serial.print(" m1=");
Serial.print(m1, 4);
Serial.print(" m0=");
Serial.print(m0, 4);
Serial.print(" W=");
Serial.print(current_W, 4);
Serial.print(" max_W=");
Serial.println(max_W, 4);
// Обновляем максимальное значение W
if (filtered_W > max_W) {
max_W = filtered_W;
if (current_W > max_W) {
max_W = current_W;
}
last_W_update = millis();
@@ -467,7 +477,7 @@ void updateDisplay() {
heat_cycle_on = true;
last_cycle_change = millis();
last_W_update = millis();
w_filter.reset(); // Сбрасываем фильтр W при начале нагрева
// Фильтр W удалён - используем прямое значение
max_W = 0.0; // Сбрасываем максимальное W
digitalWrite(HEAT_PIN, HIGH);
break;
@@ -529,8 +539,8 @@ void handleButton() {
// Тарирование 4-6 секунд
performTaring();
}
else if (press_duration >= MIN_CAL_TIME && press_duration <= MAX_CAL_TIME) {
// Калибровка 8-10 секунд
else if (press_duration >= MIN_CAL_TIME) {
// Калибровка 8+ секунд
performCalibration();
}
else if (press_duration < 1000) {
@@ -605,21 +615,38 @@ void displayHeating() {
lcd.setCursor(0, 0);
lcd.print(line1);
// Вторая строка: только максимальный W
// Вторая строка: масса (слева) и W (справа)
char line2[17];
char m_buf[6];
char w_buf[6];
char mass_buf[7];
// Форматируем максимальный W
if (max_W >= 100) {
strcpy(m_buf, ">99");
strcpy(w_buf, ">99");
} else {
dtostrf(max_W, 5, 1, m_buf);
dtostrf(max_W, 4, 1, w_buf);
}
// Формат: "Wmax: XX.X%"
snprintf(line2, sizeof(line2), "W:%s%%", m_buf);
// Форматируем массу m0 (показываем когда индуктор выключен)
if (!heat_cycle_on) {
// Индуктор выключен - показываем текущую массу
if (m0 >= 100.0) {
strcpy(mass_buf, ">99g");
} else if (m0 <= -10.0) {
strcpy(mass_buf, "<-9g");
} else {
dtostrf(m0, 5, 2, mass_buf);
strcat(mass_buf, "g");
}
// Формат: "XX.XXg W:XX.X%"
snprintf(line2, sizeof(line2), "%-8s %s%%", mass_buf, w_buf);
} else {
// Индуктор включен - показываем только W по центру
snprintf(line2, sizeof(line2), " * %s%%", w_buf);
}
printCentered(1, line2);
lcd.setCursor(0, 1);
lcd.print(line2);
}
void displayHeatingComplete() {
@@ -683,7 +710,6 @@ void performTaring() {
scale.tare();
median_filter.reset();
display_filter.setImmediate(0.0);
w_filter.reset();
// Если был режим нагрева - выходим из него
if (heating_active) {
@@ -708,6 +734,10 @@ void performCalibration() {
}
void calibrationProcedure() {
Serial.println("=== CALIBRATION START ===");
Serial.print("Old calibration_factor: ");
Serial.println(calibration_factor, 6);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Calibration ");
@@ -717,9 +747,11 @@ void calibrationProcedure() {
digitalWrite(HEAT_PIN, LOW);
heating_active = false;
heat_cycle_on = false;
Serial.println("Heating was active, turned off");
}
// Шаг 1: Clear platform
Serial.println("Step 1: Waiting for empty platform...");
lcd.setCursor(0, 1);
lcd.print("Clear platform ");
@@ -733,14 +765,22 @@ void calibrationProcedure() {
delay(100);
// Сообщение о тарировании
Serial.println("Step 2: Taring...");
lcd.setCursor(0, 1);
lcd.print("Taring... ");
// ВАЖНО: Устанавливаем scale=1.0 ПЕРЕД тарированием,
// чтобы получать сырые значения и избежать зацикливания калибровки
scale.set_scale(1.0);
Serial.println("Scale set to 1.0 for raw measurements");
// Тарируем весы (устанавливаем ноль)
delay(500); // Даем время на стабилизацию
scale.tare();
Serial.println("Tare complete");
// Шаг 2: Set 100g
Serial.println("Step 3: Waiting for 100g weight...");
lcd.setCursor(0, 1);
lcd.print("Set 100g ");
@@ -754,29 +794,47 @@ void calibrationProcedure() {
delay(100);
// Сообщение о сохранении результатов 100г
Serial.println("Step 4: Measuring 100g raw values (15 samples)...");
lcd.setCursor(0, 1);
lcd.print("saving results ");
// Измеряем среднее значение 100г (15 измерений)
// Измеряем среднее СЫРОЕ значение 100г (15 измерений)
// scale=1.0, поэтому get_units() возвращает сырые значения
delay(1000); // Даем время на стабилизацию
float weight_sum = 0;
for (int i = 0; i < 15; i++) {
float reading = scale.get_units(1);
float reading = scale.get_units(1); // При scale=1.0 это сырое значение
weight_sum += reading;
Serial.print(" Raw sample ");
Serial.print(i + 1);
Serial.print(": ");
Serial.println(reading, 2);
delay(100);
}
float weight_average = weight_sum / 15;
Serial.print("Raw weight sum: ");
Serial.println(weight_sum, 2);
Serial.print("Raw weight average: ");
Serial.println(weight_average, 2);
Serial.print("CALIBRATION_WEIGHT: ");
Serial.println(CALIBRATION_WEIGHT, 2);
// Вычисляем коэффициент калибровки
// После tare() шкала обнулена, поэтому weight_average - это разница веса напрямую
// Проверяем, что груз действительно поставлен (вес больше 10 единиц)
if (abs(weight_average) > 10) {
// scale=1.0 и tare() выполнен, поэтому weight_average - это СЫРОЕ значение АЦП
// new_factor = raw_value / known_weight
// Проверяем, что груз поставлен (сырое значение больше 1000 единиц АЦП)
if (abs(weight_average) > 1000) {
calibration_factor = weight_average / CALIBRATION_WEIGHT;
Serial.print("New calibration_factor: ");
Serial.println(calibration_factor, 6);
// Проверяем, что коэффициент положительный
if (calibration_factor <= 0) {
// Ошибка: отрицательный или нулевой коэффициент - неправильная калибровка
// (датчик подключен неправильно или вес убрали вместо добавления)
Serial.println("ERROR: calibration_factor <= 0!");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Calibration ");
@@ -786,11 +844,14 @@ void calibrationProcedure() {
} else {
// Сохраняем коэффициент в EEPROM
saveCalibrationToEEPROM(calibration_factor);
Serial.println("Calibration factor saved to EEPROM");
// Устанавливаем новый коэффициент
scale.set_scale(calibration_factor);
Serial.println("Scale updated with new factor");
// Сообщение об успешной калибровке
Serial.println("=== CALIBRATION OK ===");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Calibration ");
@@ -800,6 +861,11 @@ void calibrationProcedure() {
}
} else {
// Сообщение о неудачной калибровке (груз не поставлен или слишком легкий)
Serial.print("ERROR: abs(raw_weight_average) = ");
Serial.print(abs(weight_average), 2);
Serial.println(" <= 1000, raw ADC value too low!");
Serial.println("Check: is 100g weight placed? Is HX711 connected?");
Serial.println("=== CALIBRATION FAILED ===");
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Calibration ");
@@ -813,4 +879,5 @@ void calibrationProcedure() {
// Возврат в режим READY
current_state = STATE_READY;
need_display_clear = true;
Serial.println("Returned to READY state");
}