Простой пример неблокирующей задержки шагового двигателя (миллис)?
Я пытаюсь получить простую неблокирующую замену для:
digitalWrite(stepPinX, HIGH);
delayMicroseconds(500);
digitalWrite(stepPinX, LOW);
delayMicroseconds(500);
Вот что я пробовал, и шаговый двигатель остается неподвижным:
const int dirPinX = 0;
const int stepPinX = 2;
unsigned long startMicros = micros();
unsigned long currentMicros;
const unsigned long period = 500;
void setup()
{
pinMode(stepPinX, OUTPUT);
pinMode(dirPinX, OUTPUT);
digitalWrite(dirPinX, HIGH);
}
void loop()
{
stepX();
}
void stepX()
{
currentMicros = micros(); // получаем текущее "время" (время с начала программы)
if (currentMicros - startMicros >= period) //проверяем, истек ли период
{
digitalWrite(stepPinX, HIGH);
}
if ((currentMicros - startMicros >= period) && (currentMicros - startMicros <= period*2))
{
digitalWrite(stepPinX, LOW);
}
startMicros = currentMicros;
}
Есть предложения, как это исправить? (Я не хочу использовать такую библиотеку, как Accelstepper. Я хочу использовать миллис/микрос.)
@adamaero, 👍1
Обсуждение2 ответа
Ваша функция stepX()
выглядит следующим образом:
void stepX()
{
currentMicros = micros();
// условно делаем что-то..
startMicros = currentMicros;
}
Поскольку нет ничего, что могло бы его заблокировать, он всегда будет выполняться очень
быстрый. Это означает, что к моменту возврата функции startMicros
будет очень близко к текущему времени. Затем, при следующем вызове,
currentMicros - startMicros
будет очень маленьким, намного меньше, чем
период
, и условный код никогда не будет выполняться.
Решение состоит в том, чтобы изменить значение startMicros
: вместо
представляющее время последнего вызова stepX()
, пусть оно представляет
время начала последнего шага. Для этого вам нужно только сбросить его
при завершении шага:
void stepX()
{
currentMicros = micros();
if (currentMicros - startMicros < period) { // 1-я фаза
digitalWrite(stepPinX, HIGH);
} else if (currentMicros - startMicros < 2*period) { // 2-я фаза
digitalWrite(stepPinX, LOW);
} else { // полный цикл
startMicros = currentMicros;
}
}
`
if ((currentMicros - startMicros >= период) && (currentMicros - startMicros <= период*2))
{
digitalWrite(stepPinX, LOW);
startMicros = текущийMicros;
}`
Как это? Тот же результат, что и раньше., @adamaero
@adamaero: Ой! Действительно, я не заметил, что логика условий «если» была неправильной. Отредактировал ответ., @Edgar Bonet
Похоже, что значения startMicros
и currentMicros
всегда остаются близкими друг к другу из-за использования micros()
до и после условного блока. Поскольку условный блок выполняется быстрее, чем 500 микросекунд, в результате никогда не происходит вход в условный блок.
Отсюда вы можете пойти двумя путями,
- Подход 01. Поэкспериментируйте с переменными кода и выполните отладку в режиме реального времени, чтобы увидеть, что и где не так. Затем настраивайте, отлаживайте, повторяйте, пока не достигнете желаемого результата.
- Подход 02. Переосмыслите выполнение кода и упростите код от входа до выхода, выполняя последовательные шаги.
Поскольку ваше действие может быть упрощено до операции переключения каждые 500 микросекунд
, мы можем выполнить рефакторинг кода, аналогичного тому, что я написал,
bool toggle_flag = false;
unsigned long last_toggle;
const unsigned long period = 500;
void setup() {
last_toggle = micros();
pinMode(stepPinX, OUTPUT);
}
void loop() {
// Проверяем, истекло ли время
if (micros() - last_toggle >= period ) {
// Шаг 01: сброс last_toggle с текущим временем
last_toggle = micros();
// Шаг 02: проверьте флаг переключения и выполните действие переключения
(toggle_flag) ? digitalWrite(stepPinX, HIGH) : digitalWrite(stepPinX, LOW);
// Шаг 03: переключите переменную флага переключения после нашего действия
toggle_flag = !toggle_flag;
}
}
Надеюсь, этот ответ поможет.
- Часовой механизм на основе шагового двигателя с DS3231
- Как справиться с rollover millis()?
- Использование millis() и micros() внутри процедуры прерывания
- ардуино - миллисекунды ()
- Accelstepper запустить степпер назад
- Кнопка с таймером переключения и функцией сброса времени + светодиод обратной связи
- Использовать timer0, не влияя на millis() и micros().
- Торговый автомат Arduino для мониторинга ввода монет в слот во время ожидания ввода пользователя
второй оператор
if
будет выполняться очень редко... зачем иметь отдельный операторif
для двух выходных состояний?, @jsotolaотредактированный вопрос и программа, @adamaero
сделать только одно
if (currentMicros - startMicros >= период)
... отслеживать состояниеstepPinX
, @jsotola