Вращение двигателем и одновременное снятие показаний

Необходимо выполнение управлять шаговым двигателем и в это время снимать показания температуры. Для управления шаговым двигателем используется драйвер A4899. Пробовал код с библиотекой accelerator.h, так же пробовал переделать код управления данным драйвером с использованием dalay под milis, но двигатель прекращает вращение. при снятии показаний. Смотрел библиотеку GiverSteppers2, пишут что можно использовать параллельно с другими процессами, но не могу ее соединить с драйвером A4899. Подскажите как можно реализовать когда во время вращения двигателя снимались показания датчика?

Ну и где эти “росчерки пера”?

Представьте себя на месте микроконтроллера. Как бы лично Вы попытались одновременно управлять двигателем и снимать показания с датчика? Вот точно так же должен делать и контроллер.

Таймеры отменили что ли ?

Вот пример кода, управление драйвером шагового двигателя через драйвер a4899, dirPin задает направление вращения, stepPin - периодичность импульсов, задает скорость вращения. Но в stepPin используется dalay, заменить на millis не получается, двигатель не вращается. Как победить данную ситуацию? пробовал с millis и с использованием библиотеки, не вращается двигатель.

uint32_t myTimer1, myTimer2, myTimer3;

int raw = 0;
float temp = 0;

const int dirPin = 11;
const int stepPin = 10;
const int stepsPerRevolution = 200;

void setup() {
  pinMode( A0, INPUT );
  pinMode(stepPin, OUTPUT);
  pinMode(dirPin, OUTPUT);
}
void loop() {
  if (millis() - myTimer1 >= 1000) {   
    myTimer1 = millis(); 
    // Вращение             
    digitalWrite(dirPin, LOW); 
  for(int x = 0; x < stepsPerRevolution; x++)
  {
    digitalWrite(stepPin, HIGH);
    delayMicroseconds(1000);
    digitalWrite(stepPin, LOW);
    delayMicroseconds(1000);
  }
  }
  if (millis() - myTimer2 >= 500) {   
    myTimer2 = millis();              
    raw = analogRead(A0);
    temp = ( raw/1023.0 )*5.0*1000/10;
    if (temp < 15)
        digitalWrite(13, HIGH);
    else
        digitalWrite(13, LOW);
    delay(1000); 
  }
  
}

Возьмите аксельстеппер и вызывайте run() постоянно, а в условии на стр. #16 задавайте дистанцию через move().

Вставляю из примера. Пример работает, а так двигатель не работает. Может что то не так делаю?

#include <AccelStepper.h>

uint32_t myTimer1, myTimer2, myTimer3;

int raw = 0;
float temp = 0;


// Устанавливаем выводы
const int dirPin = 11;
const int stepPin = 10;
int i = 0;
// Определение тип интерфейса двигателя
#define motorInterfaceType 1
// Создаем экземпляр
AccelStepper myStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
  pinMode( A0, INPUT );
  myStepper.setMaxSpeed(1000);
  myStepper.setAcceleration(50);
  myStepper.setSpeed(200);
  myStepper.moveTo(100);
}
void loop() {
  if (millis() - myTimer1 >= 1000) {   
    myTimer1 = millis(); 
    // Вращение             
    if (myStepper.distanceToGo() == 0) 
  {
    myStepper.moveTo(-myStepper.currentPosition());
  }
  // Передвинуть на 1 шаг
  myStepper.run();
  }
  if (millis() - myTimer2 >= 500) {   
    myTimer2 = millis();              
    raw = analogRead(A0);
    temp = ( raw/1023.0 )*5.0*1000/10;
    if (temp < 15)
        digitalWrite(13, HIGH);
    else
        digitalWrite(13, LOW);
    delay(1000); 
  }
  
}

void loop() {
  // Передвинуть на 1 шаг
  myStepper.run();  // <<<<< "вызывать постоянно" - это вот так

  if (millis() - myTimer1 >= 1000) {   
    myTimer1 = millis(); 
    // Вращение             
    if (myStepper.distanceToGo() == 0)   {   myStepper.moveTo(-myStepper.currentPosition()); }
  }

  if (millis() - myTimer2 >= 500) {   
    myTimer2 = millis();              
    raw = analogRead(A0);
    temp = ( raw/1023.0 )*5.0*1000/10;
   //  Здесь нужен гистерезис
    if (temp < 15)   digitalWrite(13, HIGH);
    if (temp > 16)   digitalWrite(13, LOW);
    delay(1000);   // <<<<< От этого нужно избавиться
  }
}

