Опубликовано

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

По материалам книги “Arduino. Большая книга рецептов“, 3-е изд. (авторы Джепсон Брайан, Марголис Майкл, Уэлдин Николас Роберт) (глава 8. Управление
электродвигателями)

Arduino. Большая книга рецептов, 3-издание

ЗАДАЧА

Требуется управлять направлением и скоростью вращения щеточного электродвигателя, используя сигнал обратной связи с датчиков. Например, организовать управление скоростью и направлением электродвигателей с помощью двух фотодатчиков таким образом, чтобы шасси робота двигалось по направлению к источнику света.

РЕШЕНИЕ

Двигатели для этого решения подключаются так же, как показано на рис. 8.10, но к схеме добавлены два фоторезистора (или фототранзистора — подробную информацию по фототранзисторам см. в разд. 1.6), как показано в схеме на рис. 8.12. Конденсаторы номиналом 0,1 мкФ на электродвигателях должны быть керамическими.

C:\Users\acer\Documents\#Electronics\Магазин электроники\фрагменты из книг\2788. Arduino Cookbook. Recipes to Begin, Expand, and Enhance\verstka\pic\08\8.12.png

Рис. 8.12. Управление двумя щеточными электродвигателями с помощью датчиков

Скетч для работы с этой схемой приводится в листинге 8.12. Скетч отслеживает уровень освещенности на каждом из фотодатчиков и управляет электродвигателями таким образом, чтобы направлять шасси к датчику с более высоким уровнем освещенности.

Листинг 8.12. Управление двумя электродвигателями с помощью фотодатчиков

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
/*
* Скетч Brushed_H_Bridge_Direction
* Управляет электродвигателями на основании сигналов фотодатчиков,
* направляя шасси робота к источнику света
*/
 
int leftPins[] = {5,7,4}; // Один контакт для ШИМ (скорость),
// два контакта для направления левого двигателя
int rightPins[] = {6,3,2}; // То же, для правого двигателя
const int MIN_PWM = 64; // Это значение может быть в диапазоне от 0 до MAX_PWM
const int MAX_PWM = 128; // Это значение может быть в диапазоне от 50 до 255
const int leftSensorPin = A0; // Контакты для подключения фотодатчиков
const int rightSensorPin = A1;
 
int sensorThreshold = 0; // Пороговый уровень освещенности на датчике
// для вращения электродвигателя
void setup()
{
 
for(int i=1; i < 3; i++)
{
pinMode(leftPins[i], OUTPUT);
pinMode(rightPins[i], OUTPUT);
}
}
 
void loop()
{
int leftVal = analogRead(leftSensorPin);
int rightVal = analogRead(rightSensorPin);
if(sensorThreshold == 0) // Датчики откалиброваны?
{
// Если нет, калибруем до уровня освещенности несколько выше
// среднего уровня освещенности окружающей среды
sensorThreshold = ((leftVal + rightVal) / 2) + 100 ;
}
if( leftVal > sensorThreshold || rightVal > sensorThreshold)
{
// Если уровень освещенности достаточно высокий
// для движения вперед
setSpeed(rightPins, map(rightVal,0,1023, MIN_PWM, MAX_PWM));
setSpeed(leftPins, map(leftVal ,0,1023, MIN_PWM, MAX_PWM));
}
}
 
void setSpeed(int pins[], int speed )
{
if(speed < 0)
{
digitalWrite(pins[1],HIGH);
digitalWrite(pins[2],LOW);
speed = -speed;
}
else
{
digitalWrite(pins[1],LOW);
digitalWrite(pins[2],HIGH);
}
analogWrite(pins[0], speed);
}

Обсуждение работы решения и возможных проблем

Скетч управляет скоростью вращения двух электродвигателей, реагируя на уровень освещенности, определяемый двумя фотодатчиками. Фотодатчики установлены таким образом, что повышение уровня освещенности на одной стороне шасси
повышает скорость вращения электродвигателя на другой стороне шасси. В результате шасси будет поворачиваться по направлению к более высокому уровню освещенности. При одинаковом уровне освещенности с обеих сторон шасси будет двигаться вперед по прямой линии. При слишком низком уровне освещенности шасси останавливается.

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

