SBrick Remote Control

A fast incursion in Python and Tkinter (a very easy GUI library for those like me who abuse from Google-Copy-Paste) so I can play with SBrick from my Ubuntu laptop without the command line:

SBrick-RemoteControl

#!/usr/bin/env python 

from Tkinter import *
from time import sleep
from subprocess import call

def quit():
  global Window
  Window.destroy()

  return;

def STOP():

  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0002",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0003",shell=True)
  return

def NORTH():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010301FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010200FF",shell=True)
  sleep(time)
  STOP()
  return

def SOUTH():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010300FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010201FF",shell=True)
  print("Backward")
  sleep(time)
  STOP()
  return

def EAST():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010301FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010201FF",shell=True)
  print("RIGHT")
  sleep(time)
  STOP()
  return

def WEST():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010200FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010300FF",shell=True)
  sleep(time)
  STOP()
  return


Window = Tk()
Window.title("SBrick Remote Control v0.1")

B_North = Button(text = "N", command = NORTH)
B_North.grid(row=0, column=1)

B_West = Button(text = "W", command = WEST)
B_West.grid(row=1, column=0)

B_STOP = Button(text = "STOP", command = STOP)
B_STOP.grid(row=1, column=1)

B_East = Button(text = "E", command = EAST)
B_East.grid(row=1, column=2)

B_South = Button(text = "S", command = SOUTH)
B_South.grid(row=2, column=1)

scale = Scale(Window, from_=0.125, to=2.5, digits=3, resolution=0.125, orient=HORIZONTAL, length=250, label="Time")
scale.grid(row=3,column=0,columnspan=3)

B_QUIT = Button(text = "QUIT", command = quit)
B_QUIT.grid(row=4, column=1, )

mainloop()

 

SBrick – controlo remoto com um gamepad

Apresento o meu script em python para controlar o SBrick com um gamepad a partir do Linux. Recorro à biblioteca PyGame para ler o gamepad (assumindo que o gamepad é suportado nativamente pelo Linux, ver também o meu artigo sobre como utiizar um gamepad com ev3dev) e ao comando gatttool do BlueZ 5.0 para comunicar via Bluetooth BLE com o SBrick (assumindo também a presença de um dongle Bluetooth 4.0).

 

Este script funciona bem com Ubuntu mas deverá também funcionar em qualquer variante de Debian incluindo Raspbian (no Raspberry Pi) e ev3dev (no LEGO Mindstorms EV3, onde utilizei uma versão inicial deste script).

#!/usr/bin/env python

# sudo apt-get install python-pygame

import sys, traceback, os
os.environ['SDL_VIDEODRIVER'] = 'dummy'
from math import log10
from subprocess import call
from time import sleep
from pygame import joystick, event, display

### buttons ###
B_TRIANG = 0
B_CIRC = 1
B_CROSS = 2
B_SQUARE = 3
B_LTRIG2 = 4
B_RTRIG2 = 5
B_LTRIG = 6
B_RTRIG = 7
B_SELECT = 8
B_LJOY = 10
B_RJOY = 11
B_START = 9


