Угловая скорость двигателя постоянного тока, управляемая потенциометром
Я создал установку, в которой потенциометр управляет двигателем постоянного тока, а ток через двигатель постоянного тока контролируется Н-мостом. Принцип следующий: Когда циферблат потенциометра установлен в среднее положение, двигатель выключен. Вращение потенциометра по часовой стрелке приведет к вращению двигателя в одном направлении со скоростью, определяемой смещением потенциометра от средней точки: чем больше смещение от средней точки, тем больше скорость вращения двигателя. Если потенциометр вращать против часовой стрелки, в направлении от средней точки, двигатель будет вращаться в направлении, противоположном предыдущему; опять же, со скоростью, определяемой степенью смещения потенциометра от средней точки.
Цикл имеет три функции: HB_12EN — для включения драйверов, HB_1A — первый вход драйвера, а HB_2A — второй вход драйвера (контакты H-моста 1, 2 и 7 соответственно) согласно этой таблице данных: http://www.ti.com/lit/ds/symlink/sn754410.pdf< /п>
Подводя итог их функциям: HB_12EN позволяет подавать напряжение на устройство, управляемое H-мостом (в данном случае двигатель), и модулируется импульсной волной. HB_1A и HB_2A управляют потоком тока через двигатель, устанавливая его угловую скорость. HB_1A, установленный HIGH, и HB_2A, установленный LOW, направляют ток через двигатель в одну сторону, а HB1A, установленный LOW, и HB_2A, установленный HIGH, направляют ток через двигатель в другую сторону.
Цикл:
//ВЫХОДЫ
int const HB_12EN = 9; //вывод ШИМ
int const HB_1A = 2;
int const HB_2A = 3;
//ВХОДЫ
int const POT_MOT = 0; //A0, аналог 0
//ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ
unsigned int pot_val = 0; //Значение АЦП от потенциометра
unsigned int grp_num = 1;
pot_val = analogRead(POT_MOT);
grp_num = setMotSwitch(HB_12EN, HB_1A, HB_2A, pot_val, grp_num);
setMotSpeed(HB_12EN, pot_val, grp_num);
Две (небиблиотечные) функции:
unsigned int setMotSwitch(int const motor_reg, int const first_motor, int const sec_motor, unsigned int pot_value, unsigned int group_num) //grp 0: 0-383; грп 1: 384-639; группа 2: 640-1023
{
if (pot_value >= 0 && pot_value < 384)
{
if (group_num != 0)
{
digitalWrite(motor_reg, LOW);
digitalWrite(first_motor, HIGH);
digitalWrite(sec_motor, LOW);
group_num = 0;
}
}
else if (pot_value > 383 && pot_value < 640)
{
if (group_num != 1)
{
digitalWrite(motor_reg, LOW);
digitalWrite(first_motor, LOW);
digitalWrite(sec_motor, LOW);
group_num = 1;
}
}
else if (pot_value > 639 && pot_value <= 1023)
{
if (group_num != 2)
{
digitalWrite(motor_reg, LOW);
digitalWrite(first_motor, LOW);
digitalWrite(sec_motor, HIGH);
group_num = 2;
}
}
else
{
digitalWrite(motor_reg, LOW);
digitalWrite(first_motor, LOW);
digitalWrite(sec_motor, LOW);
group_num = 0;
}
return group_num;
}
void setMotSpeed(int const motor_reg, unsigned int pot_value, unsigned int group_num)
{
unsigned int mot_speed = 0;
if (group_num == 0)
{
mot_speed = map(pot_value, 0, 383, 255, 0);
mot_speed = constrain(mot_speed, 0, 255);
analogWrite(motor_reg, mot_speed);
}
else if (group_num == 1)
{
if (pot_value > 500 && pot_value < 523)
{
digitalWrite(motor_reg, HIGH); //торможение
}
else
{
digitalWrite(motor_reg, LOW);
}
}
else if (group_num == 2)
{
mot_speed = map(pot_value, 640, 1023, 0, 255);
mot_speed = constrain(mot_speed, 0, 255);
analogWrite(motor_reg, mot_speed);
}
}
Я попробовал поступить следующим образом: Поскольку потенциометр будет генерировать входной сигнал АЦП с 1024 состояниями, я разделил эти 1024 состояния на 8 групп, первые три группы, охватывающие первые 384 состояния (0–383), соответствуют направлению двигателя постоянного тока (скажем, против часовой стрелки), что представляет собой разные скорости вращения (игнорируя проблемы сопоставления «многие к одному»). Средние 2 группы, 256 состояний (384-639), соответствуют стационарному двигателю. Последние три группы, 384 состояния (640-1023), соответствуют вращению двигателя в другую сторону (в данном примере по часовой стрелке). Входы АЦП должны быть преобразованы в аналоговые выходы с 256 возможными состояниями (0–255), поэтому я отображаю каждый диапазон соответствующим образом; для 0-383 отображение должно быть обратным, поэтому ввод 383 соответствует вводу 0. Средний диапазон (384-639) является стационарным, но я попытался сделать небольшой «поддиапазон» в середине. «Диапазон торможения», я полагал, что это достигается путем установки обоих входов H-моста на НИЗКИЙ уровень. Сопоставление диапазона 640–1023 – от 640 до 0 и от 1023 до 255.
Надеюсь, это имеет смысл. Кажется, это работает, проблема, с которой я столкнулся, заключается в том, что двигатель, кажется, достигает большей скорости в одном направлении по сравнению с другим: максимальная скорость вращения, создаваемая двигателем, больше, когда потенциометр находится на максимуме в одном направлении по сравнению с другой. Я почти уверен, что приведенный выше код дает «четное» отображение потенциометра на двигатель в обоих направлениях. Значит, это как-то связано с аппаратным обеспечением? И следует ли этого ожидать в такого рода установках?
Любая помощь будет оценена по достоинству. Если у кого-нибудь есть какие-либо советы о том, как лучше всего объединить вход потенциометра или аналогичный вход с выходом двигателя, дайте мне знать. Функция «торможения» также немного сбивает с толку.
@Jay Lin, 👍1
Обсуждение2 ответа
Лично я бы не стал заморачиваться с "группами". Просто сделайте простую математику:
int velocity = analogRead(POT_MOT) - 512;
velocity
теперь дает вам значение от -512 до +511.
bool dir = (velocity >= 0);
dir
теперь имеет значение true
для положительного значения (0 считается положительным) или false
для отрицательного.
velocity = abs(velocity);
скорость
теперь становится положительной, если она отрицательная.
Теперь у вас есть две переменные: dir
, которая задает направление, и velocity
, которая задает скорость.
Теперь вы можете «компенсировать» это:
velocity = map(velocity, 0, 512, -128, 255);
velocity
теперь изменено, чтобы соответствовать диапазону от -128 до 255. Все, что выше 0, является допустимой скоростью, все, что ниже, является «мертвой зоной» и останавливает двигатель.
if (velocity <= 0) {
// Если отрицательно или ноль, остановитесь
digitalWrite(motor_reg, LOW);
digitalWrite(first_motor, LOW);
digitalWrite(sec_motor, LOW);
} else {
if (dir) { // Pot был положительным
analogWrite(motor_reg, velocity);
digitalWrite(first_motor, LOW);
digitalWrite(sec_motor, HIGH);
} else { // Банк был отрицательным
analogWrite(motor_reg, velocity);
digitalWrite(first_motor, HIGH);
digitalWrite(sec_motor, LOW);
}
}
Отрегулируйте отрицательное значение на карте, чтобы изменить размер «мертвой зоны».
Я бы разбил это на три или, по крайней мере, на две части:
1) вызов изменения скорости двигателя; 2) призыв считать показания счетчика потенциала; 3) вызов для преобразования настройки измерителя потенциала в скорость двигателя, необязательно.
код будет выглядеть так:
pot_setting = potsetting_read(); //прочитать настройку горшка
speed_setting = pot2spd(pot_setting); //преобразуем настройку потенциометра в скорость двигателя
motor_setspeed(speed_setting); //установить скорость двигателя
Нетрудно разобраться в каждой из трех функций.
Для новичка более сложным из трех является тот, который устанавливает скорость двигателя. Есть много способов сделать это, и я лично предпочитаю использовать прерывания таймера.
Основная конструкция заключается в последовательном прохождении набора состояний выводов, где длительность каждого перехода состояния контролируется прерыванием таймера. Изменяя скорость срабатывания прерывания таймера, вы изменяете скорость, с которой выводы меняют свое состояние, а значит, и скорость двигателя.
- AnalogWrite не работает - при попытке контролировать скорость двигателя постоянного тока
- Ускорение двигателя постоянного тока с помощью ШИМ
- Цифровой потенциометр и регулятор скорости двигателя
- Помощь с ускорением ПИД-двигателя постоянного тока
- Использование прерывания внутреннего таймера для чтения аналогового датчика
- Вопрос, касающийся использования Arduino и MIDI
- когда 3 компонента на Arduino nano работают вместе, один из них не работает
- Управление скоростью вентилятора с помощью библиотеки Arduino PID
Я ценю все отзывы на данный момент. Хотелось бы добавить, что сам код является продуктом ряда факторов. Частично это ограничено учебником: я пытаюсь ограничить код тем, что описано в учебнике, над которым я работаю. Другие факторы включают в себя: I) я хотел использовать ряд функций и II) я хотел написать программу, которая бы обходила настройку контактов H-Bridge на каждой итерации. Моя основная мотивация для публикации заключается в том, что я хотел бы знать, является ли проблема, с которой я столкнулся со скоростью двигателя, проблемой кодирования или, возможно, проблемой оборудования., @Jay Lin