Шаговый двигатель туда-обратно прошу подсказки
- Войдите на сайт для отправки комментариев
Ср, 03/03/2021 - 16:10
Собрал устройство набивающее табак в гильзы.
Первый в моей жизни скетч писал сам. Все работает на ура, во всяком случае меня устраивает.
По этой ссылке короткое видео, чтобы было понятно о чем речь: https://photos.app.goo.gl/LpENFB2pSp6LeHMn9
Сам скетч получился похабен, не удобен в плане редактирования, добавлений каких то действий сверх имеющихся. Планирую добавить автоматическую подачу гильз - за это действие будет отвечать вторая ардуина (на этой тупо выводов уже нет свободных, на аналоговых - диплей)
Поэтому прошу помощи: подскажите, пожалуйста, каким образом можно привести мой скетч до общепринятого формата.
Пробовал разбить отдельно типа void rabota(), void parametry() и т.д.
Не получилось - они тупо исполняются по кругу по типу бугущего огня (через монитор порта смотрел). Не могу понять, каким образом заставить программу работать, например, только в void rabota() и переходить в void parametry() только после моей команды
Сам скетч:
#include <GyverStepper.h> // подключаем библиотеку шагового двигателя ШД #include <GyverButton.h> // подключаем библиотеку для работы с кнопкой #include <GyverEncoder.h> // подключаем библиотеку для работы с энкодером #include <LiquidCrystalRus.h> // подключаем библиотеку для работы с дисплеем #include <EEPROM.h> // подключаем библиотеку для работы с памятью #define INIT_KEY 250 // ключ первого запуска EEPROM. 0-254 #define STEP_PIN 2 // назначаем пин для сигнала STEP драйвера #define DIR_PIN 3 // назначаем пин для сигнала DIR драйвера #define ENABLE_PIN 4 // назначаем пин для сигнала ENABLE драйвера #define DT 5 // назначаем пин S1 энкодера #define CLK 6 // назначаем пин S2 энкодера #define SW 7 // назначаем пин кнопки энкодера #define BTN_STOP 8 // концевик исходного положения #define BTN_PUSK 10 // создаём кнопку ПУСК/РАБОТА (сенсорная) #define rs A0 // назначаем пины дисплея #define en A1 // назначаем пины дисплея #define d4 A2 // назначаем пины дисплея #define d5 A3 // назначаем пины дисплея #define d6 A4 // назначаем пины дисплея #define d7 A5 // назначаем пины дисплея #define INTERVAL 500UL // интервал между включение/выключением строки GButton Kn(BTN_PUSK, LOW_PULL); // создаём кнопку для работы с меню (сенсорная) /*** создаём шаговый двигатель ШД ***/ GStepper<STEPPER2WIRE> stepper(400, STEP_PIN, DIR_PIN, ENABLE_PIN); Encoder Enc(CLK, DT, SW, TYPE2); // создаём энкодер /*** создаём дисплей ***/ LiquidCrystalRus lcd(rs, en, d4, d5, d6, d7); byte Strelky[8] = { // создаём стрелки анимации заключительного дисплея 0b10001, 0b01010, 0b00100, 0b00000, 0b10001, 0b01010, 0b00100, 0b00000 }; int Quant = 0; // переменная количества продукции int Dlina = 1400; // переменная длины хода рычага (Dlina_Displey = Dlina * 0.120) int Pausa = 540; // переменная продолжительности паузы int Speed = 2125; // переменная скорости (количество импульсов * 0,02(передаточное кинематики)) int Accel = 1500; // ускорение. при установке умножаем на 10 float Speed_Displey = 42.5; // скорость для дисплея float Pausa_Displey = 0.54; // пауза для дисплея static unsigned long prevTime = 0; // храним время последнего переключения состояния строки bool Stroka_State = HIGH; // этой переменной присваиваем состояние строки ВИДНА/НЕ ВИДНА static byte Step = 1; // переменная переключене шагов движения. начинаем с дисплея static byte Anim = 0; // переменная переключения анимации заключительного дисплея bool flag_Quant = LOW; // флаг сохранять/восстанавливать количество продукции в EEPROM bool flag_Param = LOW; // флаг сохранять/восстанавливать параметры в EEPROM void setup() { stepper.reverse(true); stepper.disable(); // отключаем драйвер ШД Kn.setTimeout(750); // настройка таймаута на удержание кнопки (по умолчанию 500 мс) lcd.createChar(1, Strelky); // создаем символ стрелок lcd.begin(16, 4); // инициализируем дисплей на 16 символов и 4 строки /*** Настройка пина D8 (концевик) ***/ pinMode(BTN_STOP, INPUT_PULLUP); // инициируем пин концевика (на всякий случай подтянув к +5В) // DDRB &= B11111110; // *** настроить пин 8 как ВХОД // PORTB |=B00000001; // *** установить ВЫСОКИЙ уровень на пин 8 /*** Отрабатываем с паятью при ПЕРВОМ включении микросхемы ***/ if (EEPROM.read(1023) != 250) // читаем резервную ячейку EEPROM, если ключ не совпадает { EEPROM.write(1023, 250); // пишем в память корректный ключ. 0-254 EEPROM.put(1, Quant); // сохраняем в EEPROM настройки по умолчанию EEPROM.put(3, Pausa); // переменная int занимает 2 ячейки EEPROM.put(5, Speed); // нумеруем вручную!!! EEPROM.put(7, Accel); EEPROM.put(9, Dlina); } } void loop() { switch (Step) { /***************** РАБОТАЕМ С ПАМЯТЬЮ: ВОССТАНАВЛИВАЕМ/НЕТ ПЕРЕМЕННЫЕ *****************/ case 1: /** ОТРИСОВКА НАЧАЛЬНОГО ДИСПЛЕЯ ВЫБОРА **/ lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.print(" ВОССТАНОВИТЬ "); lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print("данные из памяти"); lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Продукция: НЕТ "); lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Параметры: НЕТ "); Step = 2; // переходим к выбору "ВОССТАНАВЛИВАТЬ/НЕТ ПАРАМЕТРЫ" break; case 2: /** ВЫБОР ВОССТАНАВЛИВАТЬ/НЕТ КОЛИЧЕСТВО ПРОДУКЦИИ **/ /* мигаем надписью "Продукция:" */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.print(" "); // очищаем надпись "Продукция:" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.print("Продукция:"); // печатаем надпись "Продукция:" } } /* изменяем значение "Продукция:" */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) Step = 4; // если нажата кнопка - переходим к ВОССТАНОВЛЕНИЮ ПЕРЕМЕННЫХ if (Enc.isTurn()) // если был совершён поворот в любую сторону { flag_Quant = !flag_Quant; // инвертируем состояние флага lcd.setCursor(8, 2); // устанавливаем курсор в колонку 13, строку 3 if (flag_Quant) lcd.print("ДА "); // если флаг поднят - печатаем "ДА" else lcd.print("НЕТ"); // иначе - печатаем "НЕТ" } /* выходим или переходим к восстановлению параметров */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Продукция:"); // печатаем надпись "Продукция:" Step = 3; // переходим к восстановлению ПАРАМЕТРОВ } if (Kn.isHolded()) Step = 4; // если кнопка удержана - к ВОССТАНОВЛЕНИЮ ПЕРЕМЕННЫХ break; case 3: /** ВЫБОР ВОССТАНАВЛИВАТЬ/НЕТ ПАРАМЕТРЫ **/ /* мигаем надписью "Параметры:" */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.print(" "); // очищаем надпись "Параметры:" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.print("Параметры:"); // печатаем надпись "Параметры:" } } /* изменяем значение "Параметры:" */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) Step = 4; // если нажата кнопка - переходим к ВОССТАНОВЛЕНИЮ ПЕРЕМЕННЫХ if (Enc.isTurn()) // если был совершён поворот в любую сторону { flag_Param = !flag_Param; // инвертируем состояние флага lcd.setCursor(8, 3); // устанавливаем курсор в колонку 13, строку 4 if (flag_Param) lcd.print("ДА "); // если флаг параметров поднят - печатаем "ДА" else lcd.print("НЕТ"); // иначе - печатаем "НЕТ" } /* выходим или переходим к восстановлению количества продукции */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Параметры:"); // печатаем надпись "Параметры:" Step = 2; // переходим к восстановлению КОЛИЧЕСТВА ПРОДУКЦИИ } if (Kn.isHolded()) Step = 4; // если кнопка удержана - к ВОССТАНОВЛЕНИЮ ПЕРЕМЕННЫХ break; case 4: /** Восстанавливаем/не восстанавливаем переменные **/ if (flag_Quant == HIGH) // если флаг количества продукции поднят { EEPROM.get(1, Quant); // обновляем переменную из EEPROM Quant = Quant - 1; // так как при переходе к работе 1шт добавится } if (flag_Param == HIGH) // если флаг параметров поднят { EEPROM.get(3, Pausa); // обновляем переменные из EEPROM EEPROM.get(5, Speed); // нумеруем вручную!!! EEPROM.get(7, Accel); EEPROM.get(9, Dlina); Pausa_Displey = Pausa * 0.001; // пересчитываем ПАУЗУ в секунды для дисплея Speed_Displey = Speed * 0.02; // пересчитываем СКОРОСТЬ в об/мин для дисплея } Step = 10; // переходим к ОТРИСОВКА РАБОЧЕГО ДИСПЛЕЯ break; /***************** ОКОНЧАНИЕ РАБОТЫ С ПАМЯТЬЮ *****************/ /***************** РЕЖИМ ПОДГОТОВКИ К РАБОТЕ *****************/ case 10: /** отрисовка рабочего дисплея **/ /***Первая строка - КОЛИЧЕСТВО***/ lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.println("Сделано: шт"); lcd.setCursor(10, 0); lcd.print(Quant); /***Вторая строка - ДЛИНА ДУГИ***/ lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print((String)"Длина: " + (Dlina) + " шаг "); /***Третья строка - ПАУЗА***/ // -4 потому что 3 и 4 строки смещены на 4 колонки вправо lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Пауза: сек"); lcd.setCursor(4, 2); lcd.print(Pausa_Displey, 2); /***Четвертая строка - СКОРОСТЬ***/ lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Обороты: об"); lcd.setCursor(5, 3); lcd.print(Speed_Displey, 1); Step = 11; // переходим в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ break; case 11: /** готовим ШД для выхода из режима парковки **/ stepper.setRunMode(KEEP_SPEED); // устанавливаем режим вращения с заданной скоростью stepper.setAcceleration(300); // устанавливаем малое ускорение stepper.setSpeed(-789, SMOOTH); // устанавливаем малую скорость с плавным разгоном НАЗАД stepper.enable(); // включаем драйвер шагового двигателя ШД Step = 12; // переходим к медленному вращению НАЗАД break; case 12: /** медленное движение НАЗАД **/ // while (PINB & B00000001) stepper.tick(); while (digitalRead(BTN_STOP)) { stepper.tick(); // едем покуда на концевике исходного положения высокий уровень } stepper.reset(); // останавливаемся, устанавливаем данную позицию как ИСХОДНУЮ stepper.disable(); // отключаем драйвер ШД stepper.setRunMode(FOLLOW_POS); // задаем режим следования к цели stepper.setAcceleration(Accel * 10); // устанавливаем рабочее ускорение stepper.setMaxSpeed(Speed); // устанавливаем рабочую скорость ШД Step = 13; // переходим к проверке не нежата ли кнопка ПУСК break; case 13: /** удостоверяемся что кнопка ПУСК не нажата **/ /* только когда кнопка ПУСК наверняка отпущена - переходим к работе */ if (!digitalRead(BTN_PUSK)) Step = 20; break; /*** ОКОНЧАНИЕ РЕЖИМА ПОДГОТОВКИ К РАБОТЕ ***/ /***************** РЕЖИМ РАБОТА *****************/ case 20: /* возможность корректировать количество изготовленной продукции, перехода в НАСТРОЙКИ */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) Step = 30; // если нажата кнопка ЭНКОДЕРА переходим в НАСТРОЙКИ if (Enc.isRight()) // если был поворот ВПРАВО { Quant += 1; // увеличиваем счетчик количества продукции lcd.setCursor(10, 0); // устанавливаем курсор на число количества продукции lcd.print(Quant); // печатаем/обновляем количество продукции } if (Enc.isLeft()) // если был поворот ВЛЕВО { Quant -= 1; // уменьшаем счетчик количества продукции lcd.setCursor(10, 0); // устанавливаем курсор на число количества продукции lcd.print(" "); // ощищаем на дисплее цифру количества продукции lcd.setCursor(10, 0); // устанавливаем курсор на число количества продукции lcd.print(Quant); // печатаем/обновляем количество продукции } /** ждем нажатия на кнопку ПУСК **/ if (digitalRead(BTN_PUSK) == HIGH) // если нажата кнопка ПУСК (Сенсорная) { stepper.setTarget(Dlina); // устанавливаем длину хода ШД stepper.enable(); // включаем драйвер ШД Step = 21; // переходим к шагу движение ВПЕРЕД } break; case 21: /** движение ВПЕРЕД **/ if (!stepper.tick()) // движемся. если заданная дистанция уже пройдена { Quant = Quant + 1; // увеличиваем счетчик количества продукции lcd.setCursor(10, 0); // устанавливаем курсор в колонку 10, строку 0 lcd.print(Quant); // печатаем/обновляем количество продукции delay(Pausa); // делаем паузу stepper.setTarget(0); // даём установку ШД двигаться к исходной позиции Step = 22; // переходим к шагу движение НАЗАД } break; case 22: /** движение НАЗАД **/ stepper.tick(); // движемся пока не прийдем в исходное положение // if ((PINB & B00000001) == LOW) if (!digitalRead(BTN_STOP)) // если нажат концевик исходного положения { stepper.reset(); // останавливаемся, устанавливаем данную позицию как ИСХОДНУЮ stepper.disable(); // отключаем драйвер ШД Step = 20; // переходим к ожиданию нажатия на кнопку ПУСК } /** корректируем люфт редуктора **/ else if (!stepper.tick()) // иначе если заданный путь пройден (а концевик не нажат (см.выше)) { stepper.setTarget(-1, RELATIVE); // добавляем шаг НАЗАД ОТНОСИТЕЛЬНО данной позиции } break; /***************** ОКОНЧАНИЕ РЕЖИМА РАБОТЫ *****************/ /********************* РЕЖИМ НАСТРОЙКИ *********************/ case 30: /** отрисовка дисплея НАСТРОЙКИ **/ /***Первая строка - ДЛИНА ДУГИ***/ lcd.setCursor(0, 0); lcd.print((String)"Длина: " + (Dlina) + " шаг"); /***Вторая строка - ПАУЗА***/ lcd.setCursor(0, 1); lcd.print("Пауза: сек"); lcd.setCursor(8, 1); lcd.print(Pausa_Displey, 2); /***Третья строка - СКОРОСТЬ***/ lcd.setCursor(-4, 2); lcd.print("Обороты: об"); lcd.setCursor(5, 2); lcd.print(Speed_Displey, 1); /***Четвертая строка - УСКОРЕНИЕ/ЗАМЕДЛЕНИЕ ШД***/ lcd.setCursor(-4, 3); lcd.print((String)"Ускорение: " + (Accel) + " "); Step = 31; // переходим в режим ПОДГОТОВКИ К РАБОТЕ break; case 31: /** настройка ДЛИНЫ ДУГИ **/ /* переходим к ПАРКОВКА/переходим к НАСТРОЙКА ПАУЗЫ */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.print("Длина:"); // печатаем надпись "Длина:" Step = 32; // переходим к НАСТРОЙКА ПАУЗЫ } if (Kn.isHolded()) Step = 40; // если кнопка была удержана - переходим к ПАРКОВКА /* мигаем надписью "Длина:" */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.print(" "); // очищаем надпись "Длина" } else // иначе (строка не видна) { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.print("Длина:"); // печатаем надпись "Длина:" } } /* изменяем значение "Длина:"/возвращаемся в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) // если нажата кнопка { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.print("Длина:"); // печатаем надпись "Длина:" Step = 10; // переходим к РЕЖИМ ПОДГОТОВКИ К РАБОТЕ } if (Enc.isRight()) // если был поворот ВПРАВО { Dlina += 1; // увеличиваем переменную длины на 1 if (Dlina >= 1425) Dlina = 1425; // ограничиваем верхний диапазон хода lcd.setCursor(8, 0); lcd.print(Dlina); // обновляем показания дисплея } if (Enc.isLeft()) // если был поворот ВЛЕВО { Dlina -= 1; // уменьшаем переменную длины на 1 if (Dlina <= 1375) Dlina = 1375; // ограничиваем нижний диапазон хода lcd.setCursor(8, 0); lcd.print(Dlina); // обновляем показания дисплея } break; /************** ОКОНЧАНИЕ НАСТРОЙКИ ДЛИНЫ ДУГИ **************/ case 32: /** НАСТРОЙКА ПАУЗЫ **/ /* переходим к ПАРКОВКА/переходим к НАСТРОЙКА СКОРОСТИ */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print("Пауза:"); // печатаем надпись "Пауза:" Step = 33; // переходим к НАСТРОЙКА СКОРОСТИ } if (Kn.isHolded()) Step = 40; // если кнопка была удержана - переходим к ПАРКОВКА /* мигаем надписью "Длина:" */ if (millis() - prevTime >= INTERVAL) // проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print(" "); // очищаем надпись "Пауза" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print("Пауза:"); // печатаем надпись "Пауза:" } } /* изменяем значение "Пауза:"/возвращаемся в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) // если нажата кнопка { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print("Пауза:"); // печатаем надпись "Пауза:" Step = 10; // переходим к РЕЖИМ ПОДГОТОВКИ К РАБОТЕ } if (Enc.isRight()) // если был поворот ВПРАВО { Pausa += 20; // увеличиваем переменную паузы на 20 (0,2 сек) if (Pausa >= 950) Pausa = 950; // ограничиваем верхний диапазон паузы Pausa_Displey = Pausa * 0.001; // пересчитываем в секунды lcd.setCursor(8, 1); lcd.print(Pausa_Displey, 2); // обновляем показания дисплея } if (Enc.isLeft()) // если был поворот ВЛЕВО { Pausa -= 20; // уменьшаем переменную паузы на 20 (0,2 сек) if (Pausa <= 250) Pausa = 250; // ограничиваем нижний диапазон паузы Pausa_Displey = Pausa * 0.001; // пересчитываем в секунды lcd.setCursor(8, 1); lcd.print(Pausa_Displey, 2); // обновляем показания дисплея } break; /************** ОКОНЧАНИЕ НАСТРОЙКИ ПАУЗЫ **************/ case 33: /** НАСТРОЙКА СКОРОСТИ **/ /* переходим к ПАРКОВКА/переходим к НАСТРОЙКА УСКОРЕНИЯ */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Обороты:"); // печатаем надпись "Обороты:" Step = 34; // переходим к НАСТРОЙКА СКОРОСТИ } if (Kn.isHolded()) Step = 40; // если кнопка была удержана - переходим к ПАРКОВКА /* мигаем надписью "Обороты:" */ if (millis() - prevTime >= INTERVAL) // проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print(" "); // очищаем надпись "Обороты" } else // иначе { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Обороты:"); // печатаем надпись "Обороты" } } /* изменяем значение "Обороты:"/возвращаемся в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) // если нажата кнопка { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Обороты:"); // печатаем надпись "Обороты" Step = 10; // переходим к РЕЖИМ ПОДГОТОВКИ К РАБОТЕ } if (Enc.isRight()) // если был поворот ВПРАВО { Speed += 25; // увеличиваем переменную скорости на 25 (0.5 об/мин) if (Speed >= 2475) Speed = 2470; // ограничиваем верхний диапазон скорости Speed_Displey = Speed * 0.02; // пересчитываем в об/мин lcd.setCursor(5, 2); // обновляем показания дисплея lcd.print(Speed_Displey, 1); } if (Enc.isLeft()) // если был поворот ВЛЕВО { Speed -= 25; // уменьшаем переменную скорости на 25 (0.5 об/мин) if (Speed <= 1625) Speed = 1625; // ограничиваем нижний диапазон скорости Speed_Displey = Speed * 0.02; // пересчитываем в об/мин lcd.setCursor(5, 2); // обновляем показания дисплея lcd.print(Speed_Displey, 1); } break; /***************** ОКОНЧАНИЕ НАСТРОЙКИ СКОРОСТИ *****************/ case 34: /** НАСТРОЙКА УСКОРЕНИЯ/ЗАМЕДЛЕНИЯ **/ /* переходим к ПАРКОВКА/переходим к настройкам ДЛИНЫ ДУГИ */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Ускорение:"); // печатаем надпись "Ускорение:" Step = 31; // переходим к настройкам ДЛИНЫ ДУГИ } if (Kn.isHolded()) Step = 40; // если кнопка была удержана - переходим к ПАРКОВКА /* мигаем надписью "Ускорение:" */ if (millis() - prevTime >= INTERVAL) // проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print(" "); // очищаем надпись "Ускорение:" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Ускорение:"); // печатаем надпись "Ускорение:" } } /* изменяем значение "Ускорение:"/возвращаемся в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ */ Enc.tick(); // опрашиваем энкодер if (Enc.isPress()) // если нажата кнопка { Stroka_State = HIGH; // запоминаем что стока видна lcd.clear(); // очищаем дисплей Step = 10; // переходим в ОТРИСОВКУ ДИСПЛЕЯ, затем к РАБОТА } if (Enc.isRight()) // если был поворот ВПРАВО { Accel += 125; // увеличиваем переменную ускорения на 2500 if (Accel >= 4000) Accel = 4000; // ограничиваем верхний диапазон ускорения lcd.setCursor(8, 3); // обновляем показания дисплея lcd.print(Accel); } if (Enc.isLeft()) // если был поворот ВЛЕВО { Accel -= 125; // уменьшаем переменную ускорения на 5000 if (Accel <= 500) Accel = 500; // ограничиваем нижний диапазон ускорения lcd.setCursor(8, 3); lcd.print(" "); // очищаем показания дисплея lcd.setCursor(8, 3); lcd.print(Accel); // обновляем показания дисплея } break; /*** ОКОНЧАНИЕ НАСТРОЙКИ УСКОРЕНИЯ/ЗАМЕДЛЕНИЯ ***/ /***************** ОКОНЧАНИЕ РЕЖИМА НАСТРОЕК *****************/ /***************** РЕЖИМ ПАРКОВКИ *****************/ case 40: /** отрисовка дисплея ПАРКОВКИ, установка параметров ШД **/ lcd.clear(); // очищаем дисплей lcd.setCursor(0, 2); // устанавливаем курсор в колонку 4, строку 3 lcd.print("ПАРКУЕМСЯ"); // печатаем надпись "ПАРКУЕМСЯ" stepper.setAcceleration(300); // устанавливаем малое ускорение stepper.setMaxSpeed(789); // устанавливаем малую скорость ВПЕРЕД stepper.setTarget(678); // устанавливаем позицию чтобы расслабить пружины механизма stepper.enable(); // включаем драйвер ШД Step = 41; // переходим в режим "ПАРКУЕМСЯ" break; case 41: /***ПАРКУЕМСЯ***/ if (!stepper.tick()) // движемся. если заданная дистанция уже пройдена { stepper.disable(); // отключаем драйвер ШД Step = 50; // переходим в режим "РАБОТАЕМ С ПАМЯТЬЮ: СОХРАНЯТЬ/НЕТ ПЕРЕМЕННЫЕ" } break; /***************** ОКОНЧАНИЕ РЕЖИМА ПАРКОВКИ *****************/ /***************** РАБОТАЕМ С ПАМЯТЬЮ: СОХРАНЯТЬ/НЕТ ПЕРЕМЕННЫЕ *****************/ case 50: /** отрисовка начального дисплея выбора **/ lcd.setCursor(0, 0); // устанавливаем курсор в колонку 0, строку 1 lcd.println(" СОХРАНИТЬ "); lcd.setCursor(0, 1); // устанавливаем курсор в колонку 0, строку 2 lcd.print("данные в память"); lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Продукция: НЕТ "); lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Параметры: НЕТ "); flag_Quant = LOW; // опускаем флаг для количества продукции flag_Param = LOW; // опускаем флаг для параметров Step = 51; // переходим к выбору "ВОССТАНАВЛИВАТЬ/НЕТ ПАРАМЕТРЫ" break; case 51: /** выбор сохранять/нет КОЛИЧЕСТВО ПРОДУКЦИИ **/ /* мигаем надписью "Продукция:" */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print(" "); // очищаем надпись "Продукция:" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Продукция:"); // печатаем надпись "Продукция:" } } /* изменяем значение "Продукция:" */ Enc.tick(); // опрашиваем энкодер if (Enc.isTurn()) // если был совершён поворот в любую сторону { flag_Quant = !flag_Quant; // инвертируем состояние флага lcd.setCursor(8, 2); // устанавливаем курсор в колонку 13, строку 3 if (flag_Quant) lcd.print("ДА "); // если поднят флаг "ПАРАМЕТРЫ" - печатаем "ДА" else lcd.print("НЕТ"); // иначе - печатаем "НЕТ" } /* выходим или переходим к сохранению параметров */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 lcd.print("Продукция:"); // печатаем надпись "Продукция:" Step = 52; // переходим к выбору сохранения ПАРАМЕТРОВ } if (Kn.isHolded()) Step = 55; // если кнопка удержана - переходим к ЗАПОМИНАНИЮ ПЕРЕМЕННЫХ break; case 52: /** выбор сохранять/нет ПАРАМЕТРЫ **/ /* мигаем надписью "Параметры:" */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения if (Stroka_State == HIGH) // если строка видна { Stroka_State = LOW; // запоминаем что стока очищена lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print(" "); // очищаем надпись "Параметры:" } else { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Параметры:"); // печатаем надпись "Параметры:" } } /* изменяем значение "Параметры:" */ Enc.tick(); // опрашиваем энкодер if (Enc.isTurn()) // если был совершён поворот в любую сторону { flag_Param = !flag_Param; // инвертируем состояние флага lcd.setCursor(8, 3); // устанавливаем курсор в колонку 13, строку 4 if (flag_Param) lcd.print("ДА "); // если поднят флаг "ПАРАМЕТРЫ" - печатаем "ДА" else lcd.print("НЕТ"); // иначе - печатаем "НЕТ" } /* выходим или переходим к сохранению количества продукции */ Kn.tick(); // опрашиваем кнопку if (Kn.isPress()) // если кнопка нажата { Stroka_State = HIGH; // запоминаем что стока видна lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 lcd.print("Параметры:"); // печатаем надпись "Параметры:" Step = 51; // переходим к выбору сохранения КОЛИЧЕСТВА ПРОДУКЦИИ } if (Kn.isHolded()) Step = 55; // если кнопка была удержана - переходим к СОХРАНЕНИЮ ПЕРЕМЕННЫХ break; case 55: /** Запоминаем/не запоминаем переменные **/ if (flag_Quant == HIGH) // если флаг количества продукции поднят { EEPROM.put(1, Quant); // обновляем в EEPROM переменную КОЛИЧЕСТВА ПРОДУКЦИИ } if (flag_Param == HIGH) // если флаг параметров поднят { EEPROM.put(3, Pausa); // обновляем в EEPROM переменные ПАРАМЕТРОВ EEPROM.put(5, Speed); // нумеруем вручную!!! EEPROM.put(7, Accel); EEPROM.put(9, Dlina); } Step = 60; // переходим к ОТРИСОВКА ЗАКЛЮЧИТЕЛЬНОГО ДИСПЛЕЯ break; /***************** ОКОНЧАНИЕ РАБОТЫ С ПАМЯТЬЮ *****************/ case 60: /** печатаем ЗАКЛЮЧИТЕЛЬНЫЙ ДИСПЛЕЙ **/ lcd.setCursor(0, 0); // печатаем первую строку lcd.print((String)"Сделано " + (Quant) + " шт "); lcd.setCursor(0, 1); // печатаем вторую строку lcd.print("Храню в памяти "); lcd.setCursor(-4, 2); // устанавливаем курсор в колонку 0, строку 3 if (flag_Quant == HIGH) { // если запоминали количество продукции lcd.print("Продукция: ДА "); // печатаем "ДА " в третью строку } else lcd.print("Продукция: НЕТ "); // иначе печатаем "НЕТ " в третью строку lcd.setCursor(-4, 3); // устанавливаем курсор в колонку 0, строку 4 if (flag_Param == HIGH) // если запоминали данные { lcd.print("Параметры: ДА "); // печатаем "ДА " в четвертую строку } else lcd.print("Параметры: НЕТ "); // иначе печатаем "НЕТ " в четвертую строку Step = 61; // переходим к АНИМАЦИЯ СТРЕЛОК НА ЗАКЛЮЧИТЕЛЬНОМ ДИСПЛЕЕ break; case 61: /*** выбор ВОЗВРАТА/АНИМАЦИЯ стрелок на заключительном дисплее ***/ /* переход в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ */ Kn.tick(); // опрашиваем кнопку Enc.tick(); // опрашиваем энкодер // если было любое воздействие на кнопку или энкодер - переходим в РЕЖИМ ПОДГОТОВКИ К РАБОТЕ if (Kn.isPress() || Enc.isTurn() || Enc.isPress() || Kn.isHolded()) Step = 10; /* счетчик для анимации */ if (millis() - prevTime >= INTERVAL) //проверяем не прошел ли нужный интервал, если прошел то { prevTime = millis(); // сохраняем время последнего переключения Anim ++; // увеличиваем переменную анимации if (Anim > 3) // если переменная анимации больше чем 3 { Stroka_State = !Stroka_State; // опускаем флаг видимости строки Anim = 0; // присваиваем переменной анимации 0 } Step = 62; // переходим к ОТРИСОВКА/ЗАТИРАНИЕ стрелок } break; case 62: /*** отрисовка/затирание стрелок на заключительном дисплее ***/ if (Anim <= 1) lcd.setCursor(15, Anim); // если "Anim" <= 1 устанавливаем курсор точно в колонку 15 else lcd.setCursor(11, Anim); // устанавливаем курсор в колонку 15 со смещением в -4 колонки if (Stroka_State) lcd.print("\1"); else lcd.print(" "); // печатаем/затираем стрелки Step = 61; // переходим к ВЫБОР ВОЗВРАТА/АНИМАЦИЯ СТРЕЛОК break; /***************** ОКОНЧАНИЕ ЗАКЛЮЧИТЕЛЬНОГО ДИСПЛЕЯ *****************/ } }
Автор библиотек тут не в почете:)
ну вот у вас в коде есть куски, исполняемые по шагам. При Step == 1 выполняется один, шаг при step == 2 - второй, и так до 61...
Вот эти шаги - прям готовые заготовки для void rabota(), void parametry() и т.д.
А что бы они переходили друг в друга только по команде - вы не присваивайте параметру Step новое значение, пока не захотите сделать переход
с какого места программы вышел в отдельный void () туда и вернешься по завершению.
Ну, да, так и есть ... с какого вышел .... в void ...
(пойду выпью чего-нибудь за Ваше здоровье)
Lis07, судя по Вашим вопросам, Вам нужно не на форум писать, а книжки читать.
Начните с Керниган Ритчи "Язык программирования Си".
это не библиотека плывёт, а ваш дешёвый драйвер.
то же самое будет и на др. библиотеках.
как вариант использовать концевик для калибровки
это не библиотека плывёт, а ваш дешёвый драйвер.
то же самое будет и на др. библиотеках.
как вариант использовать концевик для калибровки
Концевик использую. строки 339 - 342
Драйвер DM542 Leadshine
на QStepper после 300 - 400 гильз я работу строк 339 - 342 слышал на каждой седьмой - двадцатой гильзе.
На библиотеке того, кого здесь не любят, я тоже слышу работу этих строк, да. Приблизительно на каждой двухсотой гильзе, не раньше.
P.S. Курю интернет насчет работы функций. пока вразумительно ничего на понимаю, но некоторые догадки уже наклевываются
что это за наркомания?
мне хватило только видео из первого поста
Если там фотоэлемент концевой, то о какой потере точности идёт речь? Калиброваться можно на каждом повороте.
Так он калибруется. издавая при этом два громких щелчка по моим расшатанным нервам
Тут речь ведь была совсем о другом: я просил совета, каким образом можно уйти от switch (Step) и сквозной нумерации к отдельным функциям типа void rabota(), void parametry() и т.д.
В данном конкретном случае:
1. Один человек вначале дал дельный совет
2. Позже Вы тоже дали верный совет
Остальные просто постарались макнуть меня в дерьмо:
1. Обвинили в пользовании библиотеками "неправильного" автора (кстати я понял почему он неправильный - помогает людям учиться, разжевывает непонятные моменты)
2. Заострили внимание на том, что тупой (но спасибо, хоть выпили за мой выход из невежества - уже помощь)
3. Посоветовали начать с образования - типа сами в школу не ходили, учитель не подсказывал - просто читали учебники и научились грамоте, счету
4. Обозвали наркоманом (от правда не для себя делаю: отцу уже 87, он всю жизнь сидел на табаке, а сейчас уже самокрутку сделать не может, приходится мне выкручиваться)
В общем интернет такой интернет...
За сим прощаюся, други.
Всего вам наилучшего!
P.S. а все же совет почитать литературу хорошо помог! Отдельное тебе спасибо, Бро!
Только что самому, без чьей-либо помощи и подсказок удалось запустить работу двух функций с переходами между ними! Дальше дело техники, принцип стал понятен.
Храните дальше свои секреты
Блеать, у вас тут чо, неделя сказочных далбаЙобоФФ шоле?
Приведённый выше код будет работать ТОЛЬКО в RTos какой-либо! Прямо влоб из дурдуины он работать не будет!!! Да и подход явно быдлокодерский, используя в "тасках" (поток, подпрограмма) delay вместо osDelay это признак дурачины&дурдуины.
Печально это читать...
Блеать, у вас тут чо, неделя сказочных далбаЙобоФФ шоле?
Приведённый выше код будет работать ТОЛЬКО в RTos какой-либо! Прямо влоб из дурдуины он работать не будет!!! Да и подход явно быдлокодерский, используя в "тасках" (поток, подпрограмма) delay вместо osDelay это признак дурачины&дурдуины.
Печально это читать...
Во-первых код чтобы понять принцип. Поэтому делай допускается, как и во многих других задачах
Во-вторых самое главное: этот код перед тем как печатать я проверил на ардуино нано. Вот прям взял и влоб загрузил. Работает. Какой из этого вывод? А вывод простой: -NMi- некомпетентен! (долбоёб по-нашему). Мало того, ведет себя с людьми по хамски, грубит как какой-то быдлан из подворотни. Значит плюс ко всему как бы это прискорбно не выглядело, он самое натуральное быдло. Быдло и Долбоёб. Адская смесь.
Извините
хорошо помог
но Вы тут же об этом забыли, и заявляете
самому, без чьей-либо помощи
Так всё-таки самому, без чьей либо помощи? Или при помощи хорошо помогшего совета?
Вы уж определитесь.
P.S. Не поверите, но это здесь обычная практика. Человек регистрируется, задаёт вопрос, из которого видно, что он не понимает слов, которые использует, получает совет, следует ему, решает свою проблему и в благодарность заявляет, что здесь все мудаки и никто ему не помог. Вы, похоже, из таких. Не считайте себя уникальным - это довольно обычно.
Я не знаю отчего там щелчок. В моей практике шаговые не щелкали так, чтобы прям невмоготу. Это особенность механической части что ли? Погоняйте на аксельстеппере - там тоже щелчки будут?
Ну дык если ты "не_еблан" - оформи код по человечески в любой САПР и выложи на любой файлообменник. Сделай возможность трассировки кода и мы вместе посмотрим, как твоя "таска №1" успешно "зависнет" в глухом цикле while(1). А уже потом будем разбираццо, кто с нас быдлокодер, договорились?
«Чтобы поймать вай-фай, нужно думать как вай-фай». В loop() все происходит в цикле, он и есть цикл while (1), Евгений Петрович хорошие мысли высказывал как-то, если я все верно понял - разбивай задачу на подзадачи, даже если не знаешь как подзадачи решать. Разделяй и властвуй, так вроде это звучало от бизнесменов начала 20го века в сша. ))
Разделяй и властвуй, так вроде это звучало от бизнесменов начала 20го века в сша. ))
(не вся История полностью американская, люди жили еще и до образования США)
Вам дали совет - почитать литературу и прокачать знания. С теми знаниями, с которыми Вы задали вопрос, никакого другого совета дать нельзя - Вы его просто не поймёте. Т.е. совет Вам дали и он Вам помог, но Вы тут же об этом забыли
Так всё-таки самому, без чьей либо помощи? Или при помощи хорошо помогшего совета?
Вы уж определитесь.
P.S. Не поверите, но это здесь обычная практика. Человек регистрируется, задаёт вопрос, из которого видно, что он не понимает слов, которые использует, получает совет, следует ему, решает свою проблему и в благодарность заявляет, что здесь все мудаки и никто ему не помог. Вы, похоже, из таких. Не считайте себя уникальным - это довольно обычно.
Да, по поводу костыля:
-NMi- вот короткий видос с монитора порта
https://drive.google.com/file/d/12qBHYhK5JU8hVP41G5rIY7RYLSzLS_OJ/view? usp=sharing
Сейчас попробовал по этому принципу десять разных задач. Переключаю энекодером на соседние. Работает. Каким образом - не знаю, но работает.
Ардуина нано, вот такая:
https://drive.google.com/file/d/19RJ_RHevMGRjnZbq8ap0cZQ8P0RTxuRW/view? usp=sharing
И это... Извини, вспылил я вчера немного, нервный стаю на старости.
sadman41
На аксельстеппере работает просто изумительно, все плавно, красиво. Немного не хватает скорости. Редуктор бы с меньшим передаточным числом, да меньшим люфтом, но уж какой был.
BOOM пишет:
В loop() все происходит в цикле, он и есть цикл while (1)
Даа, ппц... Теорию мне нужно не подтягивать, а изучать! Вдумчиво и планомерно. Не знал, что loop() является по сути той же while(1). Это получается, если упростить - сам того не ведая, решил использовать как бы несколько loop() в одном скетче. Пока не знаю насколько это верно или так же, как и ранее придуманный безобразной длины switch является моветоном...
Аксельстеппер можно пофиксить, теоретически.
Но, в целом, следует понять, почему недотягивает. Если в аксельстеппере всё ок, то значит дело в нынешней библиотеке. Если же дело в люфте, то включать его в дистанцию.
Вобщем, тут чисто чтением исходника разобраться не получится, а нафантазировать - вполне себе. Нужно собрать что-то подобное и погонять.
Lis07, ну, можно было так подробно и не расписывать. Я же сказал, что это довольно обычная практика, не Вы - первый, не Вы - последний.
Давайте представим себе ситуацию: вы в незнакомом городе спрашиваете у прохожего как пройти на улицу Лизюкова. В ответ получаете следуещее: ты не знаешь названий этих улиц, следовательно все равно не поймешь куда идти. Сходи в краеведческий музей, выучи историю создания города, выучи досконально план застройки города и тогда я тебе помогу.
Аналогия несколько хромает.
Как можно объяснить человеку, как пройти на улицу Лизюкова, если он не знает, что такое "направо", "налево", а также не понимает смысла выражения "пройдите 100 шагов", да и вообще не умеет считать более чем до один-два-много?