Сигнал с фотодатчиков подается на аналоговые контакты A0 и A1 платы Arduino,
с которых он считывается функцией analogRead() (эта функция подробно рассматривается в разд. 6.3). В начале исполнения скетча измеряется уровень фоновой освещенности, и это пороговое значение используется для определения минимального уровня освещенности, необходимого, чтобы начинать движение шасси. К измеренному пороговому уровню освещенности добавляется запас величиной в 100 еди­ниц, чтобы небольшие изменения уровня фоновой освещенности не вызывали движения. Значение уровня освещенности, возвращенное функцией analogRead(), преобразовывается с помощью функции map() в значение ШИМ. Константе MIN_PWM следует задать приблизительное значение ШИМ, при котором шасси должно начинать движение (слишком низкие значения не дадут достаточного крутящего момента. Точное значение надо будет определить экспериментальным путем). А константе MAX_PWM нужно задать значение (до 255), определяющее максимальную скорость шасси.

Скорость вращения электродвигателей управляется функцией setSpeed(). Для управления направлением вращения каждого электродвигателя используются два контакта платы Arduino и еще один контакт — для управления скоростью вращения. Номера этих контактов хранятся в массивах leftPins и rightPins для левого и правого двигателей соответственно. В первом элементе массива хранится номер контакта для управления скоростью вращения, а в двух других — для управления направлением.

В любом из решений, в котором используется микросхема H-моста L293, вместо нее можно альтернативно применить микросхему TB6612FNG. На рис. 8.13 показано подключение к плате Arduino микросхемы H-моста TB6612 (установленной на адаптерной плате артикул 713 компании Pololu).

C:\Users\acer\Documents\#Electronics\Магазин электроники\фрагменты из книг\2788. Arduino Cookbook. Recipes to Begin, Expand, and Enhance\verstka\pic\08\8.13.png

Рис. 8.13. Подключение адаптерной платы микросхемы H-моста TB6612 производства компании Pololu