def main():
  try:
    display.init();
    joystick.init();
    js=joystick.Joystick(0);
    js.init();

    DRIVE_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0102"
    DRIVE_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0103"
    COAST_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01020000"
    COAST_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01030000"
    BREAK_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0002"
    BREAK_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0003"

    ### starts in Joystick mode ###
    control_by_JOYSTICK=True;

    num_axes=js.get_numaxes();
    num_buttons=js.get_numbuttons();
    num_hats=js.get_numhats();

    ### assuming 4 axes, 13 buttons and 1 hat

    flag=False;

    while True:
      x=y=motor_r=motor_l=0.0;
      event.pump();

      button_mode=js.get_button(B_SELECT);
      button_shot=js.get_button(B_SQUARE);

      if button_mode ==1:

        if control_by_JOYSTICK==True:
          control_by_JOYSTICK=False;
          print 'Control Mode=HAT';
        else:
          control_by_JOYSTICK=True;
          print 'Control Mode=JOYSTICK';


      ### joysticks axis [-1, +1]
      ### x=axis2 , y=-axis3
      ### ignore less than 0.2 (dead zone)
      ### apply log10(100x) (to reforce lower values)
      ### result is less or equal than 2 = log10(100)

      if control_by_JOYSTICK==True:

            # Control by Right Joystick, Axis 2 e 3

            axis2=js.get_axis(2);
            axis3=js.get_axis(3);

        if axis2>0:
          if axis2<0.2:
            x=0;
          else:
            x=log10(axis2*100);
        elif axis2<0:
          if axis2>-0.2:
            x=0;
          else:
            x=-log10(-axis2*100);
            else:
              x=0;

        if axis3>0:
          if axis3<0.2:
            y=0;
          else:
            y=-log10(axis3*100);
        elif axis3<0:
          if axis3>-0.2:
            y=0;
          else:
            y=log10(-axis3*100);
        else:
          y=0;

        if y<>0:
          if x<0:
            motor_r=100*y;
            # turn left => slow motor_l
               motor_l=y*(100+25*x);
          else:
            motor_el=100*y;
            # turn right => slow motor_r
            motor_r=y*(100-25*x);
        elif x<>0:
           # y=0, just turn
           motor_l=100*x;
           motor_r=-motor_l;

      else:

         # Control by HAT keys

         hat=js.get_hat(0);

         if hat==(0,1):
#            print 'FRONT';
            motor_r=100;
            motor_l=100;
          elif hat==(1,0):
#            print 'RIGHT';
            motor_l=100;
            motor_r=-100;
         elif hat==(0,-1):
#            print 'BACK';
            motor_r=-100;
            motor_l=-100;
         elif hat==(-1,0):
#            print 'LEFT';
            motor_l=-100;
            motor_r=100;
         elif hat==(1,1):
#            print 'FRONT+RIGHT';
            motor_l=100;
            motor_r=50;
         elif hat==(-1,1):
#            print 'FRONT+LEFT';
            motor_l=50;
            motor_r=100;
         elif hat==(-1,-1):
#            print 'BACK+LEFT';
            motor_l=-100;
            motor_r=-50;
         elif hat==(1,-1):
#            print 'BACK+RIGHT';
            motor_l=-50;
            motor_r=-100;


       # get direction and duty cycle

      if (motor_l<0):
     dir_l="00"
     duty_l=str(hex(int(-motor_l)))
      else:
         dir_l="01"
         duty_l=str(hex(int(motor_l)))

      if (motor_r<0):
     dir_r="01"
     duty_r=str(hex(int(-motor_r)))
      else:
         dir_r="00"
         duty_r=str(hex(int(motor_r)))

      # command+direction+dutycyle

      command_A=DRIVE_A+dir_r+duty_r[2:]
      command_B=DRIVE_B+dir_l+duty_l[2:]
      call(command_A, shell=True);
      call(command_B, shell=True);
      sleep(0.1)
#      call(BREAK_A,shell=True);
#      call(BREAK_B,shell=True);
      call(COAST_A,shell=True);
      call(COAST_B,shell=True);

    # end while

  except (KeyboardInterrupt, SystemExit):
      print "Exiting...";
  except Exception:
      traceback.print_exc(file=sys.stdout);

  js.quit();
  joystick.quit();
  display.quit();
  sys.exit(0);

if __name__ == "__main__":
    main()

SBrick – remote control with a wireless gamepad

Here is my python script for controlling SBrick with a gamepad from Linux. It uses pygame for reading the gamepad (as long as it’s supported by the kernel, see also my post about using a gamepad with ev3dev) and gatttool from BlueZ 5.x to talk to the SBrick (you need a BT 4.0 USB dongle)

It should work in Ubuntu and other Debian variants including Raspbian (Raspberry Pi) or ev3dev (LEGO Mindstorms EV3)

