#include "GyverStepper.h" // инициализация библиотеки шагового двигателя
#include <LiquidCrystal.h> // инициализация LCD библиотеки
#define steps 1600 // 1600 - шагов на оборот с учетом деления шага
#define STEP 2
#define DIR 5
#define EN 8
GStepper< STEPPER2WIRE> stepper1(steps, STEP, DIR, EN); //Настройка портов для библиотеки шаговых двигателей
LiquidCrystal lcd(9, 10, 3, 4, 6, 7); // Пины смещены, что-бы не пересекатся с платой расширения для шаговика
// Имена кнопок клавиатуры на дисплее
#define btnUP 1
#define btnDOWN 2
#define btnLEFT 3
#define btnRIGHT 4
#define btnSELECT 5
#define btnNONE 10
// Условия разбивки одного порта на 5 кнопок
int detectButton() {
int keyAnalog = analogRead(A0);
if (keyAnalog < 100) {
// Значение меньше 100 – нажата кнопка right
return btnRIGHT;
} else if (keyAnalog < 200) {
// Значение больше 100 (иначе мы бы вошли в предыдущий блок результата сравнения, но меньше 200 – нажата кнопка UP
return btnUP;
} else if (keyAnalog < 400) {
// Значение больше 200, но меньше 400 – нажата кнопка DOWN
return btnDOWN;
} else if (keyAnalog < 600) {
// Значение больше 400, но меньше 600 – нажата кнопка LEFT
return btnLEFT;
} else if (keyAnalog < 800) {
// Значение больше 600, но меньше 800 – нажата кнопка SELECT
return btnSELECT;
} else {
// Все остальные значения (до 1023) будут означать, что нажатий не было
return btnNONE;
}
}
#define btnRST 11 // Присвоение имени и пина кнопке Reset
// Начальные значения коэффициентов
int SPS = 1600; // Начальное количество шагов в секунду
int SPSMin = 950; // Минимальные обороты двигателя
int SPSMax = 10000; // максимальные обороты двигателя
int AccelerationStepper = 30000; // ускорение двигателя
int revStepperSpeed = 10000; // Скорость реверса
int tempIn = 0; // Температура с датчика
int tempS = 320; // Начальная целевая температура
int tempMin = 20; // минимально устанавливаемая температура
int tempMax = 360; // максимально устанавливаемая температура
long posStepper = 2147483600; // крайняя позиция двигателя, после чего будет остановлен
// Флажки кнопок
boolean btnUP_flag = 0; // для задержки срабатывания кнопки UP
boolean btnDOWN_flag = 0; // для задержки срабатывания кнопки DOWN
boolean btnRIGHT_flag = 0; // для задержки срабатывания кнопки RIGHT
boolean btnLEFT_flag = 0; // для задержки срабатывания кнопки LEFT
boolean btnSELECT_flag = 0; // для задержки срабатывания кнопки SELECT
boolean btnRSTS; // храним состояния кнопок (S - State)
boolean btnRSTF; // флажки кнопок (F - Flag)
boolean btnRSTR; // флажки кнопок на отпускание (R - Release)
boolean btnRSTP; // флажки кнопок на нажатие (P - Press)
boolean btnRSTH; // флажки кнопок на удержание (многократный вызов) (H - Hold)
boolean btnRSTHO; // флажки кнопок на удержание (один вызов при нажатии) (HO - Hold Once)
boolean btnRSTD; // флажки кнопок на двойное нажатие (D - Double)
boolean btnRSTDP; // флажки кнопок на двойное нажатие и отпускание (D - Double Pressed)
unsigned long btnRST_timer; // таймер последнего нажатия кнопки
unsigned long btnRST_double; // таймер двойного нажатия кнопки
// Задержки кнопок
unsigned long button_timer; // Счетчик для замера времени удержания
// задержки кнопок
#define double_timer 150 // время (мс), отведённое на второе нажатие
#define hold 500 // время (мс), после которого кнопка считается зажатой
#define debounce 100 // (мс), антидребезг и уменьшение скорости набора
#define pause_timer 2000 // Долгое нажатие для переключения режима
// Скорости изменения коэффициентов
#define spsSpeed 100 // скорость изменения SPS (шагов в секунду)
#define tempSSpeed 1 // скорость изменения целевой температуры
boolean stopStepper = 0; // вкл и откл двигателя. в норме выключен при включении питания
boolean revStepper = 0; // Обратный ход шаговика
boolean stopTerm = 0; //вкл и откл нагревателя. в норме выключен при включении питания
void setup() {
pinMode (btnRST, INPUT); // режим кнопки Reset
pinMode(btnRST, INPUT_PULLUP);
// Для экрана
Serial.begin(9600);
lcd.begin(16, 2);
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
stepper1.setRunMode(KEEP_SPEED); // режим поддержания скорости
stepper1.setSpeed(666); //
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
}
void loop() {
Serial.print(SPS);
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
stepper1.tick();
// сделаем таймер на 50 мс и будем опрашивать потенциометр
// менять скорость чаще нет смысла
static uint32_t tmr2;
if (millis() - tmr2 > 50) {
tmr2 = millis();
// ставим новую скорость (-512.. 512 шагов в секунду)
// будет крутиться в разные стороны
stepper1.setSpeed(SPS);
stepper1.tick();
}
// ААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААААА
//-------опрос кнопок--------
btnRSTS = !digitalRead(btnRST);
buttons(); //отработка кнопок
//-------опрос кнопок--------
// отработка режимов (опускание флага обязательно!)
if (btnRSTP) {
Serial.println("pressed");
btnRSTP = 0;
}
if (btnRSTD) {
Serial.println("double");
btnRSTD = 0;
}
if (btnRSTH && btnRSTHO) {
Serial.println("hold once");
Serial.println(revStepper);
Serial.println(stopStepper);
btnRSTHO = 0;
}
// Отображение преременной SPS на экране
lcd.setCursor(0, 0);
lcd.print("SPS ");
lcd.print(SPS);
// Часть кода убирающая
if (SPS < 10) {
lcd.print(" ");
}
else if (SPS >= 10 && SPS < 100) {
lcd.print(" ");
}
else if (tempS >= 100 && tempS < 1000) {
lcd.print(" ");
}
// Отображение целевой температуры на нагревателе
lcd.setCursor(0, 1);
lcd.print("Ts ");
lcd.print(tempS);
if (tempS < 10) {
lcd.print(" ");
}
else if (tempS >= 10 && tempS < 100) {
lcd.print(" ");
}
// Отображение Текущей температуры с термистора
lcd.setCursor(7, 1);
lcd.print("T ");
lcd.print(tempIn);
if (tempS < 10) {
lcd.print(" ");
}
else if (tempS >= 10 && tempS < 100) {
lcd.print(" ");
}
// отбражение текущего режима двигателя
lcd.setCursor(13, 0);
if (stopStepper == 0 && revStepper == 0) {
lcd.print("off");}
if (revStepper == 1 && stopStepper == 0){
lcd.print("rev");}
else if (stopStepper == 1 && revStepper == 0){
lcd.print("on "); }
// отображение текущего состояния нагревателя
lcd.setCursor(13, 1);
if (stopTerm == 0) {
lcd.print("off");}
else if (stopTerm == 1){
lcd.print("on "); }
// Обработчик нажатий кнопок подключенных к пину А0. Необходим, т.к. подключено 5 кнопок к ожному пину
int button = detectButton();
switch (button) {
case btnUP:
if (btnUP_flag == 0 && millis() - button_timer > debounce && tempS < tempMax) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
{
tempS += tempSSpeed; // Увеличение Целевой температуры на величину tempSSpeed
btnUP_flag = 1;
button_timer = millis();
}
if (btnUP_flag == 1 && millis() - button_timer > debounce) //Благодаря этой части, код выполняется постоянно пока нажата кнопка
{
btnUP_flag = 0;
}
break;
case btnDOWN:
if (btnDOWN_flag == 0 && millis() - button_timer > debounce && tempS > tempMin) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
{
tempS -= tempSSpeed; // Уменьшение Целевой температуры на величину tempSSpeed
btnDOWN_flag = 1;
button_timer = millis();
}
if (btnDOWN_flag == 1 && millis() - button_timer > debounce)
{
btnDOWN_flag = 0;
}
break;
case btnLEFT:
if (btnLEFT_flag == 0 && millis() - button_timer > debounce && SPS > SPSMin) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
{
SPS -= spsSpeed; // уменьшение SPS (Скорости двигателя) на величину spsSpeed
btnLEFT_flag = 1;
button_timer = millis();
}
else if (btnLEFT_flag == 1 && millis() - button_timer > debounce) {
btnLEFT_flag = 0;
}
break;
case btnRIGHT:
if (btnRIGHT_flag == 0 && millis() - button_timer > debounce && SPS < SPSMax) // Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
{
SPS += spsSpeed; // увеличение SPS (Скорости двигателя) на величину spsSpeed
btnRIGHT_flag = 1;
button_timer = millis();
}
if (btnRIGHT_flag == 1 && millis() - button_timer > debounce)
{
btnRIGHT_flag = 0;
}
break;
case btnSELECT:
if (btnSELECT_flag == 0 && millis() - button_timer > pause_timer) /* Значекние button_timer задает скорость изменение переменной путем задержки между нажатиями
pause_timer - необходим доя медленной смены значений флажков, при малом значении сменяется слишком быстро*/
{
stopTerm = !stopTerm; // переключение состояния нагревателя
btnSELECT_flag = 1;
button_timer = millis();
}
if (btnSELECT_flag == 1 && millis() - button_timer > pause_timer)
{
btnSELECT_flag = 0;
}
break;
default:
//printDisplay("Press any key");
break;
}
}
// обрабортчик кнопки RST. делает одинарное/двойное/удержание
void buttons() {
//-------------------------btnRST--------------------------
// нажали (с антидребезгом)
if (btnRSTS && !btnRSTF && millis() - btnRST_timer > debounce) {
btnRSTF = 1;
btnRSTHO = 1;
btnRST_timer = millis();
}
// если отпустили до hold, считать отпущенной
if (!btnRSTS && btnRSTF && !btnRSTR && !btnRSTDP && millis() - btnRST_timer < hold) {
btnRSTR = 1;
btnRSTF = 0;
btnRST_double = millis();
}
// если отпустили и прошло больше double_timer, считать 1 нажатием
if (btnRSTR && !btnRSTDP && millis() - btnRST_double > double_timer) {
btnRSTR = 0;
btnRSTP = 1;
stopStepper = !stopStepper; // переключение состояния рабоы двигателя on/off
}
// если отпустили и прошло меньше double_timer и нажата снова, считать что нажата 2 раз
if (btnRSTF && !btnRSTDP && btnRSTR && millis() - btnRST_double < double_timer) {
btnRSTF = 0;
btnRSTR = 0;
btnRSTDP = 1;
}
// если была нажата 2 раз и отпущена, считать что была нажата 2 раза
if (btnRSTDP && millis() - btnRST_timer < hold) {
btnRSTDP = 0;
btnRSTD = 1;
btnRST_timer = millis();
revStepper = !revStepper; // переключение залипания реверса при двойном клике
}
// Если удерживается более hold, то считать удержанием
if (btnRSTF && !btnRSTD && !btnRSTH && millis() - btnRST_timer > hold) {
btnRSTH = 1;
revStepper = !revStepper; // Включение реверса при зажатой кнопке
}
// Если отпущена после hold, то считать, что была удержана
if (!btnRSTS && btnRSTF && millis() - btnRST_timer > hold) {
btnRSTF = 0;
btnRSTH = 0;
revStepper = !revStepper; // отключение удержания реверса при отпускании кнопки
btnRST_timer = millis();
}
}