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