Я вот чего не могу пока понять, у нас после dir=!dir@DAER, после dir = !dir возвращаемся в начало loop() (если ничего ниже нет). А далее все время будет вызываться tick(), до тех пор, пока мотор не остановиться и не выполниться условие, где запустится мотор в другую сторону и поменяем dir ещё раз, и так по кругу
#include <GyverStepper.h>
//****НАСТРАИВАЕМ РАБОТУ
int dist = 40; //рабочий ход мм
int cycles = 30; //количество циклов в минуту
int center = 45; //расстояние от концевика до центра мм
long stp = 8; //деление шага
int shkiv = 32; //мм за один оборот мотора
long roundstps = stp*200; //чилсо шагов на оборот в полном шаге
long worksteps= (dist*roundstps)/shkiv; //шагов в рабочем ходе в одну сторону
long centersteps=(center*roundstps)/shkiv; //шагов от концевика до центра
long spd; //скорость движение шаг/с
long maxspd =(dist*2*cycles*roundstps)/60/shkiv; //мкс скорость движение шаг/с
long accel =maxspd*2; //ускорение движение шаг/с*с
GStepper< STEPPER2WIRE> stepper1(roundstps, 12, 10, 4);
//*****ФЛАГИ
volatile boolean F_KONC_A;
volatile boolean F_KONC_B;
volatile boolean F_START;
volatile uint32_t debounce;
void Initial_positionA() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_A = 1;
F_START = 1;
}
}
void Initial_positionB() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
if (millis() - debounce >= 200 && digitalRead(3)) {
debounce = millis();
F_KONC_B = 1;
}
}
//********************************************************************************
void setup() {
F_KONC_A==0;
F_KONC_B==0;
F_START==0;
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B
stepper1.setRunMode(FOLLOW_POS);
stepper1.setMaxSpeed(maxspd);
stepper1.setAcceleration(accel);
Serial.begin(9600);
Serial.println("Hello World!"); // отправить
Serial.println(worksteps); // дистанция в шагах
Serial.println(maxspd); // скорость
Serial.println(accel); // ускорение
Serial.println(roundstps); //шагов в одном обороте
Serial.println(centersteps); //шагов до центра
}
void loop() {
if (!stepper1.tick() && F_START==0){//Если флаг СТАРТ поднят
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(centersteps*2, RELATIVE);//Едем ДАЛЕКОоо вперёд. Костыль такой.
}
static bool dir = true;
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
dir = !dir;
}
if (F_KONC_A ==1){ //если флаг А поднят
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(-centersteps-(worksteps/3), RELATIVE); //Едем в центр
F_KONC_A = 0; //Флаг А снова готов к труду и обороне
}
if (F_KONC_B ==1){ //если флаг В поднят
stepper1.brake(); //опять же тормозим резко
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(centersteps-(worksteps/2), RELATIVE); //Тут едем в центр но немного ближе, т.к. следующий шаг туда же
F_KONC_B = 0;//Опускаем флаг В
}
}
Такой вариант мне нравится тем, что при смене деления шага или если упоры сдвигаются (концевики), то всё рассчитывается само. Это круто. Интересно, как это выглядит в коде.Вообще интересный проект. Я делал что то похожее. С 2-мя концевиками. В самом начале я двигал до одного концевика, потом до другого и считал кол-во шагов. Получал длину , записывал ее в память. а потом по нажатии кнопки двигал из одного места до другого, замедляясь при приближении к к краю.
стоит ПОСЛЕ? - я вижу ДОЯ вот чего не могу пока понять, у нас после dir=!dir
стоит static bool dir = true;
циклом это будет во время выполнения. А во время компиляции программа анализируется последовательно строчка за строчкой и обьявление переменной должно стоять ДО ее использования.Ну это же цикл.
Понимание медленно, но приходит.циклом это будет во время выполнения. А во время компиляции программа анализируется последовательно строчка за строчкой и обьявление переменной должно стоять ДО ее использования.
Если бы у вас dir=!dir стояло ДО static bool dir = true; и это бы компилировалось - это означало бы. что у вас две переменные dir
void loop() {
static bool dir = true;
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps); //АБСОЛЮТНЫЕ ПОЗИЦИИ
dir = !dir;
}
}
void loop() {
static bool dir = true;
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE); //ОТНОСИТЕЛЬНЫЕ ПОЗИЦИИ
dir = !dir;
}
}
в первом точно не уверен - скорее всего ноль координат в том месте, где был мотор при подаче питанияещё я не понимаю где точка отсчёта в первом (абслолютные координаты) и втором (относительные) случаях.
volatile boolean F_START; //логический флаг стартовой инициации
volatile boolean F_KONC_A; //концевик А
volatile boolean F_KONC_В; //концевик В
long distance=0; //обьявили переменную дистанции и присвоили ей 0
void Initial_positionA() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_A = 1;
}
}
void Initial_positionB() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_B = 1;
}
}
void setup() {
F_KONC_A=0;
F_KONC_В=0;
F_START=1;
attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B
if (!stepper1.tick() && F_START==1 ){//Если флаг СТАРТ поднят
stepper1.setRunMode(KEEP_SPEED); //Режим поддержания скорости. Просто едем, пока не нажмём концевик А.
stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
}
if (F_KONC_A ==1 && F_START==1 &&F_KONC_B==0) //Нажали концевик А, едем к концевику В
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
stepper1.reverse(); //Инвертируем направление вращения
stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
stepper1.setCurrent(0);//обнуляем координаты
}
if (F_KONC_A ==1 && F_START==1 &&F_KONC_B==1) //Нажали концевик В
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
distance=stepper1.getCurrent(); //Получаем координату и записываем её в переменную distance
stepper1.setRunMode(FOLLOW_POS);//Устанавливаем режим следования к цели
stepper1.reverse(); //Инвертируем направление вращения
stepper1.setMaxSpeed(maxspd/2); //С маленькой скоростью
stepper1.setTarget(distance/2, Relative);//Устанавливаем координату цели. После остановки она сбросится в 0.
F_KONC_A=0;
F_KONC_В=0;
F_START=0;
}
Void loop (){
static bool dir = true;
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
dir = !dir;
}
}
volatile boolean F_START = 1; //логический флаг стартовой инициации
volatile boolean F_KONC_A = 0; //концевик А
volatile boolean F_KONC_В = 0; //концевик В
long distance = 0; //обьявили переменную дистанции и присвоили ей 0
void Initial_positionA() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_A = 1;
}
}
void Initial_positionB() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_B = 1;
}
}
void setup() {
attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B
// в начале F_START всегда 1, это раз. stepper1.tick() - проверять не имеет смысла в setup - итог условие тут не нужно!
//f (!stepper1.tick() && F_START==1 ){//Если флаг СТАРТ поднят
stepper1.setRunMode(KEEP_SPEED); //Режим поддержания скорости. Просто едем, пока не нажмём концевик А.
stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью
//}
// это не будет работать!
//if (F_KONC_A == 1 && F_START == 1 && F_KONC_B == 0) //Нажали концевик А, едем к концевику В, и лишние условия ни к чему.
/*
Тут не имеет смысла проверять tick - он всегда будет true т.к. у нас движение с пост. скоростью, а не до места.
Значит проверяем только на нажатие концевика:
проверять надо так:
*/
while (!F_KONC_A) stepper1.tick();
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик // тут не резко тормозим, а отменяем движение. Да его и не будет дальше, т.к. движение идет через tick, а его уже нет.
stepper1.setCurrent(0);//обнуляем координаты // это делаем сразу.
stepper1.reverse(); //Инвертируем направление вращения
stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью
while (!F_KONC_B) stepper1.tick();
// if (F_KONC_A == 1 && F_START == 1 && F_KONC_B == 1) //Нажали концевик В
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
distance = stepper1.getCurrent(); //Получаем координату и записываем её в переменную distance
stepper1.setRunMode(FOLLOW_POS);//Устанавливаем режим следования к цели
stepper1.reverse(); //Инвертируем направление вращения
stepper1.setMaxSpeed(maxspd / 2); //С маленькой скоростью
stepper1.setTarget(distance / 2, Relative); //Устанавливаем координату цели. После остановки она сбросится в 0.
F_KONC_A = 0;
F_KONC_В = 0;
F_START = 0;
}
Void loop () {
static bool dir = true;
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
dir = !dir;
}
}
void Initial_position() {
F_KONC= 1;
}
void setup() {
...
stepper1.setRunMode(FOLLOW_POS); //РЕЖИМ СЛЕДОВАНИЯ К ПОЗИЦИИ
...
}
void loop() {
...
if (F_KONC_A ==1 && F_TIME==1){
stepper1.brake();
stepper1.setRunMode(KEEP_SPEED); //Установили режим поддержания скорости
stepper1.setMaxSpeed(maxspd/2);
...
}
if (F_KONC_B ==1 && F_TIME==1){
//ВОТ ТУТ КАКОЙ БУДЕТ РЕЖИМ МОТОРА???
stepper1.brake();
stepper1.setMaxSpeed(maxspd/2);
....
}
}
stepper1.setRunMode(KEEP_SPEED); //Установили режим поддержания скорости
stepper1.setMaxSpeed(maxspd/2);
]
Есть готовый скетч, и он работает. Вот прямо сейчас...Я уже перестал понимать что происходит. Изначально было больше осмысленности.
Нет. Сейчас у меня между концевиками 75 мм. Рабочий ход - 40 мм ( 40 вперёд, остановка, 40 назад). (тут немного убого сделано, лучше, видимо абсолютная дистанция). roundstps нужен, чтобы удобно было менять деление шага.В конце идет перемещение используя worksteps , диапазон получился 2*worksteps.
worksteps= (dist*roundstps)/shkiv;
Но при этом теоретически может оказаться ситуация, что worksteps будет больше половины всей дистанции.
#include <GyverStepper.h>
//****НАСТРАИВАЕМ РАБОТУ
int dist = 40; //рабочий ход мм
int cycles = 15; //количество циклов в минуту
int center = 35; //расстояние от концевика до центра мм
uint32_t timer_run = 10; //время работы мин.
uint32_t timer_pause = 10; //время паузы мин.
long stp = 64; //деление шага
int shkiv = 32; //мм за один оборот мотора
//*****ВЫЧИСЛЕНИЯ
long roundstps = stp*200; //чилсо шагов на оборот в полном шаге
long worksteps= (dist*roundstps)/shkiv; //шагов в рабочем ходе в одну сторону
long centersteps=(center*roundstps)/shkiv; //шагов от концевика до центра
long spd; //скорость движение шаг/с
long maxspd =(dist*2*cycles*roundstps)/60/shkiv; //мкс скорость движение шаг/с
long accel =maxspd*2; //ускорение движение шаг/с*с
uint32_t timer_rum_millis = timer_run*60000;
uint32_t timer_pause_millis = timer_pause*60000;
GStepper< STEPPER2WIRE> stepper1(roundstps, 12, 10, 4);
//*****ФЛАГИ
volatile boolean F_KONC_A; //Флаг концевика А возле мотора
volatile boolean F_KONC_B; //флаг концевика В дальний
volatile boolean F_START; //логический флаг иници
volatile boolean F_TIME; //флаг таймера работы/паузы
uint32_t tmr; //переменная хранения времени
volatile uint32_t debounce;
void Initial_positionA() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик A
if (millis() - debounce >= 200 && digitalRead(2)) {
debounce = millis();
F_KONC_A = 1;
F_START = 1;
}
}
void Initial_positionB() { //ФУНКЦИЯ ОБРАБОТКИ ПРЕРЫВАНИЯ концевик B
if (millis() - debounce >= 200 && digitalRead(3)) {
debounce = millis();
F_KONC_B = 1;
}
}
//****SETUP***************
void setup() {
F_TIME=1;
F_KONC_A=0;
F_KONC_B=0;
F_START=0;
pinMode(2, INPUT_PULLUP);
pinMode(3, INPUT_PULLUP);
digitalWrite(2, LOW);
digitalWrite(3, LOW);
attachInterrupt(0, Initial_positionA, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ А
attachInterrupt(1, Initial_positionB, RISING); //ОБЪЯВЛЕНИЕ ПРЕРЫВАНИЯ B
stepper1.setRunMode(FOLLOW_POS);
stepper1.setMaxSpeed(maxspd);
stepper1.setAcceleration(accel);
Serial.begin(9600);
Serial.println("Hello World!"); // отправить
Serial.println(worksteps); // дистанция в шагах
Serial.println(maxspd); // скорость
Serial.println(accel); // ускорение
Serial.println(roundstps); //шагов в одном обороте
Serial.println(centersteps); //шагов до центра
}
void loop() {
if (millis() - tmr >= (F_TIME ? timer_rum_millis : timer_pause_millis)) {
tmr = millis();
F_TIME = !F_TIME;
}
if (!stepper1.tick() && F_START==0 && F_TIME==1 ){//Если флаг СТАРТ поднят
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(centersteps*2, RELATIVE);//Едем ДАЛЕКОоо вперёд. Костыль такой.
}
static bool dir = true;
if (!stepper1.tick()&& F_TIME==1) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
dir = !dir;
}
if (F_KONC_A ==1 && F_TIME==1){ //если флаг А поднят
stepper1.brake(); //РЕЗКО тормозим, чтобы не сломать концевик
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(-centersteps-(worksteps/3), RELATIVE); //Едем в центр
F_KONC_A = 0; //Флаг А снова готов к труду и обороне
}
if (F_KONC_B ==1 && F_TIME==1){ //если флаг В поднят
stepper1.brake(); //опять же тормозим резко
stepper1.setMaxSpeed(maxspd/2);
stepper1.setTarget(centersteps-(worksteps/2), RELATIVE); //Тут едем в центр но немного ближе, т.к. следующий шаг туда же
F_KONC_B = 0;//Опускаем флаг В
}
}
void loop() {
// тут все хорошо!
if (millis() - tmr >= (F_TIME ? timer_rum_millis : timer_pause_millis)) {
tmr = millis();
F_TIME = !F_TIME;
}
// если работаем то делаем все, что внутри:
if (F_TIME == 1) {
if (!stepper1.tick()) { //Начинаем работать вперёд-назад
stepper1.setMaxSpeed(maxspd);
stepper1.setTarget(dir ? worksteps : -worksteps, RELATIVE);
dir = !dir;
}
...
}
}
ISR(TIMER2_A) { //прерывание по таймеру 2А
MainSt.tick(); //тикаем
}
void loop() {
bus.poll(modbus_array,1); //Used to receive or write value from Master
if (modbus_array[0] ==0) {
MainSt.brake();
} else {
MainSt.setSpeed(modbus_array[0]); //обновляем скорость
}
}
ISR(TIMER2_A) { //прерывание по таймеру 2А
MainSt.tick(); //тикаем
}
void loop() {
bus.poll(modbus_array,1); //Used to receive or write value from Master
if(millis() - LEDTimer > 100) {
LEDTimer = millis();
if (modbus_array[0] ==0) {
MainSt.brake();
} else {
MainSt.setSpeed(modbus_array[0]); //обновляем скорость
}
}}