Есть же автоформатирование в IDE !
Вот ваш код:

#include <AccelStepper.h>

uint32_t myTimer1, myTimer2, myTimer3;

int raw = 0;
float temp = 0;


// Устанавливаем выводы
const int dirPin = 11;
const int stepPin = 10;
int i = 0;
// Определение тип интерфейса двигателя
#define motorInterfaceType 1
// Создаем экземпляр
AccelStepper myStepper(motorInterfaceType, stepPin, dirPin);

void setup() {
    pinMode( A0, INPUT );
    myStepper.setMaxSpeed(1000);
    myStepper.setAcceleration(50);
    myStepper.setSpeed(200);
    myStepper.moveTo(100);
}
void loop() {
    if (millis() - myTimer1 >= 1000) {
        myTimer1 = millis();
        // Вращение
        if (myStepper.distanceToGo() == 0)
        {
            myStepper.moveTo(-myStepper.currentPosition());
        }
        // Передвинуть на 1 шаг
        myStepper.run();
    }
    if (millis() - myTimer2 >= 500) {
        myTimer2 = millis();
        raw = analogRead(A0);
        temp = ( raw / 1023.0 ) * 5.0 * 1000 / 10;
        if (temp < 15)
            digitalWrite(13, HIGH);
        else
            digitalWrite(13, LOW);
        delay(1000);
    }

}

34 строка выполняется раз в секунду - это так задумано ?

34, нет так не задумано, взял из примера. Хорошо, сделаю автоформатирование. Через час попробую ваш код

Я никакого своего кода не постил - я ваш отформатировал !

Если хотите неблокирующий код - не используйте циклы for и while

Вот этот кусок надо переписать через миллис и все заработает

Судя по предыдущим сообщениям, вы не понимаете, что и для чего меняете. Постарайтесь понять, на что влияют в плане задержек вносимые вами изменения.
Если у вас есть рабочий пример для вашего шагового двигателя, и вы добавите туда ваш код измерения температуры (но без delay(1000)), То этот код будет вызываться раз в 500 мс, выполняться при вызове меньше 1 мс, и не должен оказывать заметного влияния на исходный рабочий пример.

  if (millis() - myTimer2 >= 500) {   
    myTimer2 = millis();              
    raw = analogRead(A0);
    temp = ( raw/1023.0 )*5.0*1000/10;
    if (temp < 15)
        digitalWrite(13, HIGH);
    else
        digitalWrite(13, LOW);
    // delay(1000);  Это здесь не нужно !!!!
  }
1 лайк

Вы прежде чем давать оценку знаниям других людей, лучше бы предложили решение! Код писал удаленно от рабочего места, поэтому да в этом коде допустил ошибку. Но если бы вы попробовали сами заменить на millis, даже при увеличении длительности увидели что такой подход не работает. Простите если грубо ответил.

у всех работает, а у вас нет?
Покажите код, как вы пробовали менять на миллис - попробуем найти ошибки

Если бы вы понимали, то знали бы, что тупо заменить delay() на millis() не выйдет - они работают по разному

1 лайк

Пробую делать так, после вращения в одну сторону программа перестает работать, показания не снимаются и процесс вращения не повторяется.

void loop() {
    
  // Передвинуть на 1 шаг
  myStepper.run();  // <<<<< "вызывать постоянно" - это вот так

  if (millis() - myTimer1 >= 500) {   
    myTimer1 = millis(); 
    // Вращение             
    myStepper.moveTo(2000); 
    }
  

  if (millis() - myTimer2 >= 500) {   
    myTimer2 = millis();              
    raw = analogRead(A0);
    temp = ( raw/1023.0 )*5.0*1000/10;
   //  Здесь нужен гистерезис
    if (temp < 15)   digitalWrite(13, HIGH);
    if (temp > 16)   digitalWrite(13, LOW);
      // <<<<< От этого нужно избавиться
      Serial.print(raw);
  }

Это что значит: myStepper.moveTo(2000) ?

Вот он доехал до 2000 и стоит там …

А как через данную библиотеку задать постоянное вращение?