Количество контактов платы Arduino, задействованных для управления схемой, можно уменьшить, добавив в схему дополнительный компонент для управления контактами направления H-моста. Такой компонент представляет собой транзистор или логический элемент для инвертирования логического уровня, подаваемого на другой ввод H-моста, позволяя использовать только один контакт платы Arduino для управления направлением вращения электродвигателя. Соответствующую принципиальную схему можно найти на веб-сайте Arduino, но также существуют и готовые решения — например, шилд H-моста Arduino Motor Shield (артикул 7630049200371, https://store.arduino.cc/arduino-motor-shield-rev3) или шилд Ardumoto компании SparkFun (артикул DEV-09213). Оба эти шилда используют микросхему L298, которая является более мощной альтернативой микросхеме L293. Эти шилды вставляются в гнездовые разъемы платы Arduino и требует только подключения к электродвигателю и его источнику питания.

В листинге 8.13 приводится скетч для управления электродвигателями с помощью шилда Arduino Motor Shield (контакты A0 и A1 платы Arduino задействованы для измерения тока, поэтому для управления в скетче используются контакты A2 и A3).

Листинг 8.13. Управление электродвигателями с помощью шилда Arduino Motor Shield

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/*
* Скетч Brushed_H_Bridge_Direction sketch for motor shield
* Управляет электродвигателями на основании сигналов фотодатчиков,
* направляя шасси робота к источнику света
*/
int leftPins[] = {3,12}; // Один контакт для ШИМ-сигнала (скорость),
// один — для направления
int rightPins[] = {11,13};
const int MIN_PWM = 64; // Это значение может быть в диапазоне
// от 0 до MAX_PWM
const int MAX_PWM = 128; // Это значение может быть в диапазоне от 50 до 255
const int leftSensorPin = A2; // Аналоговые контакты для подключения фотодатчиков
const int rightSensorPin = A3;
int sensorThreshold = 0; // Пороговый уровень освещенности на датчике
// для вращения электродвигателя
void setup()
{
pinMode(leftPins[1], OUTPUT);
pinMode(rightPins[1], OUTPUT);
}
 
void loop(){
int leftVal = analogRead(leftSensorPin);
int rightVal = analogRead(rightSensorPin);
if(sensorThreshold == 0) // Датчики откалиброваны?
{
// Если нет, калибруем до уровня освещенности несколько выше
// среднего уровня освещенности окружающей среды
sensorThreshold = ((leftVal + rightVal) / 2) + 100 ;
}
if( leftVal > sensorThreshold || rightVal > sensorThreshold)
{
// Если уровень освещенности достаточно высокий для движения вперед
setSpeed(rightPins, map(rightVal,0,1023, MIN_PWM, MAX_PWM));
setSpeed(leftPins, map(leftVal, 0,1023, MIN_PWM, MAX_PWM));
}
}
void setSpeed(int pins[], int speed )
{
if(speed < 0)
{
digitalWrite(pins[1], HIGH);
speed = -speed;
}
else
{
digitalWrite(pins[1], LOW);
}
analogWrite(pins[0], speed);
}

Функция loop() здесь идентична этой функции скетча из листинге 8.12. Функция setSpeed() скетча содержит меньший объем кода, чем ее предыдущая версия, поскольку аппаратное обеспечение шилда позволяет использовать только один контакт платы Arduino для управления направлением вращения электродвигателя.
В шилде Ardumoto используются другие контакты, поэтому для работы с ним код скетча нужно откорректировать следующим образом:

1
2
3
int leftPins[] = {3, 2}; // Один контакт для ШИМ-сигнала (скорость),
// один — для направления
int rightPins[] = {11, 4};

В листинге 8.14 приводится код скетча, реализующий эту же функциональность на основе шилда Adafruit Motor Shield V2 (https://oreil.ly/kFygk), подключение которого показано на рис. 8.14. В скетче используется библиотека Adafruit_MotorShield, которая устанавливается стандартным способом с помощью Менеджера библиотек.

Шилд Adafruit Motor Shield V2 поддерживает подключение четырех электродвигателей, но в скетче из листинге 8.14 предусмотрено, что два электродвигателя подключены к разъемам шилда 3 и 4.

Листинг 8.14. Управление электродвигателями с помощью шилда Adafruit Motor Shield V2

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
/*
* Скетч Brushed_H_Bridge_Direction sketch for Adafruit Motor shield
* Управляет электродвигателями на основании сигналов фотодатчиков,
* направляя шасси робота к источнику света
*/
#include <Wire.h>
#include <Adafruit_MotorShield.h> // Подключаем библиотеку Adafruit_MotorShield
// Создаем экземпляр объекта шилда
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_DCMotor *leftMotor = AFMS.getMotor(1);
Adafruit_DCMotor *rightMotor = AFMS.getMotor(2);
const int MIN_PWM = 64; // Это значение может быть в диапазоне от 0 до MAX_PWM
const int MAX_PWM = 128; // Это значение может быть в диапазоне от 50 до 255
const int leftSensorPin = A0; // Аналоговые контакты для подключения фотодатчиков
const int rightSensorPin = A1;
int sensorThreshold = 0; // Пороговый уровень освещенности на датчике
// для вращения электродвигателя
void setup()
{
AFMS.begin(); // Инициализируем экземпляр шилда частотой
// по умолчанию 1,6 КГц
}
 
void loop()
{
int leftVal = analogRead(leftSensorPin);
int rightVal = analogRead(rightSensorPin);
if(sensorThreshold == 0) // Датчики откалиброваны?
{
// Если нет, калибруем до уровня освещенности несколько выше
// среднего уровня освещенности окружающей среды
sensorThreshold = ((leftVal + rightVal) / 2) + 100 ;
}
if( leftVal > sensorThreshold || rightVal > sensorThreshold)
{
// Если уровень освещенности достаточно высокий для движения вперед
setSpeed(rightMotor, map(rightVal,0,1023, MIN_PWM, MAX_PWM));
setSpeed(leftMotor, map(leftVal ,0,1023, MIN_PWM, MAX_PWM));
}
}
void setSpeed(Adafruit_DCMotor *motor, int speed )
{
if(speed < 0)
{
motor->run(BACKWARD);
speed = -speed;
}
else
{
motor->run(FORWARD);
}
motor->setSpeed(speed);
}

C:\Users\acer\Documents\#Electronics\Магазин электроники\фрагменты из книг\2788. Arduino Cookbook. Recipes to Begin, Expand, and Enhance\verstka\pic\08\8.14.png

Рис. 8.14. Подключение шилда Adafruit Motor Shield V2

В случае использования иного шилда, чем только что рассмотренные, надо будет уточнить по его справочному листку, что значения в скетче совпадают с контактами, используемыми для сигналов управления скоростью (ШИМ) и направления.

Дополнительная информация

Подробная информация по адаптерной плате компании Pololu для H-моста TB6612FNG приводится в справочном листке на нее (https://oreil.ly/bD_83).

Дополнительная информация по шилду Ardumoto компании SparkFun приводится на его веб-странице (https://oreil.ly/XZTCY).

Дополнительная информация по шилду Arduino Motor Shield приводится на его веб-странице (https://oreil.ly/2gKoX).

Дополнительная информация по шилду Adafruit Motor Shield V2 приводится на его веб-странице (https://oreil.ly/T19_o).

Добавить комментарий