+7-960-0655211 (Билайн)
+7-987-4207734 (МТС)
интернет-магазин
доставка по России и СНГ
работаем с 2010 года

Управление несколькими сервоприводами на Raspberry Pi для механизма поворота/наклона PI-камеры

ГлавнаяИнформацияСтатьи

Управление несколькими сервоприводами на Raspberry Pi для механизма поворота/наклона PI-камеры



В этом обучающем проекте будет рассмотрено управление несколькими сервоприводами для позиционирования PI-камеры с помощью механизма поворота/наклона с использованием Raspberry Pi 3 Model B и программы на Python.



У подобной камеры с механизмом поворота/наклона множество применений. Это может быть система видеонаблюдения или робот с дистанционным управлением. У Raspberry PI вычислительной мощности достаточно и что бы реализовать относительно несложную обработку изображений и к примеру, реализовать автоматическое слежение за движущимся объектом или поиск нужного объекта.  И многое другое. Примеры реализации некоторых подобных вещей будут рассмотрены в будущих обучающих проектах.

Шаг 1: компоненты

Основные используемые детали:
1 x Raspberry Pi 3b
1 x RPI-камера OV5647 (5-мегапикселей, 1080p)
2 x сервопривод SG90
1 x самодельное или готовое крепление поворота/наклона для SG90
2 x резистор 1кОм, опционально

Шаг 2: ШИМ

С помощью ШИМ (широтно-импульсная модуляция) можно управлять мощностью нагрузки, яркостью свечения светодиода, скоростью вращения моторов, регулировать напряжение в преобразователях напряжения и т.д.

Принцип работы следующий. Генератор создаёт прямоугольные импульсы определённой частоты. Эта частота постоянна, а длительность импульса можно изменять. К примеру, если нужно управлять яркостью свечения светодиода, для этого можно использовать ЦАП (цифро-аналоговый преобразователь, DAC). У Raspberry Pi нет аналогового выхода (ЦАП), вместо него можно использовать ШИМ. Чем больше длительность импульса, тем больше среднее значение напряжения и наоборот, чем меньше длительность импульса, тем меньше среднее напряжение.





В случае со светодиодом, если частота будет слишком низкая, визуально светодиод будет мигать, а не менять яркость.

Кроме уже упомянутого, ШИМ используется и при управлении некоторых сервоприводов, контроллеров оборотов коллекторных или BLDC моторов и прочих вещах, используемых в моделизме и робототехнике. В данном случае нас интересуют сервоприводы. Угол, на который будет проворачиваться сервопривод задаётся длительностью импульса.



Шаг 3: схема подключения



Сервоприводы будут подключены к внешнему источнику питания 5В, а управляющий провод к Raspberry Pi. Цвета проводов у различных сервоприводов могут отличаться, в данном случае для SG90 распиновка следующая:

  • коричневый - "земля"
  • красный - "+5В"
  • желтый - сигнальный

К GPIO 17 подключается управляющий провод сервопривода наклона, к GPIO 27 сервопривод поворота. Дополнительно для защиты выводов Raspberry Pi можно использовать резистор 1кОм.

Если Вы также будете использовать отдельные источники питания для Raspbery Pi и сервоприводов, обязательно соедините их земли, в противном случае электроника может выйти из строя. В данном случае земля от внешнего источника питания для сервоприводов подключена к выводу земли (возле GPIO 17) на Raspberry Pi.

Шаг 4: калибровка сервоприводов

У SG90 от различных производителей (могут выпускаться со своей наклейкой, например, "FeeTech FS90" или как в оригинальной "TowerPro SG90") параметры сервопривода могут немного отличаться. Если питающее напряжение обычно до 4.8-5в, частота управляющих импульсов 50Гц (т.е. период следования сигнала 20мс), а угол, на который проворачивается сервопривод примерно 180градусов, то длительность управляющего импульса очень часто отличается.

К примеру длительность управляющего импульса может быть от 1мс до 2мс или от 0.75мс до 1.85мс или от 0.5мс до 2.4мс и т.д. Для сервоприводов от одного производителя, длительность управляющего импульса тоже может немного отличаться. Калибровка - это определение, какие длительности импульсов соответствуют минимальной и максимальной длительность управляющего импульса и каким углам проворачивания вала сервопривода они соответствуют.



