Плавное управление двигателем постоянного тока с помощью millis

Итак, задача состоит в том, чтобы управлять двигателем постоянного тока 12в.

С помощью первой кнопки вы можете добавить скорость двигателя на определенный шаг скорости.

С помощью второй кнопки вы можете замедлить скорость двигателя на определенный шаг.

С помощью третьей кнопки вы не можете ускорить двигатель до максимума, но проблема в том, что я должен сделать это плавно. Например, я нажимаю третью кнопку, и мотор начинает вращаться все быстрее и быстрее, пока не достигнет максимальной скорости. Но теперь, когда я нажимаю на эту кнопку, мотор прыгает до максимума, и я не знаю почему. Нет никакой гладкости.

Я не могу использовать задержку, это должен сделать миллис.

[code]
int speed = 0;
int motor = 5,
    fasterbutton = 7, slowerrbutton = 4, tillmaxbutton = 2;
unsigned long previousMillis = 0;
const long interval = 100;
const long smoothinterval = 5000;
boolean faster, slower, tillend;
int begginingspeed;
const int step = 3;
const int maxspeed = 255;

void setup() {
  pinMode(2, INPUT_PULLUP);
  pinMode(4, INPUT_PULLUP);
  pinMode(5, OUTPUT);
  pinMode(7, INPUT_PULLUP);
  Serial.begin(9600);
}
void loop() {
  tillend = digitalRead(2);
  slower = digitalRead(4);
  faster = digitalRead(7);


  //кнопка Nr 7 запускает двигатель постоянного тока и ускоряется
  if (faster == !HIGH && begginingspeed < maxspeed) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      begginingspeed += step;
      if (faster == !HIGH && speed < 1 ) {
        Serial.print('\n');
        Serial.print("MOTOR ON" );
      }
      analogWrite(motor, begginingspeed);
      Serial.print('\n');
      Serial.print("Speed = " );
      speed = begginingspeed * 100 / maxspeed;
      Serial.print(speed, DEC);
      previousMillis = currentMillis;
    }
  }


  //кнопка Nr 4 замедляет работу двигателя постоянного тока
  else if (slower == !HIGH && begginingspeed > 0) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis >= interval) {
      begginingspeed -= step;
      analogWrite(motor, begginingspeed);
      Serial.print('\n');
      Serial.print("Speed = " );
      speed = begginingspeed * 100 / maxspeed;
      Serial.print(speed, DEC);
      if (slower == !HIGH && speed < 1 ) {
        Serial.print('\n');
        Serial.print("MOTOR OFF" );
      }
      previousMillis = currentMillis;
    }
  }


  //кнопка Nr 2 для плавного крепления двигателя постоянного тока до макс.
  if (tillend == !HIGH && begginingspeed > 0) {
    unsigned long currentMillis = millis();
    if (currentMillis - previousMillis <= interval) {
      for (begginingspeed = begginingspeed; begginingspeed <= 255; begginingspeed += step)
        analogWrite(motor, begginingspeed);
    }
    previousMillis = currentMillis;
  }

}
[/code]

Shematic

, 👍2

Обсуждение