#!/usr/bin/env python

# sudo apt-get install python-pygame

import sys, traceback, os
os.environ['SDL_VIDEODRIVER'] = 'dummy'
from math import log10
from subprocess import call
from time import sleep
from pygame import joystick, event, display

### buttons ###
B_TRIANG = 0
B_CIRC = 1
B_CROSS = 2
B_SQUARE = 3
B_LTRIG2 = 4
B_RTRIG2 = 5
B_LTRIG = 6
B_RTRIG = 7
B_SELECT = 8
B_LJOY = 10
B_RJOY = 11
B_START = 9


def main():
  try:
    display.init();
    joystick.init();
    js=joystick.Joystick(0);
    js.init();

    DRIVE_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0102"
    DRIVE_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0103"
    COAST_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01020000"
    COAST_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=01030000"
    BREAK_A="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0002"
    BREAK_B="gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0003"

    ### starts in Joystick mode ###
    control_by_JOYSTICK=True;

    num_axes=js.get_numaxes();
    num_buttons=js.get_numbuttons();
    num_hats=js.get_numhats();

    ### assuming 4 axes, 13 buttons and 1 hat

    flag=False;

    while True:
      x=y=motor_r=motor_l=0.0;
      event.pump();

      button_mode=js.get_button(B_SELECT);
      button_shot=js.get_button(B_SQUARE);

      if button_mode ==1:

        if control_by_JOYSTICK==True:
          control_by_JOYSTICK=False;
          print 'Control Mode=HAT';
        else:
          control_by_JOYSTICK=True;
          print 'Control Mode=JOYSTICK';


      ### joysticks axis [-1, +1]
      ### x=axis2 , y=-axis3
      ### ignore less than 0.2 (dead zone)
      ### apply log10(100x) (to reforce lower values)
      ### result is less or equal than 2 = log10(100)

      if control_by_JOYSTICK==True:

            # Control by Right Joystick, Axis 2 e 3

            axis2=js.get_axis(2);
            axis3=js.get_axis(3);

        if axis2>0:
          if axis2<0.2:
            x=0;
          else:
            x=log10(axis2*100);
        elif axis2<0:
          if axis2>-0.2:
            x=0;
          else:
            x=-log10(-axis2*100);
            else:
              x=0;

        if axis3>0:
          if axis3<0.2:
            y=0;
          else:
            y=-log10(axis3*100);
        elif axis3<0:
          if axis3>-0.2:
            y=0;
          else:
            y=log10(-axis3*100);
        else:
          y=0;

        if y<>0:
          if x<0:
            motor_r=100*y;
            # turn left => slow motor_l
               motor_l=y*(100+25*x);
          else:
            motor_el=100*y;
            # turn right => slow motor_r
            motor_r=y*(100-25*x);
        elif x<>0:
           # y=0, just turn
           motor_l=100*x;
           motor_r=-motor_l;

      else:

         # Control by HAT keys

         hat=js.get_hat(0);

         if hat==(0,1):
#            print 'FRONT';
            motor_r=100;
            motor_l=100;
          elif hat==(1,0):
#            print 'RIGHT';
            motor_l=100;
            motor_r=-100;
         elif hat==(0,-1):
#            print 'BACK';
            motor_r=-100;
            motor_l=-100;
         elif hat==(-1,0):
#            print 'LEFT';
            motor_l=-100;
            motor_r=100;
         elif hat==(1,1):
#            print 'FRONT+RIGHT';
            motor_l=100;
            motor_r=50;
         elif hat==(-1,1):
#            print 'FRONT+LEFT';
            motor_l=50;
            motor_r=100;
         elif hat==(-1,-1):
#            print 'BACK+LEFT';
            motor_l=-100;
            motor_r=-50;
         elif hat==(1,-1):
