Ускорение двигателя постоянного тока с помощью ШИМ

Я не знаю, почему это было так сложно для меня, но я пытаюсь контролировать ускорение двигателя постоянного тока 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(); } }

Надеюсь, все проще - Есть идеи? Спасибо

, 👍1

Обсуждение

Там у вас есть хорошая бесконечно рекурсивная пара функций. У вас закончится место в стеке, если вы оставите его работать на некоторое время., @Majenko

Мне это тоже казалось очень неэффективным. Знаете ли вы какие-нибудь библиотеки, которые имеют ускорение? Мне жаль, что я не могу найти что-то вроде библиотеки AccelStepper для шаговых двигателей. К сожалению, на этот раз я ограничен двигателем постоянного тока., @zRockafellow

@zRockafellow Существует несколько библиотек, которые обеспечивают интерполяцию значений между значениями с помощью различных механизмов (например, [Ramp](https://www.arduino.cc/reference/en/libraries/ramp/)). Все, что можно сделать с помощью рекурсии, можно сделать и без нее-скорее всего, вы хотите иметь конечный автомат., @Dave Newton


1 ответ


2

Я думаю, вам нужно думать немного по-другому. Вместо того чтобы "Двигайся с такой скоростью, пока не доберешься сюда", тебе нужно больше думать о том, "Где я? Куда я хочу попасть? Как далеко это отсюда?

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

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

Возьмем одну переменную: целевое значение, до которого вы хотите добраться. Возьмите одно чтение: текущее местоположение фейдера. Вычтите одно из другого.

Возьмите знак результата - он определяет, в каком направлении вы хотите повернуть двигатель. Возьмите "абсолютное" (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