bool butt_flag1 = 0; // переменная-флаг для работы кнопки 1
bool butt_flag2 = 0; // переменная-флаг для работы кнопки 2
bool butt_flag3 = 0; // переменная-флаг для работы кнопки 3
bool butt_flag4 = 0; // переменная-флаг для работы кнопки 4
bool butt1; // переменная для отработки функции кнопки 1
bool butt2; // переменная для отработки функции кнопки 2
bool butt3; // переменная для отработки функции кнопки 3
bool butt4; // переменная для отработки функции кнопки 4
unsigned long last_press; // таймер для антидребезга кнопок
byte mode = 5; // первоначальный режим при запуске программы - 5-й (в программе никак не описан, на нём ничего не происходит)
byte PIN_BT_1; // переменная для инверсии кнопок 1 и 2
byte PIN_BT_2; // переменная для инверсии кнопок 1 и 2
bool flag_reverse; // переменная для реле
//-------------------------переменные для PID-регулятора-------------------------------
//--------------------------------начало-----------------------------------------------
float RPMdes; // переменная для задания желаемых оборотов, !!!!!!! именно эту величину надо будет увеличивать по ACCEL. Ее будет старатьтся удерживать регулятор. Зависит от количества прорезей на диске
float tok = 0.0; // начальный ток двигателя значение 0-255
float tokP = 0.0; // пропорциональная часть в PID-регуляторе
float tokI = 0.0; // интегральная часть в PID-регуляторе
float tokD = 0.0; // дифференциальная часть в PID-регуляторе
float kP = 5.0; // коэффициент p - подбирается / зависит индивидуально от конкретного двигателя
float kI = 0.0; // коэффициент i - подбирается / зависит индивидуально от конкретного двигателя
float kD = 20.0; // коэффициент d - подбирается / зависит индивидуально от конкретного двигателя
boolean srab = 0; // переменная для получения значения датчика оборотов
boolean srab_flag = 0; // флаг срабатывания датчика оборотов
int rpm; // переменная для подсчета количества срабатываний датчика оборотов
unsigned long timer; // таймер для подсчета количества срабатываний датчика оборотов в единицу времени
byte PROREZ = 1; // количество прорезей в диске датчика оборотов
int RPM; // Суммарное количество импульсов за период. Итог (результат) подпрограммы подсчета оборотов
int RPM1; // RPM1; RPM2; RPM3;.... предыдущие замеры с датчика оборотов со сдвигом по времени
int RPM2; //
int RPM3; //
int RPM4; //
float RPMsred; // среднее значение от RPM1; RPM2; RPM3...
unsigned long timersredRMP = 0; // таймер для отсечта RPM1; RPM2; RPM3;.... предыдущих замеров с датчика оборотов со сдвигом по времени
float raznostRPM = 0.0; // Разность между требуемыми оборотами и средним от измеренного
float lastraznostRPM = 0.0; // Предыдущая разность между требуемыми оборотами и средним от измеренного
unsigned long timerP = 0; // таймер, через сколько времени сравнивать разноть текущих и заданных оборотов
//unsigned long timerI = 0; // таймер, через сколько времени сравнивать разноть текущих и заданных оборотов
unsigned long timerD = 0; // dT в подсчете дифференциальной составляющей
float I; // переменная для расчета интегральной составляющей
float ABCD; // промежуточная переменная для вывода конечного значения
//---------------------------------конец-----------------------------------------------
//-------------------------переменные для PID-регулятора-------------------------------
#define RPMdes_1 0 // нижний порог ШИМ для 1-го положения контроллера
#define RPMdes_2 5 // нижний порог ШИМ для 2-го положения контроллера, верхний порог ШИМ для 1-го положения контроллера
#define RPMdes_3 15 // нижний порог ШИМ для 3-го положения контроллера, верхний порог ШИМ для 2-го положения контроллера
#define RPMdes_4 25 // нижний порог ШИМ для 4-го положения контроллера, верхний порог ШИМ для 3-го положения контроллера
#define RPMdes_5 35 // верхний порог ШИМ для 4-го положения контроллера
#define ACCEL_1_UP 100 // ускорение на 1 положении контроллера
#define ACCEL_2_UP 100 // ускорение на 2 положении контроллера
#define ACCEL_3_UP 100 // ускорение на 3 положении контроллера
#define ACCEL_4_UP 100 // ускорение на 4 положении контроллера
#define ACCEL_3_DN 100 // замедление на 3 положении контроллера
#define ACCEL_2_DN 100 // замедление на 2 положении контроллера
#define ACCEL_1_DN 100 // замедление на 1 положении контроллера
#define ACCEL_0_DN 100 // замедление на 0 положении контроллера
#define DEBOUNCE 150 // значение таймера для антидребезга кнопок
// назначение пинов на плате
#define BUTT_1_PIN 12 // пин для кнопки 1
#define BUTT_2_PIN 8 // пин для кнопки 2
#define BUTT_3_PIN 7 // пин для кнопки 3
#define BUTT_4_PIN 4 // пин для кнопки 4
#define LED_1_PIN 11 // пин для прожектора желтого
#define LED_2_PIN 13 // пин для прожектора красного
#define SHIM_PIN 9 // пин ШИМ на двигатель
#define RELAY_PIN 10 // пин на реле
#define INTRPT_PIN_2 2 // пин на прерывание 0 для тахометра
#define INTRPT_PIN_3 3 // пин на прерывание 1 для тахометра
void setup() {
Serial. begin(9600); // открыть порт
pinMode(BUTT_1_PIN, INPUT_PULLUP); // кнопка 1
pinMode(BUTT_2_PIN, INPUT_PULLUP); // кнопка 2
pinMode(BUTT_3_PIN, INPUT_PULLUP); // кнопка 3
pinMode(BUTT_4_PIN, INPUT_PULLUP); // кнопка 4
pinMode(LED_1_PIN, OUTPUT); // прожектор желтый
pinMode(LED_2_PIN, OUTPUT); // прожектор красный
pinMode(RELAY_PIN, OUTPUT); // реверсер
pinMode(SHIM_PIN, OUTPUT); // двигатель
pinMode(INTRPT_PIN_3, INPUT_PULLUP); // датчик оборотов
RPMsred = (float)(RPM+RPM1+RPM2+RPM3+RPM4)/5; // расчет среднего значения оборотов при загрузке программы
}
//--------------------------------
//--------------------------------
// алгоритм счетчика таймера ACCEL
//--------------------------------
//--------------------------------
uint8_t non_stop_program1(uint16_t span) {
static uint32_t future = 0;
if (millis() < future) return 0;
future += span;
return 1;
}
//--------------------------------
//--------------------------------
// алгоритм счетчика таймера ACCEL
//--------------------------------
//--------------------------------
void CTR_1_UP() {
for (RPMdes >= RPMdes_1; RPMdes < RPMdes_2; RPMdes) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_1 и RPMdes_2)
if (non_stop_program1(ACCEL_1_UP)) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для ускорения на 1 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_1, RPMdes_2); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_1 и RPMdes_2)
RPMdes = (float)RPMdes + 0.1; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, увеличив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("1ST CONTROLLER POSITION (FW), RPMdes = "); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt2 = !digitalRead(PIN_BT_2); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (опрос кнопки понижающенго положения)
if (butt2 == 1 && butt_flag2 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
break; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
} // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
if(butt2 == 0 && butt_flag2 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
butt_flag2 = 0; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
}
}
}
}
void CTR_2_UP() {
for (RPMdes >= RPMdes_2; RPMdes < RPMdes_3; RPMdes) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_2 и RPMdes_3)
if (non_stop_program1(ACCEL_2_UP)) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для ускорения на 2 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_2, RPMdes_3); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_2 и RPMdes_3)
RPMdes = (float)RPMdes + 0.1; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, увеличив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("2ND CONTROLLER POSITION (FW), RPMdes = "); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt2 = !digitalRead(PIN_BT_2); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (опрос кнопки понижающенго положения)
if (butt2 == 1 && butt_flag2 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
break; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
} // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
if(butt2 == 0 && butt_flag2 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
butt_flag2 = 0; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
}
}
}
}
void CTR_3_UP() {
for (RPMdes >= RPMdes_3; RPMdes < RPMdes_4; RPMdes) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_4 и RPMdes_3)
if (non_stop_program1(ACCEL_3_UP)) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для ускорения на 3 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_3, RPMdes_4); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_3 и RPMdes_4)
RPMdes = (float)RPMdes + 0.1; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, увеличив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("3RD CONTROLLER POSITION (FW), RPMdes = "); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt2 = !digitalRead(PIN_BT_2); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (опрос кнопки понижающенго положения)
if (butt2 == 1 && butt_flag2 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
break; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
} // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
if(butt2 == 0 && butt_flag2 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
butt_flag2 = 0; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
}
}
}
}
void CTR_4_UP() {
for (RPMdes >= RPMdes_4; RPMdes < RPMdes_5; RPMdes) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_4 и RPMdes_5)
if (non_stop_program1(ACCEL_4_UP)) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для ускорения на 4 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_4, RPMdes_5); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_4 и RPMdes_5)
RPMdes = (float)RPMdes + 0.1; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, увеличив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("4TH CONTROLLER POSITION (FW), RPMdes = "); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt2 = !digitalRead(PIN_BT_2); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (опрос кнопки понижающенго положения)
if (butt2 == 1 && butt_flag2 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
break; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
} // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
if(butt2 == 0 && butt_flag2 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
butt_flag2 = 0; // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
last_press = millis(); // подпрограмма для увеличения значения RPMdes через временной интервал ACCEL (если нажата кнопка понижающенго положения)
}
}
}
}
void CTR_3_DN() {
for (RPMdes <= RPMdes_5; RPMdes > RPMdes_4; RPMdes) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_5 и RPMdes_4)
if (non_stop_program1(ACCEL_3_DN)) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для замедления на 3 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_4, RPMdes_5); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_4 и RPMdes_5)
RPMdes = (float)RPMdes - 0.1; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, уменьшив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("3RD CONTROLLER POSITION (BW), RPMdes = "); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt1 = !digitalRead(PIN_BT_1); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (опрос кнопки повышающего положения)
if (butt1 == 1 && butt_flag1 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
break; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
} // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
if(butt1 == 0 && butt_flag1 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
butt_flag1 = 0; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
}
}
}
}
void CTR_2_DN() {
for (RPMdes <= RPMdes_4; RPMdes > RPMdes_3; RPMdes) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_4 и RPMdes_3)
if (non_stop_program1(ACCEL_2_DN)) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для замедления на 2 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_3, RPMdes_4); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_3 и RPMdes_4)
RPMdes = (float)RPMdes - 0.1; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, уменьшив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("2ND CONTROLLER POSITION (BW), RPMdes = "); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt1 = !digitalRead(PIN_BT_1); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (опрос кнопки повышающего положения)
if (butt1 == 1 && butt_flag1 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
break; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
} // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
if(butt1 == 0 && butt_flag1 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
butt_flag1 = 0; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
}
}
}
}
void CTR_1_DN() {
for (RPMdes <= RPMdes_3; RPMdes > RPMdes_2; RPMdes) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_3 и RPMdes_2)
if (non_stop_program1(ACCEL_1_DN)) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для замедления на 1 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_2, RPMdes_3); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_2 и RPMdes_3)
RPMdes = (float)RPMdes - 0.1; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, уменьшив его на 0,1)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("1ST CONTROLLER POSITION (BW), RPMdes = "); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt1 = !digitalRead(PIN_BT_1); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (опрос кнопки повышающего положения)
if (butt1 == 1 && butt_flag1 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
break; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
} // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
if(butt1 == 0 && butt_flag1 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
butt_flag1 = 0; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
}
}
}
}
void CTR_0_DN() {
for (RPMdes <= RPMdes_2; RPMdes > RPMdes_1; RPMdes) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если RPMdes в диапазоне RPMdes_2 и RPMdes_1)
if (non_stop_program1(ACCEL_0_DN)) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выполнить подпрограмму счетчика таймера ACCEL для замедления на 0 положении контроллера)
RPMdes = constrain (RPMdes, RPMdes_1, RPMdes_2); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (ограничить диапазон значений RPMdes значениями RPMdes_1 и RPMdes_2)
RPMdes = (float)RPMdes - 0.1; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (вычислить новое значение RPMdes, уменьшив его на 0,1)
if (RPMdes < 0) {RPMdes = 0;} // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (снятие ошибки получения отрицательного значения RPMdes)
//analogWrite(SHIM_PIN, RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать на ШИМ-пин значение RPMdes)
Serial.print("ZERO CONTROLLER POSITION (BW), RPMdes = "); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
Serial.println(RPMdes); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (выдать в порт текущее значение RPMdes)
butt1 = !digitalRead(PIN_BT_1); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (опрос кнопки повышающего положения)
if (butt1 == 1 && butt_flag1 == 0 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
Serial.print("---MODE---"); Serial.print(mode); Serial.println("---BREAK_BY_BTN_2---"); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
break; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
} // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
if(butt1 == 0 && butt_flag1 == 1 && millis() - last_press > DEBOUNCE) { // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
butt_flag1 = 0; // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
last_press = millis(); // подпрограмма для уменьшения значения RPMdes через временной интервал ACCEL (если нажата кнопка повышающего положения)
}
}
}
}
//-----------сбор исходных данных с датчика оборотов для PID-регулятора-----------
//-----------------------------------начало---------------------------------------
int RPMcycle() {
srab = digitalRead(INTRPT_PIN_3);
if (srab == HIGH && srab_flag == 0) {
srab_flag = !srab_flag;
}
if (srab == LOW && srab_flag == 1) {
srab_flag = !srab_flag;
rpm++;
}
return rpm;
}
//------------------------------------конец---------------------------------------
//-----------сбор исходных данных с датчика оборотов для PID-регулятора-----------
//----------------------------функция PID-регулятора------------------------------
//-----------------------------------начало---------------------------------------
void PID() {
RPMcycle();
if (millis() - timer <= 25) {
goto label_rpm;
}
RPM = RPMcycle()/PROREZ;
if ((millis () - timersredRMP) < 1) {goto nosred;}
timersredRMP = millis ();
RPM4 = RPM3;
RPM3 = RPM2;
RPM2 = RPM1;
RPM1 = RPM;
RPMsred = (float)(RPM+RPM1+RPM2+RPM3+RPM4)/5;
nosred: ;
/// PID - регулятор
if ((millis () - timerP) < 2) {
goto labelPID;
}
timerP = millis ();
raznostRPM = (float)RPMdes - RPM;
tokP = (float)kP * raznostRPM; // пропорциональная составляющая PID-регулятора
I = (float)I + ((float)raznostRPM * 2); // расчет значения I для интегральной составляющей PID-регулятора
tokI = (float)kI * I; // интегральная составляющая PID-регулятора
tokD = (float)kD * (raznostRPM - lastraznostRPM) / 2; // дифференциальная составляющая PID-регулятора
if ((millis () - timerD) > 2) {
lastraznostRPM = raznostRPM;
timerD = millis ();
}
//tok = (float)tok + tokP + tokD;
tok = (float)tok + tokP + tokI + tokD;
//ABCD = tok;
// Корректировка - чтобы ШИМ не уходил ниже минимума и выше максимума
if (tok < 10) {tok = 10;}
if (tok > 255) {tok = 255;}
labelPID: ;
//analogWrite(SHIM_PIN, tok);
/// конец PID - регулятора
Serial.print(RPM);
Serial.print(" ");
Serial.print(RPMdes);
Serial.print(" ");
Serial.print(RPMsred);
Serial.print(" ");
Serial.println(tok);
rpm = 0;
timer = millis();
label_rpm: ;
//return ABCD;
//ABCD = tok;
}
//------------------------------------конец---------------------------------------
//----------------------------функция PID-регулятора------------------------------
void loop() {
butt1 = !digitalRead(PIN_BT_1); // инверсия кнопок 1 и 2 при срабатывании реле (опрос кнопки 1)
butt2 = !digitalRead(PIN_BT_2); // инверсия кнопок 1 и 2 при срабатывании реле (опрос кнопки 2)
if (flag_reverse == 0) { // инверсия кнопок 1 и 2 при срабатывании реле (если реле "вперед" - флаг 0)
PIN_BT_1 = BUTT_1_PIN; // инверсия кнопок 1 и 2 при срабатывании реле (кнопка 1 считывается с пина 1-й кнопки)
PIN_BT_2 = BUTT_2_PIN; // инверсия кнопок 1 и 2 при срабатывании реле (кнопка 2 считывается с пина 2-й кнопки)
} // инверсия кнопок 1 и 2 при срабатывании реле (конец цикла)
if (flag_reverse == 1) { // инверсия кнопок 1 и 2 при срабатывании реле (если реле "назад" - флаг 1)
PIN_BT_1 = BUTT_2_PIN; // инверсия кнопок 1 и 2 при срабатывании реле (кнопка 1 считывается с пина 2-й кнопки)
PIN_BT_2 = BUTT_1_PIN; // инверсия кнопок 1 и 2 при срабатывании реле (кнопка 2 считывается с пина 1-й кнопки)
} // инверсия кнопок 1 и 2 при срабатывании реле (конец цикла)
butt3 = !digitalRead(BUTT_3_PIN); // опрос кнопки 3
butt4 = !digitalRead(BUTT_4_PIN); // опрос кнопки 4
mode = constrain (mode, 1, 9); // диапазон количества режимов - от 1 до 9
// желтый свет прожектора
if (flag_reverse == 0) { // если реле "вперед" - флаг 0
digitalWrite(LED_1_PIN, 1); // желтый свет прожектора горит
digitalWrite(LED_2_PIN, 0); // красный свет прожектора не горит
}
// красный свет прожектора
if (flag_reverse == 1) { // если реле "вперед" - флаг 1
digitalWrite(LED_1_PIN, 0); // желтый свет прожектора не горит
digitalWrite(LED_2_PIN, 1); // красный свет прожектора горит
}
// вызов режимов 6-7-8-9
if (butt1 == 1 && butt_flag1 == 0 && millis() - last_press > DEBOUNCE) { // если кнопка 1 нажата и флаг кнопки 1 имеет значение 0
butt_flag1 = 1; // флаг кнопки 1 принимает значение 1
if (mode < 5) {mode = mode + 4;} // если счетчик режимов меньше 5, то режим = текущий режим + 4
mode++; // увеличивать счетчик режимов на 1
if (RPMdes < RPMdes_2 && RPMdes > RPMdes_1) {mode = 6;} // если RPMdes в диапазоне RPMdes_2 и RPMdes_1, то режим 6
if (RPMdes < RPMdes_3 && RPMdes >= RPMdes_2) {mode = 7;} // если RPMdes в диапазоне RPMdes_3 и RPMdes_2, то режим 7
if (RPMdes < RPMdes_4 && RPMdes >= RPMdes_3) {mode = 8;} // если RPMdes в диапазоне RPMdes_4 и RPMdes_3, то режим 8
if (RPMdes < RPMdes_5 && RPMdes >= RPMdes_4) {mode = 9;} // если RPMdes в диапазоне RPMdes_5 и RPMdes_4, то режим 9
if (mode > 9) mode = 9; // если счетчик режимов больше 9, то остается 9-й режим
Serial.print("---MODE---"); // вывести в порт значение текущего режима
Serial.print(mode); // вывести в порт значение текущего режима
Serial.println("---BTN_1---"); // вывести в порт значение текущего режима
// описание каждого режима 6-7-8-9
switch (mode){ // переключать режимы
case 6: { // режим имеет значение 6
for (RPMdes >= RPMdes_1; RPMdes < RPMdes_2; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_1 до RPMdes_2
CTR_1_UP();
goto label_2; // переход на метку 1-го режима
}
label_1: ; // метка 6-го режима
} // конец цикла режима 6
break; // обязательная команда для switch case
case 7: { // режим имеет значение 7
for (RPMdes >= RPMdes_2; RPMdes < RPMdes_3; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_2 до RPMdes_3
CTR_2_UP();
goto label_4; // переход на метку 2-го режима
}
label_3: ; // метка 7-го режима
} // конец цикла режима 7
break; // обязательная команда для switch case
case 8: { // режим имеет значение 8
for (RPMdes >= RPMdes_3; RPMdes < RPMdes_4; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_3 до RPMdes_4
CTR_3_UP();
goto label_6; // переход на метку 3-го режима
}
label_5: ; // метка 8-го режима
} // конец цикла режима 8
break; // обязательная команда для switch case
case 9: { // режим имеет значение 9
for (RPMdes >= RPMdes_4; RPMdes < RPMdes_5; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_4 до RPMdes_5
CTR_4_UP();
goto label_8; // переход на метку 4-го режима
}
label_7: ; // метка 9-го режима
} // конец цикла режима 9
break; // обязательная команда для switch case
} // конец цикла switch case переключения режимов 6-7-8-9
last_press = millis(); // сброс счетчика таймера антидребезга
} // конец цикла нажатия кнопки 1
if(butt1 == 0 && butt_flag1 == 1 && millis() - last_press > DEBOUNCE) { // если кнопка 1 отпущена и флаг кнопки имеет значение 1
butt_flag1 = 0; // флаг кнопки принимает значение 0
last_press = millis(); // сброс счетчика таймера антидребезга
} // конец цикла отпускания кнопки 1
// вызов режимов 4-3-2-1
if (butt2 == 1 && butt_flag2 == 0 && millis() - last_press > DEBOUNCE) { // если кнопка 2 нажата и флаг кнопки 1 имеет значение 0
butt_flag2 = 1; // флаг кнопки 2 принимает значение 1
if (mode > 5) {mode = mode - 4;} // если счетчик режимов больше 5, то режим = текущий режим - 4
mode--; // уменьшать счетчик режимов на 1
if (RPMdes <= RPMdes_5 && RPMdes > RPMdes_4) {mode = 4;} // если RPMdes в диапазоне RPMdes_5 и RPMdes_4, то режим 4
if (RPMdes <= RPMdes_4 && RPMdes > RPMdes_3) {mode = 3;} // если RPMdes в диапазоне RPMdes_4 и RPMdes_3, то режим 3
if (RPMdes <= RPMdes_3 && RPMdes > RPMdes_2) {mode = 2;} // если RPMdes в диапазоне RPMdes_3 и RPMdes_2, то режим 2
if (RPMdes <= RPMdes_2 && RPMdes >= RPMdes_1){mode = 1;} // если RPMdes в диапазоне RPMdes_2 и RPMdes_1, то режим 1
if (mode < 1) mode = 1; // если счетчик режимов меньше 1, то остается 1-й режим
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//------------------ПЕРЕКЛЮЧЕНИЕ-----РЕВЕРСА-------------------------------
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
if (RPMdes == RPMdes_1) { // если RPMdes соответствует RPMdes_1
flag_reverse = !flag_reverse; // флаг реле соответствует противоположному значению
digitalWrite(RELAY_PIN, flag_reverse); // на пин реле выводится текущее значение флага
Serial.println("<<<<< CHANGE REVERSER POSITION >>>>>"); // вывод в порт сообщения об изменении положения реле
goto label_1; // переход на метку 6-го режима
} // конец цикла
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
//-------------------------------------------------------------------------
Serial.print("---MODE---"); // вывести в порт значение текущего режима (обязательно после вывода положения реверса)
Serial.print(mode); // вывести в порт значение текущего режима (иначе при нажатии кнопки на переключение реверса)
Serial.println("---BTN_2---"); // вывести в порт значение текущего режима (будет одновременно выводится значение режима)
// описание каждого режима 1-2-3-4
switch(mode) {
case 4: { // режим имеет значение 4
for (RPMdes <= RPMdes_5; RPMdes > RPMdes_4; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_5 до RPMdes_4
CTR_3_DN();
goto label_7; // переход на метку 9-го режима
}
label_8: ; // метка 4-го режима
} // конец цикла режима 4
break; // обязательная команда для switch case
case 3: { // режим имеет значение 3
for (RPMdes <= RPMdes_4; RPMdes > RPMdes_3; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_4 до RPMdes_3
CTR_2_DN();
goto label_5; // переход на метку 8-го режима
}
label_6: ; // метка 3-го режима
} // конец цикла режима 3
break; // обязательная команда для switch case
case 2: { // режим имеет значение 2
for (RPMdes <= RPMdes_3; RPMdes > RPMdes_2; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_3 до RPMdes_2
CTR_1_DN();
goto label_3; // переход на метку 7-го режима
}
label_4: ; // метка 2-го режима
} // конец цикла режима 2
break; // обязательная команда для switch case
case 1: { // режим имеет значение 1
for (RPMdes <= RPMdes_2; RPMdes > RPMdes_1; RPMdes) { // выполняется в диапазоне значений RPMdes от RPMdes_2 до RPMdes_1
CTR_0_DN();
goto label_1; // переход на метку 6-го режима
}
label_2: ; // метка 1-го режима
} // конец цикла режима 1
break; // обязательная команда для switch case
} // конец цикла switch case переключения режимов 4-3-2-1
last_press = millis(); // сброс счетчика таймера антидребезга
} // конец цикла нажатия кнопки 2
if(butt2 == 0 && butt_flag2 == 1 && millis() - last_press > DEBOUNCE) { // если кнопка 2 отпущена и флаг кнопки имеет значение 1
butt_flag2 = 0; // флаг кнопки 2 принимает значение 0
last_press = millis(); // сброс счетчика таймера антидребезга
} // конец цикла отпускания кнопки 2
PID();
}