вам нужно больше состояний, на 1 логическое значение больше, скажем, is_accelerating. Вы устанавливаете это значение true при нажатии кнопки и устанавливаете его false при максимальной скорости. Он в основном заменяет `быстрее == ! ВЫСОКИЙ", так что вам не нужно удерживать нажатой кнопку., @dandavis

@dandavis в моем коде мне не нужно удерживать кнопку, чтобы достичь максимальной скорости., @Jānis

цикл for в if (tillend == !HIGH выполняется мгновенно. завершите цикл for, затем удерживайте кнопку _tillend_, чтобы плавно увеличить скорость. затем создайте мой мод, чтобы вам не нужно было удерживать кнопку., @dandavis

@dandavis тебе нужно больше состояний, на 1 логическое значение больше, скажем, is_accelerating. Вы устанавливаете это значение true при нажатии кнопки и устанавливаете его false при максимальной скорости. Он в основном заменяет faster == !HIGH, так что вам не нужно удерживать нажатой кнопку. Так что не могли бы вы объяснить мне эту часть, я не понимаю, как объявить все это., @Jānis

@dandavisint итак, я внес изменения, да, теперь мне не нужно удерживать кнопку, но скорость все равно подскакивает, плавности нет, @Jānis

else if (tillend ==!HIGH && начальная скорость> 0) { беззнаковый длинный текущий миллион = миллис(); if (текущий миллион - предыдущий миллион> = 5000) { if (tillend==!HIGH){ is_accelerating= true; } начальная скорость += шаг; } if (начальная скорость = максимальная скорость){ is_accelerating= false; } analogWrite(двигатель, начальная скорость); previousMillis = currentMillis; } }, @Jānis


2 ответа


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

0

Я предлагаю использовать другую логику в вашей программе. Сначала я бы разделил различные части проекта:

  • Часть кода, которая считывает 3 кнопки и устанавливает / увеличивает / уменьшает переменную на основе нажатий кнопок, а также
  • часть кода, которая принимает переменную в качестве заданного значения и перемещает выход PWM (analogWrite()) вверх или вниз до тех пор, пока заданное значение не будет достигнуто. (Таким образом, заданное значение - это целевое значение скорости / ШИМ)

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


Давайте сначала рассмотрим вторую часть (усиление ШИМ-сигнала вверх и вниз). Нам нужна переменная, которая содержит текущее значение ШИМ, и переменная, которая содержит текущее заданное значение (для обоих мы начинаем с нуля, поэтому двигатель здесь стоит на месте:

int current_speed = 0;
int speed_setpoint = 0;

Нам также нужна переменная timestamp для использования millis() для регулярной настройки выхода PWM в соответствии с заданным значением и соответствующим интервалом (здесь как define). Кроме того, мы также определяем приращение, с которым значение ШИМ должно увеличиваться на каждом образце:

unsigned long motor_timestamp;
#define MOTOR_SAMPLE_INTERVAL  100
#define MOTOR_SAMPLE_INCREMENT 3

Все это мы делаем в глобальном масштабе. Теперь в функции loop мы сначала проверяем наличие millis() и метки времени (которая дает нам регулярный интервал выборки для скорости двигателя), а затем проверяем, выше или ниже текущей скорости, чем заданное значение, и соответственно меняем current_speed. В конце мы записываем на выход значение current_speed:

if(millis() - motor_timestamp > MOTOR_SAMPLE_INTERVAL){
    if(current_speed < speed_setpoint){
        current_speed += MOTOR_SAMPLE_INCREMENT;
    } else if(current_speed > speed_setpoint){
        current_speed -= MOTOR_SAMPLE_INCREMENT;
    }
    analogWrite(motor, current_speed);
    motor_timestamp += MOTOR_SAMPLE_INTERVAL;
 }

Итак, теперь мы current_speed двигателя будем следовать speed_setpoint, но будем только увеличивать или уменьшать скорость, установленную с помощью MOTOR_SAMPLE_INTERVAL и MOTOR_SAMPLE_INCREMENT. Новая целевая скорость просто устанавливается путем присвоения переменной speed_setpoint нового значения. Вышеприведенный код позаботится о том, чтобы добраться до него.


Теперь давайте посмотрим на первую часть (чтение кнопок для изменения переменной). В вашем текущем коде вам нужно удерживать кнопку нажатой, чтобы значение изменилось. Из вашего текста можно догадаться, что вам нужно поведение клика (1 шаг в скорости для 1 нажатия кнопки, что означает нажатие и отпускание кнопки). Для этого я предлагаю использовать библиотеку Bounce2, которая будет обрабатывать кнопки - особенно дебоунсинг - для вас:

#include <Bounce2.h>
Bounce bounce = Bounce();

void setup(){
    bounce.attach( BOUNCE_PIN, INPUT_PULLUP );
    // ИНТЕРВАЛ ДЕБОУНСА В МИЛЛИСЕКУНДАХ
    bounce.interval(5); // интервал в мс
}

void loop(){
    bounce.update();
    if(bounce.fell()){
        // Ручка кнопки нажмите здесь
    }
}

Внутри оператора if(bounce.fell()) вы будете обрабатывать действие для нажатия кнопки, в данном случае: обновление переменной speed_setpoint . Определите значение инкремента для кнопок и выполните инкремент /декремент в операторах if. В глобальном масштабе:

#define BUTTON_SPEED_INCREMENT 4

В функции loop():

if(slower_bounce.fell()){
    speed_setpoint -= BUTTON_SPEED_INCREMENT;
}
if(faster_bounce.fell()){
    speed_setpoint += BUTTON_SPEED_INCREMENT;
}
if(tillend_bounce.fell()){
    speed_setpoint = maxspeed;
}

Теперь вам нужно собрать все это воедино. Я оставляю это на ваше усмотрение. Затем вы можете настроить поведение по своему вкусу, изменив определения.


Обратите внимание на следующие моменты:

  • Двигатель будет ускоряться линейно. Это должно быть тебе к лицу.

  • Код перезапустит ШИМ-волну при каждом MOTOR_SAMPLE_INTERVAL. Это нормально для двигателя, когда интервал значительно превышает интервал ШИМ. Когда вы выбираете слишком низкий интервал (например, однозначные миллисекунды), вам нужно поместить вызов analogWrite() в операторы if с приращением speed_setpoint. Это займет еще 1 утверждение, но решит проблему.

  • Если вы выберете MOTOR_SAMPLE_INTERVAL слишком низким, изменение скорости будет заикаться

,

0

Если нет, то вам, вероятно, придется использовать что-то вроде H-моста. L298N - хорошее место для начала. Вы можете использовать ШИМ для управления его скоростью и постепенностью.

https://www.browncountylibrary.org/wp-content/uploads/2018/03/arduino_dc_motors.pdf

Вот соответствующая документация

,

я только что нажал CTRL + T, надеюсь, это поможет. кнопка 3 наиболее плавно добавляет скорость двигателю постоянного тока, поэтому, когда я нажимаю ее, она должна перейти на максимальную скорость (255) от текущей скорости., @Jānis

Да, спасибо, поэтому при программировании имена переменных должны быть короткими и простыми и старайтесь не использовать избыточные переменные. Это поможет отладить процесс намного быстрее, а также будет менее обременительным для вашего компилятора., @N0m4d

спасибо за совет, я новичок в программировании, так что да: D заранее спасибо, @Jānis

да, кнопка работает, но она не плавная, она просто "прыгает" на максимум, вот в чем дело. Я знаю, как заставить двигатель постоянного тока работать на максимальной скорости, но я не знаю, как заставить его плавно увеличивать скорость после нажатия 3-й кнопки, @Jānis

Вы пробовали увеличить задержку, скажем, до 100? из моего кода выше `задержка (50)`, @N0m4d

и, к сожалению, я не могу использовать задержку, @Jānis

Вы пробовали увеличить задержку, скажем, до 100? из моего кода выше задержка (50) - Да, не сработало, просто перескочил на максимум, @Jānis

да, схема верна.Это должно быть сделано с помощью диода, транзистора и кнопок., @Jānis

@N0m4d почему именно H-мост должен быть необходим для плавного изменения скорости?, @chrisl