[Практика 8] Удаленное управление
Фев 25, 2020 в 07:50  •  9 мин  •  читали 521 раз

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



Если Вы следите за трелло, то знаете, что в планах было реализовать управление роботом по сокетам и с помощью REST API, но от последнего я отказался.


Собственно, начнем.


Стек технологий на самом деле легко предсказать: нам нужно принимать команды и применять их каким-то образом. Вспоминаем, что мы собираем робота на RPi, значит нам пригодится RPi.GPIO, ну а принимать команды мы будем с помощью python-socketio:


%lang(python)%
import eventlet
import socketio
import mech


mech это самописный модуль, его импорты таковы:

%lang(python)%
import RPi.GPIO as GPIO


Сначала нужно проинициализировать сокет сервер:

%lang(python)%
sio = socketio.Server(cors_allowed_origins='*')
app = socketio.WSGIApp(sio, static_files={
    '/': {'content_type': 'text/html', 'filename': 'index.html'}
})


Мы инициализируем его как WSGI приложение, однако пользоваться этим мы не будем)))

Не будем ставить на малину веб сервер, будем просто кидать запросы на ip:port.


Обращаю внимание, что мы разрешаем делать запросы откуда угодно. Это нужно потому что запрос с ПК оператора робота на малину считается cross-origin (что логично), и без такой настройки он просто не пройдет.


Далее инициализируем наш mech модуль:

%lang(python)%
mech.init()


Вот код иницализации:

%lang(python)%
GPIO.setmode(GPIO.BCM) # настраиваем логический маппинг пинов (их 2)
GPIO.setwarnings(False) # говорим, что нам неинтересно знать, что там уже используется
  for pin in pins_on:
    GPIO.setup(pin, GPIO.OUT) # настраиваем все пины на выход
  left_right_motors_off() # на всякий случай ставим их в логический 0


pins_on это массив GPIO, которые мы используем.


Рассмотрим низкоуровневые функции работы с GPIO:

%lang(python)%
def left_right_motors_off():
  for pin in pins_on:
    GPIO.output(pin, False)
  	
def left_motor_on(ward):
  level = True if ward == 'forward' else False
  GPIO.output(21, level)
  GPIO.output(22, not level)
  	
def right_motor_on(ward):
  level = True if ward == 'forward' else False
  GPIO.output(23, level)
  GPIO.output(24, not level)


Мы просто в зависимости от переданного аргумента (forward/backward) устанавливаем пины в нужные логические уровни. Моторы подключены через драйвер TB6612FNG:

Таким образом, мы можем менять направление вращения ротора моторов.

Условно есть 2 пина A и B. Если A = 1, B = 0, то вращение, например, по часовой стрелке, иначе - против.


Пины PWM этого драйвера мы не используем, поэтому просто подадим на них лог. 1.

На пин STBY подаем лог. 1 (Это пин включения драйвера, пускай всегда будет включен)

Остались пины питания и входы-выходы драйверы, но тут все вроде бы логично.


Теперь посмотрим чуть выше:

%lang(python)%
def go(direction):
  print('go', direction)
  right_motor_on(direction)
  left_motor_on(direction)
	
def stop():
  print('stop')
  left_right_motors_off()
	
def turn(direction):
  print('turn', direction)
  if direction == 'left':
    left_motor_on('forward')
    right_motor_on('backward')
  else:
    left_motor_on('backward')
    right_motor_on('forward')

В зависимости от направления включаем моторы в нужном порядке в нужные стороны вращения.


Все довольно просто.


Но как же все это работает в совокупности?

А вот как:

%lang(python)%
@sio.event
def connect(sid, environ):
  print('connect ', sid)
	
@sio.event
def disconnect(sid):
  print('disconnect ', sid)
	
@sio.on('go')
def go(sid, data):
  mech.go(data)
	
@sio.on('turn')
def turn(sid, data):
  mech.turn(data)
	
@sio.on('stop')
def stop(sid, data):
  mech.stop()

Мы регистрируем слушателей событий. И в момент, когда эти события приходят с веб-интерфейса, вызываем нужные функции. Все!


Остается разве что запустить сервер:

%lang(python)%
if __name__ == '__main__':
  eventlet.wsgi.server(eventlet.listen(('', 8765)), app)


Практика подходит к концу. Остается немного времени. На днях я соберу весь материал в кучу и мы посмотрим, что нам удалось собрать. Следите за обновлениями!


Спасибо за внимание.

Копирование материалов допускается только с разрешения автора (vladivanov.dev@gmail.com) в письменной форме.
(Copying of materials is allowed only with the written permission of the author)
Похожие статьи