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();