#            print 'BACK+RIGHT';
            motor_l=-50;
            motor_r=-100;


       # get direction and duty cycle

      if (motor_l<0):
     dir_l="00"
     duty_l=str(hex(int(-motor_l)))
      else:
         dir_l="01"
         duty_l=str(hex(int(motor_l)))

      if (motor_r<0):
     dir_r="01"
     duty_r=str(hex(int(-motor_r)))
      else:
         dir_r="00"
         duty_r=str(hex(int(motor_r)))

      # command+direction+dutycyle

      command_A=DRIVE_A+dir_r+duty_r[2:]
      command_B=DRIVE_B+dir_l+duty_l[2:]
      call(command_A, shell=True);
      call(command_B, shell=True);
      sleep(0.1)
#      call(BREAK_A,shell=True);
#      call(BREAK_B,shell=True);
      call(COAST_A,shell=True);
      call(COAST_B,shell=True);

    # end while

  except (KeyboardInterrupt, SystemExit):
      print "Exiting...";
  except Exception:
      traceback.print_exc(file=sys.stdout);

  js.quit();
  joystick.quit();
  display.quit();
  sys.exit(0);

if __name__ == "__main__":
    main()

 

 

SBrick remote control com Snap!

Um controlo remoto simples em Snap! usando as 4 teclas cursoras:

snap-SBrick2A device extension que criei implementa 3 motores: A (canal #1), B (canal #2) e um pseudo-motor P (ambos os canais). Para movimentar o rover para trás e para a frente é usado o motor P, para rodá-lo para a esquerda ou para a direita são usados os motores A e B com direcções opostas.

Depois de uma décima de segunda de rotação dos motores é dado um comando de rotação aos motores com duty cycle de zero (COAST) mas também podia ser usado o comando stop (BREAK).

SBrick + Snap!

A linguagem Snap! (antes designada BYOB) é uma linguagem de programação visual baseada na experiência “drag-and-drop”, uma reimplementação extendida da linguagem Scratch que tem ganho alguma notoriedade por ter sido incluída no ambiente gráfico dos Raspberry Pi.

Eis um exemplo de um programa muito simples, que faz um rover andar às voltas:

snap-SBrick1De há um par de anos para cá que alimento a ideia de utilizar Snap! para ensinar à miudagem [e não só] conceitos básicos de robótica. A forma como o Snap! está a ser desenvolvido permite criar «device extensions» para interagir com dispositivos físicos (descobri o Snap! justamente por ter uma extensão para Mindstorms NXT, a Snap-NXT by Technoboy10) e hoje criei a minha primeira extensão, para o Sbrick.

Basicamente editei a extensão para Mindstorms NXT, deitei fora a parte específica do NXT e acrescentei os meus comandos que invocam o comando gatttool do BlueZ (do que resulta a minha extensão apenas funcionar em Linux, lamento).

A device extension consiste em dois ficheiros:

O primeiro é um programa em Python que corre um servidor http muito básico que aceita comandos http. O segundo é uma definição XML das funcionalidades implementadas (dois comandos apenas: ‘move motor’ e ‘stop motor’, sendo possível controlar 3 «motores»: A = channel#1, B=channel#2 e P = channel#1+channel#2). Estando o programa ‘snap-sbrick.py’ a correr, lançamos o Snap! com a device extension quando acedemos por browser ao endereço:

http://snap.berkeley.edu/snapsource/snap.html#open:http://localhost:1330/snap-sbrick

Ou seja o Snap! em si é carregado da Universidade de Berkeley e apontado para o nosso PC de onde carrega as definições das funcionalidades adicionais. É possível carregar o Snap! a partir do nosso próprio PC para trabalhar em modo offline mas isso já é outra história.

A definição dos comandos pode também ser feita graficamente, sendo depois gerado um ficheiro XML semelhante ao acima referido:

  • comando ‘move motor’

snap-movemotor-def

  • comando ‘stop motor’

snap-stopmotor-defPodemos ver que a definição de ‘move motor’ está bem melhor que a de ‘stop motor’ – é feita uma validação dos parâmetros, se speed não pertencer ao intervalo [-100,100] ou se motor não for A/B/P é gerada uma excepção.

SBrick Remote Control

Uma incursão rápida em Python e Tkinter (uma library para aplicações GUI muito fácil de usar no modo Google-Copy-Paste) para poder comunicar com o SBrick a partir do meu laptop Ubuntu sem usar a linha de comando:

SBrick-RemoteControl

#!/usr/bin/env python 

from Tkinter import *
from time import sleep
from subprocess import call

def quit():
  global Window
  Window.destroy()

  return;

def STOP():

  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0002",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=0003",shell=True)
  return

def NORTH():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010301FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010200FF",shell=True)
  sleep(time)
  STOP()
  return

def SOUTH():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010300FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010201FF",shell=True)
  print("Backward")
  sleep(time)
  STOP()
  return

def EAST():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010301FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010201FF",shell=True)
  print("RIGHT")
  sleep(time)
  STOP()
  return

def WEST():

  time=scale.get()
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010200FF",shell=True)
  call("gatttool -b 00:07:80:7F:28:E1 -i hci0 --char-write --handle=0x0025 --value=010300FF",shell=True)
  sleep(time)
  STOP()
  return


Window = Tk()
Window.title("SBrick Remote Control v0.1")

B_North = Button(text = "N", command = NORTH)
B_North.grid(row=0, column=1)

B_West = Button(text = "W", command = WEST)
B_West.grid(row=1, column=0)

B_STOP = Button(text = "STOP", command = STOP)
B_STOP.grid(row=1, column=1)

B_East = Button(text = "E", command = EAST)
B_East.grid(row=1, column=2)

B_South = Button(text = "S", command = SOUTH)
B_South.grid(row=2, column=1)

scale = Scale(Window, from_=0.125, to=2.5, digits=3, resolution=0.125, orient=HORIZONTAL, length=250, label="Time")
scale.grid(row=3,column=0,columnspan=3)

B_QUIT = Button(text = "QUIT", command = quit)
B_QUIT.grid(row=4, column=1, )

mainloop()

 

 

LEGO MOC: Xutos & Pontapés ao vivo no Braga BRInCKa 2014

Longe de estar terminado mas já suficientemente funcional para supreender alguns visitantes:

[actualização] com mais algumas minifigs e um backstage a disfarçar a electrónica [ideia da mulher, claro 😉 ]

Relés USB

Adquiri um módulo USB-RLY16 que permite comandar 8 relés através de uma porta USB. A ideia original é controlar as minifiguras LEGO em palco pelo que com 8 relés poderei controlar 4 micromotores LEGO de forma independente e em ambos os sentidos (os Xutos&Pontapés são 5 pelo que 2 deles terão de partilhar o mesmo motor ou terei de arranjar outra forma para controlar um quinto motor).

O módulo é baseado num circuito FT232RL que emula uma porta série através da ligação USB. Em Linux o suporte a este tipo de devices já vem incluído no kernel sendo associado um device do tipo ‘/dev/ttyUSBn’. No meu PC com Ubuntu 14.04 funcionou à primeira, tal como no EV3 com ev3dev e estou 100% convencido que com Raspberry Pi e Raspbian acontecerá o mesmo.

São necessárias duas alimentações: uma para o accionamento dos relés e outra (ou outras) para os circuitos controlados pelos relés. Teoricamente podem ser as mesmas mas optei por separá-las:

  • uma pilha PP3 com ficha de 2.1mm para o accionamento dos relés
  • uma pilha PP3 em caixa LEGO para os motores

Nota: a pseudo-documentação afirma serem necessários pelo menos 12V/500 mA para o accionamento dos relés mas dei-me bem com os 9V de uma pilha alcalina PP3.

Ligando ao EV3:

$ dmesg
(...)
usb 1-1.4: new full-speed USB device number 6 using ohci
usbcore: registered new interface driver usbserial
usbcore: registered new interface driver ftdi_sio
usbserial: USB Serial support registered for FTDI USB Serial Device
ftdi_sio 1-1.4:1.0: FTDI USB Serial Device converter detected
usb 1-1.4: Detected FT232RL
usb 1-1.4: Number of endpoints 2
usb 1-1.4: Endpoint 1 MaxPacketSize 64
usb 1-1.4: Endpoint 2 MaxPacketSize 64
usb 1-1.4: Setting MaxPacketSize 64
usb 1-1.4: FTDI USB Serial Device converter now attached to ttyUSB0

Para comunicar com a placa é necessário configurar a porta série virtual (/dev/ttyUSB0) para comunicar a 19200 baud, 8 databits, 2 stop bits, sem paridade (19200 8N2) e sem hardware nem software handshaking. No Ubuntu usei o ‘puTTy’ mas como requer ambiente gráfico no ev3dev optei pelo ‘minicom’:

$ apt-get install minicom

O minicom tem um modo de setup:

$ minicom -s

depois de configurado (19200 8N2, no flow control) se carregarmos na tecla ‘d’ accionamos todos os relés e na tecla ‘n’ desactivamos todos (confirmem numa tabela ASCII que correspondem aos códigos decimais 100 e 110). Confirmado o funcionamento podemos sair (‘Control+A’ seguido de ‘Q’), a porta virtual permanece configurada até ao próximo reboot.

Podemos agora enviar comandos directamente da shell:

$ echo d > /dev/ttyUSB0
$ echo n > /dev/ttyUSB0

Em python podemos comunicar directamente com a porta virtual através da biblioteca pyserial (http://pyserial.sourceforge.net/):

$ apt-get install python-serial
import serial
from time import sleep

port = serial.Serial("/dev/ttyUSB0", baudrate=19200, bytesize=8, parity='N', stopbits=2, timeout=None, xonxoff=0, rtscts=0)
port.write("d");
sleep(1);
port.write("n");
sleep(1);
port.close()

O video acima corresponde ao script python abaixo:

import serial
from time import sleep


# da esquerda para a direita:
# motores A, B, C e D
#
# motor A e/f o/p
# motor B g/h q/r
# motor C i/j s/t
# motor D k/l u/v
#

def relays_all_off():
  port.write("n");

def relays_all_on():
  port.write("d");

### Motor A ###
def motor_A_Right():
  port.write("ep");

def motor_A_Left():
  port.write("of");

def motor_A_OFF():
  port.write("op");

### Motor B ###
def motor_B_Right():
  port.write("gr");

def motor_B_Left():
  port.write("qh");

def motor_B_OFF():
  port.write("qr");

### Motor C ###
def motor_C_Right():
  port.write("it");

def motor_C_Left():
  port.write("sj");

def motor_C_OFF():
  port.write("st");

### Motor D ###
def motor_D_Right():
  port.write("kv");

def motor_D_Left():
  port.write("ul");

def motor_D_OFF():
  port.write("uv");


port = serial.Serial("/dev/ttyUSB0", baudrate=19200, bytesize=8, parity='N', stopbits=2, timeout=None, xonxoff=0, rtscts=0)

motor_A_Left();
motor_B_Left();
motor_C_Left();
motor_D_Left();
sleep(1);
motor_A_OFF();
motor_B_OFF();
motor_C_OFF();
motor_D_OFF();
sleep(1);
motor_A_Right();
motor_B_Right();
motor_C_Right();
motor_D_Right();
sleep(1);
motor_A_OFF();
motor_B_OFF();
motor_C_OFF();
motor_D_OFF();
sleep(2);

motor_A_Left();
sleep(1);
motor_A_OFF();
sleep(1);
motor_B_Left();
sleep(1);
motor_B_OFF();
sleep(1);
motor_C_Left();
sleep(1);
motor_C_OFF();
sleep(1);
motor_D_Left();
sleep(1);
motor_D_OFF();
sleep(1);

port.close();