Гм.. Не въехал..В самом простом виде в прерывании таймера вызывать тики обоих шаговых моторов.
ISR(TIMER1_COMPA_vect) {
bool flag_break = false;
int32_t check = 0;
// здесь происходит движение мотора
// если мотор должен двигаться (true) - ставим новый период таймеру
if (a_stepper.tickManual()) setPeriod(a_stepper.getPeriod());
else stopTimer();
// если нет - останавливаем таймер
if (stat_hal != digitalRead(AZ_HAL_PIN)) flag_hal = true; // проверка на то, что двигатель действительно крутится (датчик холла)
check = a_stepper.getCurrent() - start_pos;
if (abs(check)>41 && flag_hal == false) { // если мотор не крутится, делаем стоп и записываем текущую позицию в EEPROM
stopTimer();
a_stepper.brake();
a_stepper.setCurrent(a_stepper.getCurrent() -(a_stepper.dir*abs(check)));
flag_break = true;
flag_error = true;
} else {
flag_error = false;
}
if (a_stepper.ready() || flag_break == true)
{
a_stepper.disable();
digitalWrite(LED_PIN , LOW);
cur_pos = a_stepper.pos;
flag = 0;
WriteBackup(); // запись текущей позиции в EEPROM
}
}
if (a_stepper.tickManual()) setPeriod(a_stepper.getPeriod());
else stopTimer()
if (a_stepper.tickManual()) // stepper azimut
{
setPeriod(a_stepper.getPeriod());
}
else if (e_stepper.tickManual()) // stepper elevation
{
setPeriod(e_stepper.getPeriod());
}
else
{
stopTimer();
}
ISR(TIMER1_COMPA_vect) {
a_stepper.tick();
b_stepper.tick();
}
А где это делать? В обработчике прерывания таймера, как вы предлагали выше, или где-то в loop?Если просто дергать тик мотора,
А это как реализовать? И чем сиё может грозить? Потери плавности движения не будет?а ускорение и торможение повесить на библиотеку мотра,
// крутим мотор туда-сюда плавно с ускорением
// для синхронного многоосевого движения используй встроенный планировщик траекторий
// папка с примерами Planner и Planner2
#include "GyverStepper.h"
// подключим три мотора
// у первого и второго управление EN не подключаем
GStepper stepper1(100, 2, 3);
GStepper stepper2(100, 4, 5);
GStepper stepper3(100, 6, 7, 8);
void setup() {
// мотор 1 просто вращается
stepper1.setRunMode(KEEP_SPEED);
stepper1.setSpeed(300);
// мотор 2 будет делать sweep по проверке tick
stepper2.setRunMode(FOLLOW_POS);
stepper2.setMaxSpeed(1000);
stepper2.setAcceleration(300);
// мотор 3 будет перемещаться на случайную позицию
stepper3.setRunMode(FOLLOW_POS);
stepper3.setMaxSpeed(1000);
stepper3.setAcceleration(300);
stepper3.autoPower(true);
stepper3.enable();
}
void loop() {
// первый мотор
stepper1.tick();
// второй крутим туды-сюды (-1000, 1000)
if (!stepper2.tick()) {
static bool dir;
dir = !dir;
stepper2.setTarget(dir ? -1000 : 1000);
}
// третий по таймеру
// будет отключаться при остановке
stepper3.tick();
static uint32_t tmr;
if (millis() - tmr > 5000) { // каждые 5 секунд
tmr = millis();
stepper3.setTarget(random(0, 2000)); // рандом 0-2000
}
}
Увы, loop совсем не пустой.. В нём кнопки, энкодер, дисплей, serial для приёма данных от Orbitron.1) Пример похож на то что я описывал. В нем вместо прерывания по таймеру сам цикл loop , пустой цикл может крутиться с частотой 200кГц.
И тут "в пролёте".. На этих пинах энкодер на EncButton. Датчики холла на A0-A1. "Цифровых" пинов не хватило на всё..2) Датчики холла я бы считывал по прерыванию на пинах 2 и 3 (аппаратно)
Чёт плохо воспринимается на родном языке..3) Если одновременное движение двух моторов не требуется, то можно и поочередно делать движение моторов. Будет что то типа этого в прервании:
если положение мотора 1 не соотв движению то
{
шевелить мотором номер 1 с нужным ускорением
}
иначе
{
если положение мотора 2 не соотв движению то
{
шевелить мотором номер 2 с нужным ускорением
}
}
if (a_stepper.tickManual())
{
setPeriod(a_stepper.getPeriod());
}
else
{
if (e_stepper.tickManual()) setPeriod(e_stepper.getPeriod());
}
if (a_stepper.tickManual())
{
setPeriod(a_stepper.getPeriod());
}
else if (e_stepper.tickManual())
{
setPeriod(e_stepper.getPeriod());
}
else
{
stopTimer();
}
не нужен 2х ядерный процессор, нужно учиться разбивать задачи на мелкие неблокирующие кусочки.Увы.. Одноядрёная Arduino Nano...
ISR(TIMER1_COMPA_vect) {
if (stat_hal != digitalRead(AZ_HAL_PIN)) flag_hal = true; // проверка на то, что двигатель действительно крутится (датчик холла)
check = a_stepper.getCurrent() - start_pos;
if (abs(check)>41 && flag_hal == false) { // если мотор не крутится, делаем стоп и записываем текущую позицию в EEPROM
}
if (a_stepper.ready() || flag_break == true)
{
a_stepper.disable();
digitalWrite(LED_PIN , LOW);
WriteBackup(); // запись текущей позиции в EEPROM
}
}
Проект интересный, но он имеет одно существенное отличие - в нём используются серво-двигатели. В моём - шаговые...Вот пример как можно управлять пятью моторами
Ну если устраивает заведомо ущербный подход - дерзайте, что можно тут сказать. Таймер и прерывания это не "серебрянная пуля".нагружать прерывания "допами" - плохое решение, но по-другому пока не получается. Кстати, сейчас как раз обкатываю этот вариант (с "монструозным" обработчиком прерывания).
Если честно, понятия не имею. Этим занимается Gyver Stepper.С какой частотой у вас идут импульсы на моторы на максимальной скорости и на какую частоту настроен таймер?
АналогичноНо с плавным стартом я не знаю как вы выкручиваетесь.
Сейчас там собственно ничего и не осталосьВы так "допишетесь" до того что у вас обработчик прерываний от таймера
ISR(TIMER1_COMPA_vect) {
if (a_stepper.tickManual())
{
setPeriod(a_stepper.getPeriod());
}
else if (e_stepper.tickManual())
{
setPeriod(e_stepper.getPeriod());
}
else
{
stopTimer();
}
}
Их считает библиотека.Шаги мотора вы всё равно не считаете,
Нууу.. Смотря что подразумевать под этим.точность вам не нужна
Нет сенсоров! Только датчик Холла в моторчике. По нему позицию не особо вычислишь..Управляйте только положеним и оборотами от сенсоров
GStepper2<STEPPER2WIRE> a_stepper(5760, 11, 10, 12);
GStepper2<STEPPER2WIRE> e_stepper(5760, 11, 10, 12);
GStepper2<STEPPER2WIRE> a_stepper(5760, 5, 8, 9);
GStepper2<STEPPER2WIRE> e_stepper(5760, 5, 8, 10);
GStepper2<STEPPER2WIRE> a_stepper(5760, 5, 8, 9);
GStepper2<STEPPER2WIRE> e_stepper(5760, 5, 8, 10);
Никак не могу одолеть..Предыдущая "копия" GStepper держит "свой" DIR.
И получается так, что если предыдущее направление было "по часовой", а текущее "против", текущий поворот выполняется в ложном направлении..
Не понял.. Как дёрнуть DIR? Так что ли?попробуйте уже с нужной копией GStepper 2 раза дернуть DIR
void stepper_turn(int st) {
if (st == 0 && a_stepper.getStatus() == 0 && TruAzim != ComAzim)
{
a_stepper.enable();
a_stepper.dir = a_stepper.dir;
a_stepper.dir = a_stepper.dir;
a_flag_hal = false;
a_stepper.setTargetDeg(ComAzim*-1,ABSOLUTE);
az_cur_pos = a_stepper.getCurrent();
az_start_pos = az_cur_pos;
az_stat_hal = digitalRead(AZ_HAL_PIN);
setPeriod(a_stepper.getPeriod());
startTimer();
}
Эммм. А разве так можно?a_stepper.dir = !a_stepper.dir;
Если dir будет равен "-1", !a_stepper.dir сделает из него "0". Никак не "1".int8_t dir; // направление (1, -1)
Не прокатило..a_stepper.dir =~a_stepper.dir;