#include <Wire.h> //Библиотека для работы с шиной I2C
#include <LiquidCrystal_I2C.h> //Библиотека управления дисплеем
#include <EEPROM.h> //Бибилиотека работы с сохранением параметров память микроконтроллера
#include <AccelStepper.h>
#define pin_StartV1 2
#define pin_StartV2 3
//Номера пинов подключения драйвер
#define pin_ENA 4 //Включение шагового двигателя
#define pin_DIR 5 //Направление вращения
#define pin_PUL 6 //Импульс для поворота на угол
#define STEPS 200 //Количество шагов у двигателя
//ПРИСВАЕВАЕМ АДРЕСА ПИНОВ ДЛЯ ЭНКОДЕРА
#define pinSW A0
#define pinCLK A1
#define pinDT A2
//АВАРИЙНАЯ ОСТАНОВКА
#define emergencyStop A3
//Пины управления сварочным аппаратом
#define pin_WeldingA 9
#define pin_WeldingB 10
//ПРИСВАЕВАЕМ ИМЯ ПИНУ РЕЖИМА РАБОТЫ
#define pin_ModeWork 8
//Номер пина кнопки переключения верхнего предела скорости
#define pinSetV 12
#define pinButton 11
//Запись скоростей, углов и прочее в память при первом запуске
#define INIT_ADR 1024
#define INIT_KEY 12
#define initxx 40
#define inityy 40
#define inita 0
#define initaa 60
#define initaaa 300
#define initb 0
#define initbb 60
#define initbbb 300
#define initRV1 1
#define initRV2 2
#define initDrStp 1
#define initReductor 1
#define initFlagOnCH1 1
#define initFlagOnCH2 0
#define initG 5
#define initGG 50
#define initGGG 300
LiquidCrystal_I2C lcd(0x27,16,2); // Устанавливаем дисплей
/*#######################################################*/
AccelStepper stepper(1, pin_PUL, pin_DIR);
/*#######################################################*/
//ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
byte k_DrvrSteps; // 1:1 k=1; 1:2 k = 2 ; 1:4 k = 4; 1:8 k = 8; 1:16 k = 16;
byte k_Reductor;
int16_t rotorPos;
uint16_t setSpeed;
float Speed;
float Accel;
int16_t Angle;
boolean flagStartSystem = true;
volatile boolean flagModeSetVal;
volatile boolean flagModeWork;
boolean flagHideCursor = true;
boolean flagOnCH1;
boolean flagOnCH2;
byte item_M; //Пункт указателя выбора скоростей для изменения
byte item_RV1; //Пункт указателя направления вращения для скорости 2
byte item_RV2; //Пункт указателя направления вращения для скорости 1
byte index_V1; // Индекс выбора разряда для скорости 1
byte index_V2; // Индекс выбора разряда для скорости 2
byte index_A; // Индекс выбора разряда для угла поворота 1
byte index_B; // Индекс выбора разряда для угла поворота 2
byte index_G; //
/********************************************/
float x; //Дробная часть разрядов скорости 1
float y; //Дробная часть разрядов скорости 2
byte xx; //Величины разрядов для скорости 1
byte yy; //Величины разрядов для скорости 2
const float initx = 0.5;
const float inity = 0.5;
/*********************************************/
int16_t a, aa, aaa; //величины разрядов для угла поворота 1
int16_t b, bb, bbb; //величины разрядов для угла поворота 2
int16_t g, gg, ggg; //Величины разрядов для скорости шлифования
uint32_t timer; // Таймер времени
int16_t angleA; //Угол поворота 1
int16_t angleB; //Угол поворота 2
const int16_t maxA = 720; //Максимальный угол поворота 1
const int16_t minA = 0;//Минимальный угол поворота 1
const int16_t maxB = 720; //Максимальный угол поворота 2
const int16_t minB = 0; //Минимальный угол поворота 2
const int16_t maxG = 500; //Максимальная скорость шлифования
const int16_t minG = 0; //Минимальная скорость шлифования
/********************************************/
//float valV1; // Переменная скорости 1
//float valV2; // Переменная скорости 2
const float maxV1 = 99.9; //Переменная верхнего предела скорости 1
const float minV1 = 0.0; //Переменная нижнего предела скорости 1
const uint16_t maxV2 = 255; //Переменная верхнего предела скорости 2
const uint16_t minV2 = 0; //Переменная нижнего предела скорости 2
boolean flagV1 = true; //Флаг мигания выбранного разряда скорости 1
boolean flagV2 = true; //Флаг мигания выбранного разряда скорости 2
/*********************************************/
boolean flagA = true; //Флаг мигания выбранного разряда угла поворота 1
boolean flagB = true; //Флаг мигания выбранного разряда угла поворота 2
/*********************************************/
boolean flagG = true; //Флаг мигания выбранного рзряда скорости шлифования
//ПЕРЕМЕННЫЕ ДЛЯ РАБОТЫ ЭНКОДЕРА ПО ВНЕШНЕМУ ПРЕРЫВАНИЮ
volatile byte seqA = 0;
volatile byte seqB = 0;
volatile int16_t cnt1 = 0;
volatile boolean button = false;
volatile boolean flagItem_M = false;
//Флаг аварийной остановки.
volatile boolean flagEmerStop = false;
byte setChar[] = {B11000, B10100, B10010, B10001, B10001, B10010, B10100, B11000};
byte setFullChar[] = {B11000, B11100, B11110, B11111, B11111, B11110, B11100, B11000};
byte setCharRotateClock[] = {B00100, B01110, B11111, B00100, B00100, B00100, B01110, B11111};
byte setCharRotateAntiClock[] = {B11111, B01110, B00100, B00100, B00100, B11111, B01110, B00100};
byte setOnChar[] = {B01000,
B10100,
B10100,
B01000,
B00101,
B00110,
B00101,
B00101};
byte setNoChar[] = {B00000,
B00000,
B00000,
B00000,
B11011,
B10010,
B11011,
B10010};
//КОД ВЫПОЛНЯЕТСЯ ТОЛЬКО ПРИ ЗАПУСКЕ
void setup() {
Serial.begin(9600);
//ЗАДАЕМ РЕЖИМ РАБОТЫ ПИНАМ ЭНКОДЕРА
pinMode(pinCLK, INPUT_PULLUP);
pinMode(pinDT, INPUT_PULLUP);
pinMode(pinSW, INPUT_PULLUP);
//Пины кнопок
pinMode(emergencyStop, INPUT_PULLUP);
//pinMode(pinButtonRotate, INPUT_PULLUP);
pinMode(pinSetV, INPUT_PULLUP);
pinMode(pinButton, INPUT_PULLUP);
pinMode(pin_StartV1, INPUT_PULLUP);
pinMode(pin_StartV2, INPUT_PULLUP);
//Пины подключения драйвера
pinMode (pin_PUL, OUTPUT);
pinMode (pin_DIR, OUTPUT);
pinMode (pin_ENA, OUTPUT);
//pinMode (pin_ModeSetVal, INPUT_PULLUP);
pinMode (pin_ModeWork, INPUT_PULLUP);
pinMode(pin_WeldingA, OUTPUT);
pinMode(pin_WeldingB, OUTPUT);
// Включить внутренние подтягивающие резисторы
digitalWrite(A0, HIGH);
digitalWrite(A1, HIGH);
digitalWrite(A2, HIGH);
//digitalWrite(A3, HIGH);
PCICR = 0b00000010; // 1. PCIE1: Включить прерывание 1 по изменению состояния
PCMSK1 = 0b00001111; // Включить прерывание по изменению состояния для A0, A1, A2, A3
//Проверка режима работы при старте системы
timer = millis();
// Первый запуск
if (EEPROM.read(INIT_ADR) != INIT_KEY){
EEPROM.write(INIT_ADR, INIT_KEY);
EEPROM.put(0, initx);
EEPROM.put(4, initxx);
EEPROM.put(12, inity);
EEPROM.put(16, inityy);
EEPROM.put(24, inita);
EEPROM.put(28, initaa);
EEPROM.put(32, initaaa);
EEPROM.put(36, initb);
EEPROM.put(40, initbb);
EEPROM.put(44, initbbb);
EEPROM.put(48, initRV1);
EEPROM.put(52, initRV2);
EEPROM.put(56, initDrStp);
EEPROM.put(60, initReductor);
EEPROM.put(64, initFlagOnCH1);
EEPROM.put(68, initFlagOnCH2);
EEPROM.put(72, initG);
EEPROM.put(76, initGG);
EEPROM.put(80, initGGG);
}
// Чтение сохраненных данных
EEPROM.get(0, x);
EEPROM.get(4, xx);
EEPROM.get(12, y);
EEPROM.get(16, yy);
EEPROM.get(24, a);
EEPROM.get(28, aa);
EEPROM.get(32, aaa);
EEPROM.get(36, b);
EEPROM.get(40, bb);
EEPROM.get(44, bbb);
EEPROM.get(48, item_RV1);
EEPROM.get(52, item_RV2);
EEPROM.get(56, k_DrvrSteps);
EEPROM.get(60, k_Reductor);
EEPROM.get(64, flagOnCH1);
EEPROM.get(68, flagOnCH2);
EEPROM.get(72, g);
EEPROM.get(76, gg);
EEPROM.get(80, ggg);
angleA = aaa + aa + a;
angleB = bbb + bb + b;
index_V1 = 3;
index_V2 = 3;
index_A = 4;
index_B = 4;
index_G = 4;
item_M = 1;
lcd.init();
lcd.backlight();// Включаем подсветку дисплея
lcd.createChar(0, setChar);
lcd.createChar(1, setFullChar);
lcd.createChar(2, setCharRotateClock);
lcd.createChar(3, setCharRotateAntiClock);
lcd.createChar(4, setOnChar);
lcd.createChar(5, setNoChar);
start_setup_menu();
init_main_menu_lcd();
}//END SETUP
///////////////////////////////////////////
// ГЛАВНЫЙ ЦИКЛ ПРОГРАММЫ //
///////////////////////////////////////////
void loop() {
if (!digitalRead(pin_ModeWork) && index_V1 == 3 && index_V2 == 3 && index_A == 4 && index_B == 4){
flagModeWork = true;
flagModeSetVal = false;
flagEmerStop = false;
}else{
flagModeWork = false;
flagModeSetVal = true;
flagHideCursor = true;
flagEmerStop = true;
}
//Режим настройки и вывода информации на дисплей
if (flagModeSetVal == true){
if (!digitalRead(pinButton)){
if (millis() - timer >= 550){
flagItem_M = true;
timer = millis();
}
}
setMenu();
setMenuLevel();
setRotateWay();
if (item_M == 1 || item_M == 2){
editSpeedUp();
editSpeedDown();
}
if (item_M == 3 || item_M == 4){
editAngleUp();
editAngleDown();
}
pressButtonToSetup();
}
//Режим выполнения вращения двигателя
if (flagModeWork == true){
if (flagHideCursor == true){
flagHideCursor = false;
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(8, 0);
lcd.print(" ");
lcd.setCursor(8, 1);
lcd.print(" ");
lcd.setCursor(13, 0);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.print(" ");
}
if (!digitalRead(pin_StartV1) && flagOnCH1 == true){
if (millis() - timer >= 350){
//Serial.println(item_RV1);
calcAngle(aaa, aa, a, item_RV1);
calcSpeed(xx, x, item_RV1);
stepper.setMaxSpeed(Accel);
stepper.setSpeed(Speed);
if (flagEmerStop == false){
digitalWrite(pin_WeldingA, HIGH);
motorMove(item_RV1);
}
}
}
if (!digitalRead(pin_StartV2) && flagOnCH2 == true){
if (millis() - timer >= 350){
//Serial.println(item_RV2);
calcAngle(bbb, bb, b, item_RV2);
calcSpeed(yy, y, item_RV2);
stepper.setMaxSpeed(Accel);
stepper.setSpeed(Speed);
if (flagEmerStop == false){
digitalWrite(pin_WeldingB, HIGH);
motorMove(item_RV2);
}
}
}
}
}//END LOOP
void start_setup_menu(){
lcd.setCursor(0, 0);
lcd.print("PRESS 'STOP'");
lcd.setCursor(0, 1);
lcd.print("FOR SETUP");
timer = millis();
static const uint16_t timeDelaySetup = 3000;
while (millis()-timer <= timeDelaySetup){
if (!digitalRead(emergencyStop)){
if (millis() - timer >= 350){
lcd.clear();
setupMenu();
}
}else{
lcd.setCursor(14, 1);
lcd.print((timeDelaySetup+1000-millis()+timer)/1000 );
lcd.setCursor(15, 1);
lcd.print("c");
}
}
timer = millis();
flagEmerStop = false;
lcd.clear();
}
//#######################################
// Вывод на дисплей после запуска
//#######################################
void init_main_menu_lcd(){
lcd.setCursor(1, 0);
lcd.print("V1=");
lcd.setCursor(4, 0);
lcdSpeedDisplayV1();
lcd.setCursor(1, 1);
lcd.print("V2=");
lcd.setCursor(4, 1);
lcdSpeedDisplayV2();
//lcd.setCursor(14,0);
//lcd.print("R");
//lcd.setCursor(14,1);
//lcd.print("R");
lcd.setCursor(9, 0);
lcd.print("A");
lcdAngleDisplayA();
lcd.setCursor(9, 1);
lcd.print("B");
lcdAngleDisplayB();
setRotateWay();
lcd.setCursor(15, 0);
if (flagOnCH1 == true){lcd.write(4);}else{lcd.write(5);}
lcd.setCursor(15, 1);
if (flagOnCH2 == true){lcd.write(4);}else{lcd.write(5);}
}
//############################################################################################
// ГЛАВНОЕ МЕНЮ (осуществляется перестановка указателя пункта меню)
//############################################################################################
void setMenu(){
if (flagItem_M && index_V1 == 3 && index_V2 == 3 && index_A == 4 && index_B == 4){
//if (millis()-timer >=350){
item_M++;
if (item_M > 6){item_M = 1;}
flagItem_M = false;
//timer = millis();
//}
}else{
flagItem_M = false;
}
switch (item_M) {
case 1:
if (index_V1 == 3){
lcd.setCursor(0, 0);
lcd.write(1);
}else{
lcd.setCursor(0, 0);
lcd.write(0);
}
lcd.setCursor(13, 1);
lcd.print(" ");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(" ");
if (index_V2 == 3){
lcd.setCursor(0, 1);
lcd.write(1);
}else{
lcd.setCursor(0, 1);
lcd.write(0);
}
break;
case 3:
lcd.setCursor(0, 1);
lcd.print(" ");
if (index_A == 4){
lcd.setCursor(8, 0);
lcd.write(1);
}else{
lcd.setCursor(8, 0);
lcd.write(0);
}
break;
case 4:
lcd.setCursor(8, 0);
lcd.print(" ");
if (index_B == 4){
lcd.setCursor(8, 1);
lcd.write(1);
}else{
lcd.setCursor(8, 1);
lcd.write(0);
}
break;
case 5:
lcd.setCursor(8, 1);
lcd.print(" ");
lcd.setCursor(13, 0);
lcd.write(1);
break;
case 6:
lcd.setCursor(13, 0);
lcd.print(" ");
lcd.setCursor(13, 1);
lcd.write(1);
}
}
//########################################
//МЕНЮ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
//########################################
void setRotateWay(){
if (item_M == 5){
if(cnt1 > 0){item_RV1++; cnt1 =0;}
if(cnt1 < 0){item_RV1--; cnt1 =0;}
if (item_RV1 > 2){item_RV1 = 1;}
if (item_RV1 == 0){item_RV1 = 2;}
}
if (item_M == 6){
if(cnt1 > 0){item_RV2++; cnt1 =0;}
if(cnt1 < 0){item_RV2--; cnt1 =0;}
if (item_RV2 > 2){item_RV2 = 1;}
if (item_RV2 == 0){item_RV2 = 2;}
}
switch (item_RV1){
case 1: //Если вращение по часовой стрелке
lcd.setCursor(14, 0);
lcd.write(2);
break;
case 2: //Если вращение против часовой стрелки
lcd.setCursor(14, 0);
lcd.write(3);
break;
}
switch (item_RV2){
case 1: //Если вращение по часовой стрелке
lcd.setCursor(14, 1);
lcd.write(2);
break;
case 2: //Если вращение против часовой стрелки
lcd.setCursor(14, 1);
lcd.write(3);
break;
}
}//END VOID
//#################################################
//ВЫБОР ИЗМЕНЯЕМЫХ РАЗРЯДОВ СКОРОСТЕЙ
//#################################################
void setMenuLevel(){
static uint32_t tmr = millis();
if (!digitalRead(pinSetV)){
if (millis()-tmr >=350){
tmr = millis();
if (item_M == 1){index_V1++; if (index_V1 > 3){index_V1 = 1;}}
if (item_M == 2){index_V2++; if (index_V2 > 3){index_V2 = 1;}}
if (item_M == 3){index_A++; if (index_A > 4){index_A = 1;}}
if (item_M == 4){index_B++; if (index_B > 4){index_B = 1;}}
}
}
}//END VOID
//#############################################################
//ИЗМЕНЯЕМ СКОРОСТЬ 1 ПОВОРОТОМ ЕНКОДЕРА ВЫВОДИМ НА ДИСПЛЕЙ
//#############################################################
void editSpeedUp(){
if (cnt1 > 0) {
if (item_M==1){
setValueSpeed(index_V1, x, xx, maxV1, minV1);
timer = millis();
}
if (item_M==2){
setValueSpeed(index_V2, y, yy, maxV2, minV2);
timer = millis();
}
cnt1 =0;
}
if (millis() - timer >= 1500 && millis() - timer <= 1600){
saveSpeedMemory();
}
lcdSpeedDisplayV1();
lcdSpeedDisplayV2();
}
//#############################################
//ИЗМЕНЯЕМ СКОРОСТЬ 2 ПОВОРОТОМ ЕНКОДЕРА
//#############################################
void editSpeedDown(){
if (cnt1 < 0) {
if (item_M == 1){
setValueSpeed(index_V1, x, xx, maxV1, minV1);
timer = millis();
}
if (item_M == 2){
setValueSpeed(index_V2, y, yy, maxV2, minV2);
timer = millis();
}
cnt1 =0;
}
if (millis() - timer >= 1500 && millis() - timer <= 1600){
saveSpeedMemory();
}
lcdSpeedDisplayV1();
lcdSpeedDisplayV2();
}
//#########################################
//Вывод на дисплей значения скорости 1
//#########################################
void lcdSpeedDisplayV1(){
static byte interval = 200; //Интервал мигания разряда
static uint32_t timeNew = 0; //Время текущее для отсчета мигания разряда
static uint32_t timeOld = 0; //Время предыдущее для отсчета мигания разряда
if (item_M == 1){
timeNew = millis();
}
if (timeNew - timeOld >= interval){
flagV1 = !flagV1;
timeOld = timeNew;
}
if (index_V1 == 2){
if (flagV1){
lcd.setCursor(4, 0);
lcd.print(" ");
}else{
if (xx>=10){
lcd.setCursor(4, 0);
}else{
lcd.setCursor(4, 0);
lcd.print("0");
lcd.setCursor(5, 0);
}
lcd.print(xx);
}
lcd.setCursor(7, 0);
lcd.print(x*10, 0);
lcd.setCursor(6, 0);
lcd.print(".");
}
if (index_V1 == 1){
if (xx>=10){
lcd.setCursor(4, 0);
}else{
lcd.setCursor(4, 0);
lcd.print("0");
lcd.setCursor(5, 0);
}
lcd.print(xx);
lcd.setCursor(6, 0);
lcd.print(".");
if (flagV1){
lcd.setCursor(7, 0);
lcd.print(" ");
}else{
lcd.setCursor(7, 0);
lcd.print(x*10, 0);
}
}
if (index_V1 == 3){
if (xx>=10){
lcd.setCursor(4, 0);
}else{
lcd.setCursor(4, 0);
lcd.print("0");
lcd.setCursor(5, 0);
}
lcd.print(xx);
lcd.setCursor(7, 0);
lcd.print(x*10, 0);
lcd.setCursor(6, 0);
lcd.print(".");
}
}
//##########################################
//Вывод на дисплей значения скорости 2
//##########################################
void lcdSpeedDisplayV2(){
static byte interval = 200; //Интервал мигания разряда
static uint32_t timeNew = 0; //Время текущее для отсчета мигания разряда
static uint32_t timeOld = 0; //Время предыдущее для отсчета мигания разряда
if (item_M == 2){
timeNew = millis();
}
if (timeNew -timeOld >= interval){
timeOld = timeNew;
flagV2 = !flagV2;
}
if (index_V2 == 2) {
if (flagV2){
lcd.setCursor(4, 1);
lcd.print(" ");
}else{
if (yy>=10){
lcd.setCursor(4, 1);
}else{
lcd.setCursor(4, 1);
lcd.print("0");
lcd.setCursor(5, 1);
}
lcd.print(yy);
}
lcd.setCursor(7, 1);
lcd.print(y*10, 0);
lcd.setCursor(6, 1);
lcd.print(".");
}
if (index_V2 == 1){
if (yy>=10){
lcd.setCursor(4, 1);
}else{
lcd.setCursor(4, 1);
lcd.print("0");
lcd.setCursor(5, 1);
}
lcd.print(yy);
lcd.setCursor(6, 1);
lcd.print(".");
if (flagV2){
lcd.setCursor(7, 1);
lcd.print(" ");
}else{
lcd.setCursor(7, 1);
lcd.print(y*10, 0);
}
}
if (index_V2 == 3){
if (yy>=10){
lcd.setCursor(4, 1);
}else{
lcd.setCursor(5, 1);
lcd.setCursor(4, 1);
lcd.print("0");
}
lcd.print(yy);
lcd.setCursor(7, 1);
lcd.print(y*10, 0);
lcd.setCursor(6, 1);
lcd.print(".");
}
}
//#############################################
//ИЗМЕНЯЕМ УГОЛ ПОВОРОТА 1 ПОВОРОТОМ ЕНКОДЕРА
//#############################################
void editAngleUp(){
if (cnt1 > 0) {
if (item_M == 3){
setValue(index_A, a, aa, aaa, maxA, minA);
timer = millis();
}
if (item_M==4){
setValue(index_B, b, bb, bbb, maxB, minB);
timer = millis();
}
cnt1 =0;
}
if (millis() - timer == 1500 && millis() - timer <= 1700){
saveAngleMemory();
}
lcdAngleDisplayA();
lcdAngleDisplayB();
}
//################################################
//ИЗМЕНЯЕМ УГОЛ ПОВОРОТА 2 ПОВОРОТОМ ЕНКОДЕРА
//################################################
void editAngleDown(){
if (cnt1 < 0) {
if (item_M== 3){
setValue(index_A, a, aa, aaa, maxA, minA);
timer = millis();
}
if (item_M== 4){
setValue(index_B, b, bb, bbb, maxB, minB);
timer = millis();
}
cnt1 =0;
}
if (millis() - timer == 1500 && millis() - timer <= 1700){
saveAngleMemory();
}
lcdAngleDisplayA();
lcdAngleDisplayB();
}
//############################################
//Вывод значения угла поворота 1 на дисплей
//############################################
void lcdAngleDisplayA(){
static byte interval = 200; //Интервал мигания разряда
static uint32_t timeNew = 0; //Время текущее для отсчета мигания разряда
static uint32_t timeOld = 0; //Время предыдущее для отсчета мигания разряда
if (item_M == 3){
timeNew = millis();
}
if (timeNew - timeOld >= interval){
flagA = !flagA;
timeOld = timeNew;
}
if (index_A == 3){
if (flagA){
lcd.setCursor(10, 0);
lcd.print(" ");
}else{
lcd.setCursor(10, 0);
lcd.print(aaa/100);
}
lcd.setCursor(11, 0);
lcd.print(aa/10);
lcd.setCursor(12, 0);
lcd.print(a);
}
if (index_A == 2){
lcd.setCursor(10, 0);
lcd.print(aaa/100);
if (flagA){
lcd.setCursor(11, 0);
lcd.print(" ");
}else{
lcd.setCursor(11, 0);
lcd.print(aa/10);
}
lcd.setCursor(12, 0);
lcd.print(a);
}
if (index_A == 1){
lcd.setCursor(10, 0);
lcd.print(aaa/100);
lcd.setCursor(11, 0);
lcd.print(aa/10);
if (flagA){
lcd.setCursor(12, 0);
lcd.print(" ");
}else{
lcd.setCursor(12, 0);
lcd.print(a);
}
}
if (index_A == 4){
lcd.setCursor(10, 0);
lcd.print(aaa/100);
lcd.setCursor(11, 0);
lcd.print(aa/10);
lcd.setCursor(12, 0);
lcd.print(a);
}
}
//###########################################
//Вывод на дисплей значения угла поворота 2
//###########################################
void lcdAngleDisplayB(){
static byte interval = 200; //Интервал мигания разряда
static uint32_t timeNew = 0; //Время текущее для отсчета мигания разряда
static uint32_t timeOld = 0; //Время предыдущее для отсчета мигания разряда
if (item_M == 4){
timeNew = millis();
}
if (timeNew -timeOld >= interval){
timeOld = timeNew;
flagB = !flagB;
}
if (index_B == 3){
if (flagB){
lcd.setCursor(10, 1);
lcd.print(" ");
}else{
lcd.setCursor(10, 1);
lcd.print(bbb/100);
}
lcd.setCursor(11, 1);
lcd.print(bb/10);
lcd.setCursor(12, 1);
lcd.print(b);
}
if (index_B == 2) {
lcd.setCursor(10, 1);
lcd.print(bbb/100);
if (flagB){
lcd.setCursor(11, 1);
lcd.print(" ");
}else{
lcd.setCursor(11, 1);
lcd.print(bb/10);
}
lcd.setCursor(12, 1);
lcd.print(b);
}
if (index_B == 1){
lcd.setCursor(10, 1);
lcd.print(bbb/100);
lcd.setCursor(11, 1);
lcd.print(bb/10);
if (flagB){
lcd.setCursor(12, 1);
lcd.print(" ");
}else{
lcd.setCursor(12, 1);
lcd.print(b);
}
}
if (index_B == 4){
lcd.setCursor(10, 1);
lcd.print(bbb/100);
lcd.setCursor(11, 1);
lcd.print(bb/10);
lcd.setCursor(12, 1);
lcd.print(b);
}
}
//#####################################################
// Вывод на дисплей изменяемой скорости в меню настроек
//#####################################################
void lcdGrindSpeedDisplay(byte item_G){
static byte interval = 200; //Интервал мигания разряда
static uint32_t timeNew = 0; //Время текущее для отсчета мигания разряда
static uint32_t timeOld = 0; //Время предыдущее для отсчета мигания разряда
if (item_G == 1){
timeNew = millis();
}
if (timeNew - timeOld >= interval){
flagG = !flagG;
timeOld = timeNew;
}
if (index_G == 3){
if (flagG){
lcd.setCursor(7, 1);
lcd.print(" ");
}else{
lcd.setCursor(7, 1);
lcd.print(ggg/100);
}
lcd.setCursor(8, 1);
lcd.print(gg/10);
lcd.setCursor(9, 1);
lcd.print(g);
}
if (index_G == 2){
lcd.setCursor(7, 1);
lcd.print(ggg/100);
if (flagG){
lcd.setCursor(8, 1);
lcd.print(" ");
}else{
lcd.setCursor(8, 1);
lcd.print(gg/10);
}
lcd.setCursor(9, 1);
lcd.print(g);
}
if (index_G == 1){
lcd.setCursor(7, 1);
lcd.print(ggg/100);
lcd.setCursor(8, 1);
lcd.print(gg/10);
if (flagG){
lcd.setCursor(9, 1);
lcd.print(" ");
}else{
lcd.setCursor(9, 1);
lcd.print(g);
}
}
if (index_G == 4){
lcd.setCursor(7, 1);
lcd.print(ggg/100);
lcd.setCursor(8, 1);
lcd.print(gg/10);
lcd.setCursor(9, 1);
lcd.print(g);
}
}
void setValueSpeed(byte index, float& v, byte& vv, float maxV, float minV) {
if (cnt1 > 0){
if (index == 1){
if (v+0.1f < 0.9f && (float)(vv+v) < maxV){
v = v+0.1f;
}else{
v = 0.0;
}
}
if(index == 2){
if (vv + 1 < (maxV - v)){
vv = vv + 1;
}else{
vv = 99;
}
}
if (index == 3){
if (vv+v <= maxV){
v = v+0.1f;
if (v >= 1.0 && (vv+v) < maxV){
v = 0;
vv = vv + 1;
}
if (vv >= (maxV - v)){
vv = maxV - v;
}
}
}
}
if (cnt1 < 0){
if (index == 1){
if (v-0.1f >= 0 && (float)(vv+v - 0.1f) >= minV){
v = v-0.1f;
}else{
if(vv+0.9f <= maxV){v=0.9f;}else{
if(vv+0.8f <= maxV){v=0.8f;}else{
if(vv+0.7f <= maxV){v=0.7f;}else{
if(vv+0.6f <= maxV){v=0.6f;}else{
if(vv+0.5f <= maxV){v=0.5f;}else{
if(vv+0.4f <= maxV){v=0.4f;}else{
if(vv+0.3f <= maxV){v=0.3f;}else{
if(vv+0.2f <= maxV){v=0.2f;}else{
if(vv+0.1f <= maxV){v=0.1f;}else{
if(vv <= maxV){v = 0;}
}
}
}
}
}
}
}
}
}
}
}
if(index == 2){
if (vv - 1 >= 0 && (vv+v - 1) > minV){
vv = vv - 1;
}
if(vv <= minV){
vv = minV;
}
}
if (index == 3){
if ((vv+v) > minV){
v = v-0.1f;
if (v < 0 && (float)(vv+v) > minV){
v = 0.9;
vv = vv - 1;
}
if (vv <= minV && (vv+v) < minV){
vv = minV;
}
}
}
}
}
//ФУНКЦИЯ ИЗМЕНЕНИЯ ПАРАМЕТРОВ УГЛОВ
void setValue(byte index, int& p, int& pp, int& ppp, int maxVal, int minVal){
//Увеличиваем параметр
if (cnt1 > 0){
if (index == 1){
if (p+1 < 10 && ppp+pp+p < maxVal){
p = p+1;
}else{
p = 0;
}
}
if(index == 2){
if (pp + 10 < 100 && ppp+pp+p + 10 < maxVal){
pp = pp + 10;
}else{
pp = 0;
}
}
if (index == 3){
if (ppp + 100 < maxVal-pp-p && ppp+pp+p + 100 < maxVal){
ppp = ppp + 100;
}else{
ppp = 0;
}
}
if (index == 4){
if (ppp+pp+p < maxVal){
p = p+1;
if (p >= 10 && ppp+pp+p < maxVal){
p = 0;
pp = pp + 10;
}
if (pp >= 100 && ppp+pp+p < maxVal){
pp = 0;
ppp = ppp + 100;
}
if (ppp >= maxVal && ppp+pp+p < maxVal){
ppp = maxVal - pp -p;
}
}
}
timer = millis();
}
//Уменьшаем параметр
if (cnt1 < 0){
if (index == 1){
if (p-1 >= 0 && ppp+pp+p - 1 >= minVal){
p = p-1;
}else{
if(ppp+pp+9 <= maxVal){p=9;}else{
if(ppp+pp+8 <= maxVal){p=8;}else{
if(ppp+pp+7 <= maxVal){p=7;}else{
if(ppp+pp+6 <= maxVal){p=6;}else{
if(ppp+pp+5 <= maxVal){p=5;}else{
if(ppp+pp+4 <= maxVal){p=4;}else{
if(ppp+pp+3 <= maxVal){p=3;}else{
if(ppp+pp+2 <= maxVal){p=2;}else{
if(ppp+pp+1 <= maxVal){p=1;}else{
if(ppp+pp <= maxVal){p=0;}
}
}
}
}
}
}
}
}
}
}
}
if(index == 2){
if (pp - 10 >= 0 && ppp+pp+p - 10 >= minVal){
pp = pp - 10;
}else{
if(ppp+p+90 <= maxVal){pp=90;}else{
if(ppp+p+80 <= maxVal){pp=80;}else{
if(ppp+p+70 <= maxVal){pp=70;}else{
if(ppp+p+60 <= maxVal){pp=60;}else{
if(ppp+p+50 <= maxVal){pp=50;}else{
if(ppp+p+40 <= maxVal){pp=40;}else{
if(ppp+p+30 <= maxVal){pp=30;}else{
if(ppp+p+20 <= maxVal){pp=20;}else{
if(ppp+p+10 <= maxVal){pp=10;}else{
if(ppp+p <= maxVal){pp=0;}
}
}
}
}
}
}
}
}
}
}
}
if (index == 3){
if (ppp - 100 >= minVal && ppp+pp+p - 100 >= minVal){
ppp = ppp - 100;
}else{
if(pp+p+900 <= maxVal){ppp=900;}else{
if(pp+p+800 <= maxVal){ppp=800;}else{
if(pp+p+700 <= maxVal){ppp=700;}else{
if(pp+p+600 <= maxVal){ppp=600;}else{
if(pp+p+500 <= maxVal){ppp=500;}else{
if(pp+p+400 <= maxVal){ppp=400;}else{
if(pp+p+300 <= maxVal){ppp=300;}else{
if(pp+p+200 <= maxVal){ppp=200;}else{
if(pp+p+100 <= maxVal){ppp=100;}else{
if(pp+p <= maxVal){ppp=0;}
}
}
}
}
}
}
}
}
}
}
}
if (index == 4){
if (ppp+pp+p > minVal){
p = p-1;
if (p < 0 && ppp+pp+p > minVal){
p = 9;
pp = pp - 10;
}
if (pp < 0 && ppp+pp+p > minVal){
pp = 90;
ppp = ppp - 100;
}
if (ppp <= minVal && ppp+pp+p > minVal){
ppp = 0;
}
}
}
timer = millis();
}
}
void saveSetupMemory(){
EEPROM.put(56, k_DrvrSteps);
EEPROM.put(60, k_Reductor);
EEPROM.put(64, flagOnCH1);
EEPROM.put(68, flagOnCH2);
EEPROM.put(72, g);
EEPROM.put(76, gg);
EEPROM.put(80, ggg);
}
//СОХРАНЕНИЕ ПАРАМЕТРОВ СКОРОСТЕЙ
void saveSpeedMemory(){
EEPROM.put(0, x);
EEPROM.put(4, xx);
EEPROM.put(12, y);
EEPROM.put(16, yy);
//Serial.print(millis()/1000);
}
//СОХРАНЕНИЕ ПАРАМЕТРОВ УГЛОВ
void saveAngleMemory(){
EEPROM.put(24, a);
EEPROM.put(28, aa);
EEPROM.put(32, aaa);
EEPROM.put(36, b);
EEPROM.put(40, bbb);
EEPROM.put(44, bbb);
//Serial.print(millis()/1000);
}
/*##########################################################################*/
// ВРАЩЕНИЕ ДВИГАТЕЛЯ с использованием библиотеки <AccelStepper.h> //
/*##########################################################################*/
//РАСЧЕТ СКОРОСТИ И УСКОРЕНИЯ В ШАГАХ
void calcSpeed(uint16_t ss, float s, byte item){
if (Angle > 0){
Speed = (float)STEPS*k_DrvrSteps*k_Reductor*(ss+s)/60;
Accel = (float)STEPS*k_DrvrSteps*k_Reductor*(ss+s)/60;
}else{
Speed = (float)STEPS*k_DrvrSteps*k_Reductor*(ggg+gg+g)*k_DrvrSteps/60;
Accel = (float)STEPS*k_DrvrSteps*k_Reductor*(ggg+gg+g)/60;
}
if(item == 2){Speed = -Speed; /*Accel = -Accel;*/};
Serial.println(" ");
Serial.println(" ");
Serial.print("REDUCTION = ");
Serial.println(k_Reductor);
Serial.print("DRIVER OPT = ");
Serial.println(k_DrvrSteps);
Serial.print("SPEED = ");
Serial.println(Speed);
Serial.print("ACCELERATION = ");
Serial.println(Accel);
}
//РАСЧЕТ УГЛА ПОВОРОТА В ШАГАХ
void calcAngle(uint16_t ddd, uint16_t dd, uint16_t d, byte item){
Angle = (float)((ddd+dd+d)*k_DrvrSteps*k_Reductor/1.8);
if(item == 2){Angle = -Angle;};
}
// ЗАПУСК ДВИГАТЕЛЯ И ОТРАБОТКА ЗАДАНИЯ
void motorMove(byte item){
rotorPos = stepper.currentPosition();
//Serial.println(rotorPos);
if (Angle > 0){
if(item == 2){
while(rotorPos > Angle){
rotorPos = stepper.currentPosition();
stepper.runSpeed();
if (flagEmerStop == true){break;}
}
}else{
while(rotorPos < Angle){
rotorPos = stepper.currentPosition();
stepper.runSpeed();
if (flagEmerStop == true){break;}
}
}
digitalWrite(pin_WeldingA, LOW);
digitalWrite(pin_WeldingB, LOW);
}
if (Angle == 0){
if(item == 2){Speed = -Speed; /*Accel = -Accel;*/};
while(true){
stepper.runSpeed();
rotorPos = stepper.currentPosition();
if(flagEmerStop == true){break;}
}
}
stepper.setCurrentPosition(0);
Serial.print("ANGLE = ");
Serial.println(Angle);
Serial.print("ROTOR POSITION = ");
Serial.println(rotorPos);
}
/*###############################################################*/
// Меню настроек (ГЛАВНОЕ)
/*###############################################################*/
void pressButtonToSetup(){
static uint32_t tmr = millis();
if (millis()-tmr>= 550){
if (!digitalRead(pin_StartV1) || !digitalRead(pin_StartV2)){
setupMenu();
}
tmr = millis();
}
init_main_menu_lcd();
}
// #################### меню настроек (ГЛАВНОЕ) ########################
void setupMenu(){
flagEmerStop = false;
static byte itm = 1;
static byte i = 1;
static byte j = 1;
while(true){
lcd.setCursor(1, 0);
lcd.print("Drive 1:");
lcd.setCursor(1, 1);
lcd.print("Beltn 1:");
lcd.setCursor(12, 0);
lcd.print("Next");
lcd.setCursor(12, 1);
lcd.print("EXIT");
if(flagItem_M == true || !digitalRead(pinButton)){
flagItem_M = false;
static uint32_t tmr = millis();
if(millis() - tmr >= 350){itm++; tmr = millis();}
if(itm > 4){itm = 1;}
Serial.println(flagItem_M);
}
switch (itm){
case 1:
lcd.setCursor(0, 0);
lcd.write(1);
lcd.setCursor(11, 1);
lcd.print(" ");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.write(1);
break;
case 3:
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(11, 0);
lcd.write(1);
break;
case 4:
lcd.setCursor(11, 0);
lcd.print(" ");
lcd.setCursor(11, 1);
lcd.write(1);
break;
}
if(itm == 1){
if(cnt1>0){i++; cnt1=0; if(i>5){i=1;}}
if(cnt1<0){i--; cnt1=0; if(i<1){i=5;}}
}
if(itm == 2){
if(cnt1>0){j++; cnt1=0; if(j>10){ j=1;}}
if(cnt1<0){j--; cnt1=0; if(j<1){ j=10;}}
}
//Настройка микрошага на драйвере
switch (i){
case 1:
k_DrvrSteps = 1;
lcd.setCursor(9, 0);
lcd.print("1");
lcd.setCursor(10, 0);
lcd.print(" ");
break;
case 2:
k_DrvrSteps = 2;
lcd.setCursor(9, 0);
lcd.print("2");
lcd.setCursor(10, 0);
lcd.print(" ");
break;
case 3:
k_DrvrSteps = 4;
lcd.setCursor(9, 0);
lcd.print("4");
lcd.setCursor(10, 0);
lcd.print(" ");
break;
case 4:
k_DrvrSteps = 8;
lcd.setCursor(9, 0);
lcd.print("8");
lcd.setCursor(10, 0);
lcd.print(" ");
break;
case 5:
k_DrvrSteps = 16;
lcd.setCursor(9, 0);
lcd.print("1");
lcd.setCursor(10, 0);
lcd.print("6");
break;
}
//Коэффициент редукции
switch (j){
case 1:
k_Reductor = 1;
lcd.setCursor(9, 1);
lcd.print("1 ");
break;
case 2:
k_Reductor = 2;
lcd.setCursor(9, 1);
lcd.print("2 ");
break;
case 3:
k_Reductor = 3;
lcd.setCursor(9, 1);
lcd.print("3 ");
break;
case 4:
k_Reductor = 4;
lcd.setCursor(9, 1);
lcd.print("4 ");
break;
case 5:
k_Reductor = 5;
lcd.setCursor(9, 1);
lcd.print("5 ");
break;
case 6:
k_Reductor = 6;
lcd.setCursor(9, 1);
lcd.print("6 ");
break;
case 7:
k_Reductor = 7;
lcd.setCursor(9, 1);
lcd.print("7 ");
break;
case 8:
k_Reductor = 8;
lcd.setCursor(9, 1);
lcd.print("8 ");
break;
case 9:
k_Reductor = 9;
lcd.setCursor(9, 1);
lcd.print("9 ");
break;
case 10:
k_Reductor = 10;
lcd.setCursor(9, 1);
lcd.print("10");
break;
}
if(!digitalRead(emergencyStop) && itm == 3){
lcd.clear();
setupMenuNext();
}
if(!digitalRead(emergencyStop) && itm == 4){
break;
}
}
saveSetupMemory();
lcd.clear();
}
//################# Меню настроек (окно 1) ###########################
void setupMenuNext(){
flagEmerStop = false;
static byte itm = 1;
while(true){
lcd.setCursor(1, 0);
lcd.print("CH_1:");
lcd.setCursor(1, 1);
lcd.print("CH_2:");
lcd.setCursor(12, 0);
lcd.print("Next");
lcd.setCursor(12, 1);
lcd.print("Back");
if(flagItem_M == true || !digitalRead(pinButton)){
flagItem_M = false;
static uint32_t tmr = millis();
if(millis() - tmr >= 350){itm++; tmr = millis();}
if(itm > 4){itm = 1;}
Serial.println(flagItem_M);
}
switch (itm){
case 1:
lcd.setCursor(0, 0);
lcd.write(1);
lcd.setCursor(11, 1);
lcd.print(" ");
break;
case 2:
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.write(1);
break;
case 3:
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(11, 0);
lcd.write(1);
break;
case 4:
lcd.setCursor(11, 0);
lcd.print(" ");
lcd.setCursor(11, 1);
lcd.write(1);
break;
}
if(itm == 1){
if(cnt1>0){flagOnCH1 = true; cnt1=0;}
if(cnt1<0){flagOnCH1 = false; cnt1=0;}
}
if(itm == 2){
if(cnt1>0){flagOnCH2 = true; cnt1=0;}
if(cnt1<0){flagOnCH2 = false; cnt1=0;}
}
if(!digitalRead(emergencyStop) && itm == 3){
lcd.clear();
setupMenuNext2();
}
//Настройка микрошага на драйвере
switch (flagOnCH1){
case true:
lcd.setCursor(7, 0);
lcd.print("ON ");
break;
case false:
lcd.setCursor(7, 0);
lcd.print("OFF");
break;
}
//Коэффициент редукции
switch (flagOnCH2){
case true:
lcd.setCursor(7, 1);
lcd.print("ON ");
break;
case false:
lcd.setCursor(7, 1);
lcd.print("OFF");
break;
}
//if(!digitalRead(emergencyStop) && itm == 3){
//lcd.clear();
//setupMenu();
//}
if(!digitalRead(emergencyStop) && itm == 4){
break;
}
}
saveSetupMemory();
lcd.clear();
}
//################### Меню настроек (окно 2) ############################
void setupMenuNext2(){
flagEmerStop = false;
static byte itm = 1;
static uint32_t tmr = millis();
while(true){
lcd.setCursor(1, 0);
lcd.print("GRIND rpm");
lcd.setCursor(1, 1);
lcd.print("SPEED:");
lcd.setCursor(12, 1);
lcd.print("Back");
//lcd.setCursor(12, 1);
//lcd.print("Next");
if (!digitalRead(pinSetV)){
if (millis()-tmr >=500){
tmr = millis();
if (itm == 1){index_G++; if (index_G > 4){index_G = 1;}}
}
}
if (cnt1 > 0) {
if (itm == 1){
setValue(index_G, g, gg, ggg, maxG, minG);
timer = millis();
}
cnt1 =0;
}
if (cnt1 < 0) {
if (itm == 1){
setValue(index_G, g, gg, ggg, maxG, minG);
timer = millis();
}
cnt1 =0;
}
if (millis() - timer == 1500 && millis() - timer <= 1700){
saveAngleMemory();
}
lcdGrindSpeedDisplay(itm);
if((flagItem_M == true || !digitalRead(pinButton))&& (index_G == 4)){
flagItem_M = false;
if(millis() - tmr >= 350){itm++; tmr = millis();}
if(itm > 2){itm = 1;}
Serial.println(flagItem_M);
}
switch (itm){
case 1:
lcd.setCursor(0, 1);
lcd.write(1);
lcd.setCursor(11, 1);
lcd.print(" ");
break;
case 2:
lcd.setCursor(0, 1);
lcd.print(" ");
lcd.setCursor(11, 1);
lcd.write(1);
break;
}
if (!digitalRead(pinSetV)){
if (millis()-tmr >=350){
tmr = millis();
if (itm == 1){
index_G++;
if (index_G > 4){
index_G = 1;
}
}
}
}
if(!digitalRead(emergencyStop) && itm == 2){
break;
}
}
saveSetupMemory();
lcd.clear();
}
//##########################################################//
// ВНЕШНЕЕ ПРЕРЫВАНИЕ ДЛЯ КНОПОК
//##########################################################//
ISR (PCINT1_vect){
if (!digitalRead(emergencyStop)){
if (flagModeWork){
flagEmerStop = true;
}
if (flagModeSetVal){
pressButtonToSetup();
}
}
// Если прерывание вызвано кнопкой
if (!digitalRead(pinSW))
{
flagItem_M = true;
}
// Или если прерывание вызвано сигналами энкодера
else
{
// Прочитать сигналы A и B
boolean A_val = digitalRead(pinCLK);
boolean B_val = digitalRead(pinDT);
// Записать сигналы A и B в отдельные последовательности
seqA <<= 1;
seqA |= A_val;
seqB <<= 1;
seqB |= B_val;
// Маскировать четыре старших бита
seqA &= 0b00001111;
seqB &= 0b00001111;
// Сравнить запсанную последовательность с ожидаемой последовательностью
if (seqA == 0b00001001 && seqB == 0b00000011)
{
cnt1--;
}
if (seqA == 0b00000011 && seqB == 0b00001001)
{
cnt1++;
}
//Serial.println(cnt1);
}
}