Под нейтральным положением может подразумеваться то положение, в которое проворачивается вал при средней длительности импульса (в данном случае это 1.5мс). Обозначать в градусах могут как на картинке выше, т.е. нейтральное 90 градусов и крайние положения как 0 и 180. Или под нейтральным подразумевать 0 градусов, а крайние обозначать как -90 и +90. С обозначениями углов это условность, могут быть и другие варианты. В данном случае будет использоваться первый вариант.

Для программирования позиции сервопривода с использованием Python очень важно знать соответствующий коэффициент заполнения (англ. duty cycle) для вышеуказанных позиций (задаётся в процентах). К примеру длительность импульса 2мс, при периоде следования сигнала 20мс это коэффициент заполнения 10%. Давайте сделаем вычисления для всех углов:

  • исходное положение ==> (0 градусов) длительность импульса 1мс ==> коэффициент заполнения = 1мс/20мс*100% = 5%
  • нейтральное положение ==> (90 градусов) длительность импульса 1,5мс ==> коэффициент заполнения = 1,5мс/20мс*100% = 7,5%
  • конечная позиция ==> (180 градусов) длительность импульса 2мс ==> коэффициент заполнения = 2мс/20мс*100% = 10%

Таким образом коэффициент заполнения варьируется от 5% до 10%.

Давайте откалибруем сервоприводы. Для этого откроем терминал на Raspberry и запустим редактор Python 3 с правами от суперпользователя (нужно для работы с GPIO):

sudo python3

Python Shell:

>>> 

Импортируем модуль RPI.GPIO и называем его GPIO:

import RPi.GPIO as GPIO

Определите, какие схемы нумерации выводов хотите использовать (BCM или BOARD). Я провел этот тест с BOARD, поэтому используемые контакты были физическими (GPIO 17 это контакт 11 и GPIO 27 это контакт 13). Мне было легко их идентифицировать и не ошибиться во время теста (в финальной программе я буду использовать BCM). Выбираем:

GPIO.setmode(GPIO.BOARD) 

Определяем вывод сервопривода, который будет использоваться:

tiltPin = 11

Если хотите использовать схему BCM, последние 2 команды должны быть заменены на:

GPIO.setmode(GPIO.BCM)
tiltPin = 17

Теперь указываем, что этот вывод будет работать как выход:

GPIO.setup(tiltPin, GPIO.OUT) 

Настраиваем частоту, для SG90 нужно 50 Гц:

tilt = GPIO.PWM(tiltPin, 50)

Включаем генерацию сигнала ШИМ на выводе и задаём начальный коэффициент заполнения равный нулю:

tilt = start(0)

Теперь мы можем устанавливать различные значения коэффициента заполнения и наблюдать за движением сервопривода. Давайте начнем с 5% и посмотрим, что происходит:

tilt.ChangeDutyCycle(5)

Сервопривод перешел в "нулевое положение". Сервопривод продолжал вращаться, при задании заполнения вплоть до 3%. При задании заполнения 2% сервопривод оставался в том же положении. После чего начав задавать значения больше 2%, движение сервопривода в моём случае начало происходить при установке коэффициента заполнения более 3%. Итак, 3% - это минимальное заполнение (позиция "0 градусов") для этого сервопривода.

То же самое произошло и с максимальным коэффициентом заполнения. Для начала установлено 10%:

tilt.ChangeDutyCycle(10)

Затем задавались большие значения, сервопривод продолжал проворачиваться при установке коэффициента заполнения вплоть до 13%. Таким образом максимальный коэффициент заполнения для данного сервопривода это 13%, угол, на который проворачивается вал сервопривода составил примерно 180 градусов (но это в данном случае, в зависимости от сервопривода физический угол может оказаться и больше и меньше). Итак, в результате калибровки получены следующие данные:

0 градусов ==> заполнение 3%
90 градусов ==> заполнение 8%
180 градусов ==> заполнение 13%

После окончания калибровки останавливаем ШИМ и очищаем GPIO:

tilt=stop()
GPIO.cleanup()

Для второго сервопривода процедура калибровки аналогична.

Шаг 5: создание скрипта Python

Для управления сервоприводами с использованием ШИМ, функции на Python нужно передавать значение коэффициента заполнения, указываемого в процентах. В данном случае удобней будет оперировать не коэффициентом заполнения, а градусами.

Сделать это очень просто. Мы знаем, что диапазон заполнения в пределах от 3% до 13% и что это эквивалентно диапазону углов от 0 до 180 градусов. Так же мы знаем, что зависимость линейная.



Позже в коде пересчёт заданного угла в коэффициент заполнения соответственно будет таким:

dutycycle = angle/18 + 3

Давайте создадим файл "angleServoCtrl.py" скрипта на Python для выполнения тестов. По сути, мы повторим то, что мы делали раньше в Python Shell:

from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
def setServoAngle(servo, angle):
	pwm = GPIO.PWM(servo, 50)
	pwm.start(8)
	dutyCycle = angle / 18. + 3.
	pwm.ChangeDutyCycle(dutyCycle)
	sleep(0.3)
	pwm.stop()
if __name__ == '__main__':
	import sys
	servo = int(sys.argv[1])
	GPIO.setup(servo, GPIO.OUT)
	setServoAngle(servo, int(sys.argv[2]))
	GPIO.cleanup()

Функция setServoAngle(servo, angle) получает в качестве аргументов номер вывода GPIO, к которому подключен сервопривод и значение угла, в который сервопривод должен провернуться.

В консоли этот скрипт запускается так:

sudo python3 angleServoCtrl.py 17 45 

Вышеприведенная команда установит сервопривод, подключенный к GPIO 17, под углом 45 градусов.

Файл "angleServoCtrl.py" можно скачать по ссылке.

Шаг 6: Механизм поворота и наклона

Сервопривод поворота ("Pan") будет вращать нашу камеру в горизонтальной плоскости, а сервопривод наклона ("Tilt") будет вращать её в вертикальной плоскости.

На следующем изображении показано, как работает механизм:



В этом проекте pan/tilt механизм будет вращать камеру только в диапазоне углов от 30 до 150 градусов.



Этого диапазона будет достаточно для камеры.

Шаг 7: самодельный механизм поворота и наклона

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

В этом проекте будет использован самодельный:



















Шаг 8: подключение электроники

После сборки механизма поворота/наклона, подключите сервоприводы по схеме из третьего шага. Последовательность подключения электроники:

  • отключить питание Raspberry Pi и сервоприводов
  • соберите всю схему
  • на всякий случай ещё раз всё перепроверьте
  • включите питание Raspberry Pi
  • если все в порядке, подключите питание сервоприводов

Подключать и настраивать камеру пока не будем, это будет рассмотрено в следующем обучающем проекте. 

Шаг 9: скрипт Python

Создадим скрипт "servoCtrl.py" для одновременного управления обоими сервоприводами:

from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
GPIO.setwarnings(False)
pan = 27
tilt = 17
GPIO.setup(tilt, GPIO.OUT) # white => TILT
GPIO.setup(pan, GPIO.OUT) # gray ==> PAN
def setServoAngle(servo, angle):
	assert angle >=30 and angle <= 150
	pwm = GPIO.PWM(servo, 50)
	pwm.start(8)
	dutyCycle = angle / 18. + 3.
	pwm.ChangeDutyCycle(dutyCycle)
	sleep(0.3)
	pwm.stop()
if __name__ == '__main__':
	import sys
	if len(sys.argv) == 1:
		setServoAngle(pan, 90)
		setServoAngle(tilt, 90)
	else:
		setServoAngle(pan, int(sys.argv[1])) # 30 ==> 90 (middle point) ==> 150
		setServoAngle(tilt, int(sys.argv[2])) # 30 ==> 90 (middle point) ==> 150
	GPIO.cleanup()

При запуске скрипта в качестве параметров нужно указать углы для обоих сервоприводов:

sudo python3 servoCtrl.py 45 120

Приведенная выше команда установит сервопривод поворота в позицию "45 градусов", сервопривод наклона в позицию "120 градусов". Если скрипту не будут переданы параметры, оба сервопривода провернуться в позицию "90 градусов".



Файл крипта "servoCtrl.py" можно скачать по ссылке.

Шаг 10: циклический тест для сервоприводов

Создадим скрипт " servoTest.py" для автоматического движения обоими сервоприводами в диапазоне углов от 30 до 150 градусов:



Осциллограф только для иллюстрации теории ШИМ, как объяснялось ранее.

Приведенный выше код скрипта "servoTest.py" можно скачать по ссылке.

Шаг 11: Заключение

Сделанное в этом обучающем проекте можно использовать для различных целей, некоторые примеры реализации будут рассмотрены в следующих обучающих проектах. К примеру управление и просмотр изображения с RPi-камеры через веб-страницу:



Или создание автоматического слежения за предметом:



Или слежения за лицом человека:



Автор: Marcelo Rovai
Перевод и адаптация: RobotoTehnika.ru