Плавное управление двигателем постоянного тока с помощью 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]
@Jānis, 👍2
Обсуждение2 ответа
Лучший ответ:
Я предлагаю использовать другую логику в вашей программе. Сначала я бы разделил различные части проекта:
- Часть кода, которая считывает 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
слишком низким, изменение скорости будет заикаться
Если нет, то вам, вероятно, придется использовать что-то вроде 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
- Как справиться с rollover millis()?
- Использование millis() и micros() внутри процедуры прерывания
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Вопрос о различных способах подключения платы драйвера двигателя L298N к Arduino и двигателям и их питания.
- Обратное вращение шагового двигателя
- Неиспользуемые контакты в Arduino L293D motor shield?
- Arduino uno + cnc Shield v3 + драйвер шагового двигателя A4988 + AccelStepper?
вам нужно больше состояний, на 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