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