Простой пример неблокирующей задержки шагового двигателя (миллис)?

Я пытаюсь получить простую неблокирующую замену для:

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. Я хочу использовать миллис/микрос.)

, 👍1

Обсуждение

второй оператор if будет выполняться очень редко... зачем иметь отдельный оператор if для двух выходных состояний?, @jsotola

отредактированный вопрос и программа, @adamaero

сделать только одно if (currentMicros - startMicros >= период) ... отслеживать состояние stepPinX, @jsotola


2 ответа


1

Ваша функция 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


1

Похоже, что значения 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;

  }

}

Надеюсь, этот ответ поможет.

,