Расширенные коды библиотеки AccelStepper!

Я пытался выяснить, как эта библиотека может одновременно запускать несколько шаговых двигателей, и я увидел эту важную функцию под названием...

void AccelStepper::setOutputPins(uint8_t mask)
{
    uint8_t numpins = 2;
    if (_interface == FULL4WIRE || _interface == HALF4WIRE)
    numpins = 4;
    else if (_interface == FULL3WIRE || _interface == HALF3WIRE)
    numpins = 3;
    uint8_t i;
    for (i = 0; i < numpins; i++)
    digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));
}

почему используется uint8_t? а что такое маска? и это строка:

digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));

отправляет сигнал шага на несколько шаговых двигателей?

, 👍0

Обсуждение

Как использовать несколько степперов зависит от ваших потребностей. Вы можете просто определить несколько объектов AccelStepper и последовательно вызвать их метод запуска. Или вы можете использовать класс multistepper, который также является частью библиотеки AccelStepper., @chrisl

Мне нужно отредактировать библиотеку, чтобы получить то, что я хочу... Я хочу получить отзывы о моих двигателях, показать данные энкодера в реальном времени на последовательном мониторе... попробовать и протестировать различные методы управления... Я должен знать, как эти коды работай., @2012User

Итак, ваш вопрос не о запуске нескольких степперов, а о понимании этой функции?, @chrisl

Точно. Я использовал библиотеку... Я хочу настроить ее., @2012User


1 ответ


Лучший ответ:

1

Функция setOutputPins() устанавливает контакты для импульса для одиночного шагового двигателя. В зависимости от используемого шагового двигателя необходимо установить разное количество контактов (обычные драйверы шаговых двигателей имеют 2 контакта, ULN2003 и его собратья - 4) по-разному. Для этого функция сначала определяет количество контактов для использования с помощью переменной-члена _interface класса.

Параметр mask содержит состояния выводов. Каждый бит представляет один контакт. Если соответствующий бит установлен в 1, контакт будет установлен в активное состояние. В противном случае он будет установлен в неактивное состояние. Обычно активное состояние (как я назвал его здесь) — ВЫСОКОЕ, неактивное состояние — НИЗКОЕ. Но при работе с разными шаговыми драйверами некоторые выводы могут работать с инвертированной логикой. Таким образом, значение (LOW или HIGH) инвертируется, если контакт помечен как инвертированный в массиве _pinInverted. Эта логика находится в строке

digitalWrite(_pin[i], (mask & (1 << i)) ? (HIGH ^ _pinInverted[i]) : (LOW ^ _pinInverted[i]));

Идиома условие ? выражение : выражение представляет встроенное условие if. Если условие оценивается как true, используется первое выражение, в противном случае — второе выражение. С маской & (1 << i) мы проверяем, установлен ли i-й бит в mask. Если да, используем следующее выражение: HIGH ^ _pinInverted[i]. Здесь побитовый оператор XOR ^ используется для инвертирования значения, если для _pinInverted[i] установлено значение 1 (и, таким образом, вывод помечается как инвертированный). Если _pinInverted[i] равен нулю, значение останется прежним. Обработка значения LOW аналогична.

Чтобы лучше понять это, вы можете узнать больше о побитовых операторах, если вы еще этого не сделали.

почему [параметр mask] использует uint8_t?

uint8_t — это наименьший тип, который можно использовать: 1 байт. Поскольку каждый бит представляет один вывод, а библиотека поддерживает степперы с 4 выводами, максимум требуется только 4 бита. Таким образом, достаточно использовать наименьший тип с 8 битами.

Отправляет ли эта линия сигнал шага на несколько шаговых двигателей?

Нет, это установка контактов одного шагового двигателя. Каждый экземпляр класса AccelStepper представляет один шаговый двигатель. Таким образом, каждая функция в нем также взаимодействует только с одним двигателем. Вы действительно не объяснили, как вы хотите добавить функциональность обратной связи. Но вы не должны изменять класс AccelStepper для обработки нескольких двигателей. Это не имеет смысла для меня. Каждый двигатель должен управляться индивидуально, и этот класс предназначен для того, чтобы заключить в себе работу, стоящую за этим. В этом и заключается идея создания класса для этого.

Я предполагаю, что вы хотите управлять несколькими двигателями, каждый из которых имеет собственную петлю обратной связи. Итак, вам сначала нужно изменить класс AccelStepper для поддержки этого цикла обратной связи. То, как это делается, во многом зависит от вашего типа обратной связи. Также метод setOutputPins() не подходит для этого. Это функция очень низкого уровня. Вам нужно начать дальше в цепочке вызовов, возможно, в методе step() или методе runSpeed() (это действительно зависит от того, как вы хотите обрабатывать обратную связь). ). Также вам нужно написать методы для настройки и обработки ввода кодировщиков. Вам может потребоваться настроить таймеры и/или прерывания для их правильного чтения.

Для поддержки нескольких шаговых двигателей вы все равно можете обратиться к классу MultiStepper. Вы можете изменить его, чтобы он соответствовал вашим изменениям в AccelStepper, или написать свой собственный класс-оболочку. Это в основном зависит от того, как вы хотите, чтобы несколько степперов вели себя.

,