#include <Arduino.h>
#include <EEPROM.h>
struct Config {
uint8_t tick = 100;
uint8_t encType = 1;
uint16_t diameter = 50;
uint16_t signalDist = 500;
uint16_t targetM = 0;
uint16_t targetCM = 0;
uint16_t targetMM = 0;
};
Config settings;
volatile long pulses = 0;
unsigned long lastSignalMillis = 0;
long totalTargetMM = 0;
void calculateTarget() {
totalTargetMM = (settings.targetM * 1000L) + (settings.targetCM * 10L) + settings.targetMM;
}
double getMM() {
return (pulses * (3.14159265 * settings.diameter)) / settings.tick;
}
void setup() {
Serial.begin(9600);
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
pinMode(13, OUTPUT);
attachInterrupt(digitalPinToInterrupt(2), []() {
if (settings.encType == 0) pulses++;
else (digitalRead(3) == LOW) ? pulses++ : pulses--;
}, RISING);
EEPROM.get(0, settings);
calculateTarget();
// ПРИВЕТСТВИЕ С ПЕРЕНОСОМ СТРОКИ
Serial.println(F("Система готова к работе\nвведи ? для списка комманд."));
}
void loop() {
if (Serial.available() > 0) {
String cmd = Serial.readStringUntil('\n');
cmd.trim();
if (cmd.length() == 0) return;
bool recognized = false;
bool silentMode = false;
// --- Информационные команды (БЕЗ OK) ---
if (cmd == "m?") {
Serial.println(getMM() / 1000.0, 2);
recognized = true; silentMode = true;
}
else if (cmd == "cm?") {
Serial.println(getMM() / 10.0, 1);
recognized = true; silentMode = true;
}
else if (cmd == "mm?") {
Serial.println((long)getMM());
recognized = true; silentMode = true;
}
// --- Остальные команды (С ПОДТВЕРЖДЕНИЕМ OK) ---
else if (cmd == "?") {
Serial.println(F("? - вывод списка комманд"));
Serial.println(F("set? - вывод значений настроек"));
Serial.println(F("m? - показать сколько отмоталось в метрах и два знака после запятой."));
Serial.println(F("cm? - показать сколько отмоталось в сантиметрах."));
Serial.println(F("mm? - показать сколько отмоталось в милиметрах."));
Serial.println(F("save(1-16)- сохранить настройки в профиль 1...16 в eeprom если 0 то в текущий профиль."));
Serial.println(F("load(1-16) - загрузить настройки из профиля 1...16 из eeprom если 0 то в текущий профиль."));
Serial.println(F("tick (0-255) количество импульсов на оборот"));
Serial.println(F("enc 0\\1 - тип энкодера\\тахометра 0- однопроводный 1- двухпроводный квадратурный"));
Serial.println(F("diameter (1-65535) диаметр измерительного колеса в мм"));
Serial.println(F("signal (0-65535) за сколько мм до конца метража начать подавать сигнал."));
Serial.println(F("meters (0-65535) сколько метров отмотать 0 - не сигналить"));
Serial.println(F("cm (0-65535) сколько сантиметров отмотать 0 - не сигналить"));
Serial.println(F("mm (0-65535) сколько милиметров отмотать 0 - не сигналить"));
recognized = true;
}
else if (cmd == "set?") {
Serial.println(F("--- Текущие настройки ---"));
Serial.print(F("tick: ")); Serial.println(settings.tick);
Serial.print(F("enc: ")); Serial.println(settings.encType);
Serial.print(F("diameter: ")); Serial.println(settings.diameter);
Serial.print(F("signal: ")); Serial.println(settings.signalDist);
Serial.print(F("meters: ")); Serial.println(settings.targetM);
Serial.print(F("cm: ")); Serial.println(settings.targetCM);
Serial.print(F("mm: ")); Serial.println(settings.targetMM);
recognized = true;
}
else if (cmd == "reset") { pulses = 0; recognized = true; }
else if (cmd.startsWith("tick ")) { settings.tick = cmd.substring(5).toInt(); recognized = true; }
else if (cmd.startsWith("enc ")) { settings.encType = cmd.substring(4).toInt(); recognized = true; }
else if (cmd.startsWith("diameter ")) { settings.diameter = cmd.substring(9).toInt(); recognized = true; }
else if (cmd.startsWith("daimeter ")) { settings.diameter = cmd.substring(9).toInt(); recognized = true; }
else if (cmd.startsWith("signal ")) { settings.signalDist = cmd.substring(7).toInt(); recognized = true; }
else if (cmd.startsWith("meters ")) { settings.targetM = cmd.substring(7).toInt(); calculateTarget(); recognized = true; }
else if (cmd.startsWith("cm ")) { settings.targetCM = cmd.substring(3).toInt(); calculateTarget(); recognized = true; }
else if (cmd.startsWith("mm ")) { settings.targetMM = cmd.substring(3).toInt(); calculateTarget(); recognized = true; }
else if (cmd.startsWith("save")) {
int p = extractProfile(cmd);
if (p >= 0 && p <= 16) { EEPROM.put(p * sizeof(Config), settings); recognized = true; }
}
else if (cmd.startsWith("load")) {
int p = extractProfile(cmd);
if (p >= 0 && p <= 16) { EEPROM.get(p * sizeof(Config), settings); calculateTarget(); recognized = true; }
}
if (recognized) {
if (!silentMode) {
Serial.print(cmd);
Serial.println(F(" >> OK"));
}
} else {
Serial.print(F("Ошибка: Неизвестная команда ["));
Serial.print(cmd);
Serial.println(F("]. Введите '?' для вывода списка команд."));
}
}
handleSignal();
}
int extractProfile(String s) {
int start = s.indexOf('(');
int end = s.indexOf(')');
if (start != -1 && end != -1) return s.substring(start + 1, end).toInt();
return -1;
}
void handleSignal() {
if (totalTargetMM <= 0) { digitalWrite(13, LOW); return; }
long remaining = totalTargetMM - (long)getMM();
if (remaining <= 0) {
digitalWrite(13, HIGH);
} else if (remaining < settings.signalDist) {
int interval = map(constrain(remaining, 0, settings.signalDist), 0, settings.signalDist, 40, 500);
if (millis() - lastSignalMillis >= interval) {
digitalWrite(13, !digitalRead(13));
lastSignalMillis = millis();
}
} else {
digitalWrite(13, LOW);
}
}