Ускорение двигателя постоянного тока с помощью ШИМ
Я не знаю, почему это было так сложно для меня, но я пытаюсь контролировать ускорение двигателя постоянного тока 10 В с помощью Arduino UNO и H-моста L298n. Использование регулируемого источника питания 12 В для питания двигателя
Ни за что на свете я не могу добиться плавного ускорения/замедления для этого. Я хочу, чтобы двигатель двигался вперед и назад с помощью потенциометра, замедляясь по мере достижения положений "0" и "10". Это работает, но не очень гладко
const byte motorUp = 4;
const byte motorDown = 5;
const byte motorPWM = 6;
const int speed1 = 85;
const int speed2 = 92;
const int speed3 = 100;
const int speed4 = 110;
const int speed5 = 130;
const int speed6 = 190;
int state = 0;
const byte wiper = A0; //Положение фейдера относительно GND (аналог 0)
double faderMax = 0; //Значение, считываемое максимальным положением фейдера (0-1023)
double faderMin = 0; //Значение, считываемое минимальной позицией фейдера (0-1023)
byte motorSpeed = 255; // Поднять, если фейдер слишком медленный (0-255)
byte tolerance = 10; // Поднять, если фейдер слишком шаткий (0-1023)
void setup() {
Serial.begin(250000);
pinMode(motorDown, OUTPUT);
pinMode(motorUp, OUTPUT);
pinMode(motorPWM, OUTPUT);
analogWrite(motorPWM, motorSpeed);
calibrateFader(); }
void calibrateFader() {
digitalWrite(motorUp, HIGH);
analogWrite(motorPWM, 155);
delay(300);
digitalWrite(motorUp, LOW);
faderMax = analogRead(wiper) - tolerance;
digitalWrite(motorDown, HIGH);
analogWrite(motorPWM, 155);
delay(300);
digitalWrite(motorDown, LOW);
faderMin = analogRead(wiper) + tolerance;
delay(2500); }
void loop () {
moveMotorUp();}
void moveMotorUp() {
while (analogRead(A0) <= 100) {
analogWrite(motorPWM, speed1);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 100) && (analogRead(A0) <= 200)) {
analogWrite (motorPWM, speed2);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 200) && (analogRead(A0) <= 300)) {
analogWrite (motorPWM, speed3);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 300) && (analogRead(A0) <= 400)) {
analogWrite (motorPWM, speed4);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 400) && (analogRead(A0) <= 500)) {
analogWrite (motorPWM, speed5);
digitalWrite (motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 500) && (analogRead(A0) <= 600)) {
analogWrite (motorPWM, speed6);
digitalWrite (motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 600) && (analogRead(A0) <= 700)) {
analogWrite (motorPWM, speed5);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 700) && (analogRead(A0) <= 800)) {
analogWrite (motorPWM, speed4);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 800) && (analogRead(A0) <= 900)) {
analogWrite (motorPWM, speed3);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while ((analogRead(A0) > 900) && (analogRead(A0) <= 1000)) {
analogWrite (motorPWM, speed2);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW); }
while (analogRead(A0) > 1000) {
analogWrite (motorPWM, speed1);
digitalWrite(motorUp, HIGH);
digitalWrite(motorDown, LOW);
moveMotorDown(); } }
void moveMotorDown() {
while (analogRead(A0) > 1000) {
analogWrite(motorPWM, speed1);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 900) && (analogRead(A0) <= 1000)) {
analogWrite (motorPWM, speed2);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 800) && (analogRead(A0) <= 900)) {
analogWrite (motorPWM, speed3);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 700) && (analogRead(A0) <= 800)) {
analogWrite (motorPWM, speed4);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 600) && (analogRead(A0) <= 700)) {
analogWrite (motorPWM, speed5);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 500) && (analogRead(A0) <= 600)) {
analogWrite (motorPWM, speed6);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 400) && (analogRead(A0) <= 500)) {
analogWrite (motorPWM, speed5);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 300) && (analogRead(A0) <= 400)) {
analogWrite (motorPWM, speed4);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 200) && (analogRead(A0) <= 300)) {
analogWrite (motorPWM, speed3);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 100) && (analogRead(A0) <= 200)) {
analogWrite (motorPWM, speed2);
digitalWrite (motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while ((analogRead(A0) > 10) && (analogRead(A0) <= 100)) {
analogWrite(motorPWM, speed1);
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW); }
while (analogRead(A0) <= 10) {
digitalWrite(motorDown, HIGH);
digitalWrite(motorUp, LOW);
moveMotorUp(); } }
Надеюсь, все проще - Есть идеи? Спасибо
@zRockafellow, 👍1
Обсуждение1 ответ
Я думаю, вам нужно думать немного по-другому. Вместо того чтобы "Двигайся с такой скоростью, пока не доберешься сюда", тебе нужно больше думать о том, "Где я? Куда я хочу попасть? Как далеко это отсюда?
По сути, чем дальше вам нужно идти, тем быстрее вы хотите идти. Чем ближе вы подходите к своему целевому значению, тем медленнее вы хотите двигаться.
Проще говоря, вы хотите преобразовать расстояние между вашей текущей и целевой позициями в пропорциональную скорость.
Возьмем одну переменную: целевое значение, до которого вы хотите добраться. Возьмите одно чтение: текущее местоположение фейдера. Вычтите одно из другого.
Возьмите знак результата - он определяет, в каком направлении вы хотите повернуть двигатель. Возьмите "абсолютное" (abs(...)
) значение результата - это расстояние, на котором вы находитесь от своей цели. Разделите это абсолютное значение на коэффициент скорости, чтобы оно находилось в пределах диапазона вашего ШИМ, или ниже, если вы хотите идти медленнее. Установите скорость двигателя на этот результат.
Итак, если вы хотите добраться до 0 и в данный момент читаете 1000 с фейдера, то:
- Разница = 0 - 1000 = -1000
- Знак отрицательный, поэтому установите направление "вниз".
- Расстояние-
abs(-1000)
или 1000. - Разделить на 4 (макс. АЦП - 1023, макс. ШИМ-255- 1023/4 = 255) = 250
- Установите скорость на 250
Затем мгновение спустя вы, возможно, читаете 738 из АЦП - так что на этот раз:
- Разница = 0 - 738 = -738
- Знак отрицательный, поэтому установите направление "вниз".
- Расстояние-
abs(-738)
или 738. - Разделить на 4 (макс. АЦП - 1023, макс. ШИМ-255- 1023/4 = 255) = 184
- Установите скорость на 184
Продолжайте делать это до тех пор, пока не достигнете своего целевого значения (или в пределах определенного допуска), после чего остановитесь и дождитесь выбора нового целевого значения (или автоматически измените целевое значение в соответствии с вашей демонстрацией развертки - если 0, то установите значение 1023. Если 1023, то установите значение 0).
Затем этот метод позволяет вам перейти непосредственно к любому выбранному вами значению с замедлением по мере приближения к этой цели.
Привет Маенко, Спасибо за подробности! Я пытался понять, как внедрить ПИД-контроль в этот проект. Но я до сих пор не знаю, как его настроить. Я пытался следовать вашим инструкциям, но вы потеряли меня в "Возьми знак результата"., @zRockafellow
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
- Как устранить шум от вентилятора 12 В с ШИМ-управлением на низкой скорости
- Как управлять 6 шаговыми двигателями с помощью Arduino?
- Не могу контролировать скорость двигателей постоянного тока с помощью analogWrite()
- Как Arduino Uno может поддерживать до 12 сервоприводов, если у него всего 6 цифровых выводов ШИМ?
- L298N издает звуковые сигналы и дает сбой при получении определенных значений AnalogWrite
- AnalogWrite не работает - при попытке контролировать скорость двигателя постоянного тока
- Контакты ШИМ серводвигателей, Arduino Uno
Там у вас есть хорошая бесконечно рекурсивная пара функций. У вас закончится место в стеке, если вы оставите его работать на некоторое время., @Majenko
Мне это тоже казалось очень неэффективным. Знаете ли вы какие-нибудь библиотеки, которые имеют ускорение? Мне жаль, что я не могу найти что-то вроде библиотеки AccelStepper для шаговых двигателей. К сожалению, на этот раз я ограничен двигателем постоянного тока., @zRockafellow
@zRockafellow Существует несколько библиотек, которые обеспечивают интерполяцию значений между значениями с помощью различных механизмов (например, [Ramp](https://www.arduino.cc/reference/en/libraries/ramp/)). Все, что можно сделать с помощью рекурсии, можно сделать и без нее-скорее всего, вы хотите иметь конечный автомат., @Dave Newton