Создание класса для работы с двигателем постоянного тока
Серия-статей: Arduino, использование двигателей постоянного тока #3
Соберем схему из двух двигателей:
Создадим класс MotorClass
и добавим в него перменные для текущего состояния двигателя (скорость и направление вращения). Кроме того создадим переменнные, которые будут использоваться при плавном изменении скорости
У нашего класса будет несколько методов:
MotorClass(pE, pI)
– конструктор класса, здесь мы будем указывать, какими выходами будем управлять двигателем
RunMotor(motorpower)
– изменяем внутренние переменные (мощность, направление) и непосредственно управляем двигателем .
SetSpeed(newspeed)
– устанавливаем новую скорость. Мощность меняется в диапазоне 0..255, что не всегда удобно. Поэтому будем задавать скорость в % от максимума
SetSpeed(newspeed, smooth)
– устанавливаем новую скорость, делаем это не стразу, а плавно – устанавливаем соотвтетсвующие переменные, а непосредствено скорость будет меняться функцией UpdateSpeed()
UpdateSpeed()
– здесь будет проверяться временный интервал и меняться скорость, если предыдущим методом были установлены соответствующие переменные. Помещаем эту функцию в loop()
Вот что у нас получилось:
/* Пользовательский класс управления двигателями постоянного тока с поддержкой плавного изменения скорости */
class MotorClass
{
public:
byte pinE; // Номер цифрового выхода для управления скоростью – должен поддерживать ШИМ
byte pinI; // Номер цифрового выхода для управления направлением вращения
boolean SpeedChanging; // Включен ли режим ускорения двигателя (обрабатывается функцией UpdateSpeed())
unsigned long StartTimer; // Таймер для плавного пуска
int StartTimeStep; // Интервал изменения мощности двигателя, в мс
int StartPowerStep; // Один шаг изменения мощности двигателя
int ReqPower // До какого занчения будет меняться мощность двигателя
int Power; // Мощность двигателя (0 - остановка, 255 - полная мощность)
int Direction; // Направление вращения
MotorClass(int pE, int pI) // Конструктор класса. Первый аргумент - номер пина управления скоростью, второй - направлением
{
pinE=pE; // Задаем управляющие пины для скорости
pinI=pI; // И направления вращения
pinMode (pinE, OUTPUT); // Задаем работу соответствующих пинов в качестве выходов
pinMode (pinI, OUTPUT);
Power=0; // по умолчанию двигатель стоит
SpeedChanging=false; // по умолчанию двигатель не ускоряется
}
void RunMotor(int motorpower) // Задаем скоротсь и направления вращения двигателя
// Отрицательное значение - вращение в обратную сторону
{
Direction=(motorpower>0)?HIGH:LOW; // Если указано положительная скорость - на выход направления подается сигнал HIGH
digitalWrite(pinI,Direction); // для отрицательной - LOW
digitalWrite(pinE,abs(Power)); // Подаем на выход управления скоростью сигнал, который соответствует нужной скорости
}
void SetSpeed(int newspeed) // Устанавливаем скорость двигателя в процентах от максимума.
{
Power=(int)newspeed/2.55; // Поскольку скорость меняется от 0 дл 100 %, а мощность - в диапазоне от 0 до 255,
// вычисляем необходимое значение мощности
RunMotor(Power);
}
void SetSpeed(int newspeed, int smooth) // Плавно меняем скорость двигателя в процентах от максимума.
// Отрицательное значение - вращение в обратную сторону
// Плавность изменения регулируется значнением smooth (время на один шаг изменения скорости, в мс)
{
ReqPower=(int)newspeed/2.55; // Поскольку скорость меняется от 0 дл 100 %, а мощность - в диапазоне от 0 до 255, вычисляем нужное значение
if (ReqPower>=Power) // В какую сторону будет меняться мощность?
StartPowerStep=1; // увеличиваться на 1 (1/255 от полной)
else
StartPowerStep=-1; // уменьшаться на 1 (1/255 от полной)
StartTimeStep=smooth;
StartTimer=millis(); // Начинаем отсчет времени для изменения скорости
SpeedChanging=true; // устанавливаем режим изменения скорости, для последующей обработки в функции UpdateSpeed()
}
void UpdateSpeed()
{
if (SpeedChanging) // Если установлен режим изменения скорости
if ((millis()-StartTimer)>= StartTimeStep) // Если с предыдущего изменения скорости прошло больше времени, чем задано
{
if (Power!=ReqPower) // Пока не достигли нужной скорости
{
Power+=StartPowerStep; // меняем скорость
RunMotor(Power); // даем команду двигателю
StartTimer=millis(); // устанавливаем таймер для начала отсчета для следующего измеенния мощности
}
else // Если нужная скорость достигнута
SpeedChanging=false; // Выключаем режим изменения скорости
}
}
};
MotorClass M1(5,4); // Первый двигатель управляется выходами 5 и 4 (скорость и направление соответственно)
MotorClass M2(6,7);// Второй двигатель управляется выходами 6 и 7
void setup()
{
M1.SetSpeed(50); //Первый двигатель - включить на 50% скорости
M1.SetSpeed(-100, 2); // Второй двигатель - включить на 100% скорости в обратную сторону с плавным разгоном
}
void loop()
{
M1.UpdateSpeed(); // Обработать изменения скорости первого двигателя
M2.UpdateSpeed(); // Обработать изменения скорости второго двигателя
}
При запуске программы первый двигатель максимально быстро разгонится до половины максимальной скорости. А вот второй будет вращаться в обратную сторону, причем на разгон с нуля до максимума у него уйдет пол секунды (255 шагов изменения через 2мс) Управление двигателями независимое, причем добавление еше нескольких двигателей не вызовет затрудений. На нашем motor-shield нет больше выводво для подключения моторов, но нам ничто не мешает использовать два одинаковых (единственное ограничение – сврху контроллера можно установить только один, второй нужно будет подключать проводами к соответствующим выходам. Но для таких случаев сушествуют четырехканальные motor-shield, в которых используются две и более микромхемы L298P:
Такая плата уже может управлять четырьмя двигателями постоянного тока, т.е можно, например, сделать полностью независимое управление каждого колеса четырехколесного робота. Единственный недостаток- в таком варианте используются практически все цифровые выходы обычной платы UNO. Но эта проблема решается либо использованием более функциональной платы (например, Arduino MEGA с 54 цифровыми выходами ) или подключением motor-shielda через L2P.