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