Ter o LEGO Mindstorms EV3 a correr uma versão quase standard de Debian Linux começa agora a revelar as suas vantagens: podemos atirar-lhe com quase tudo o que tivermos na nossa gaveta de sucata… como por exemplo um teclado numérico USB:
O sistema operativo reconhece-o como um teclado convencional:
root@ev3dev:~# dmesg usb 1-1.4.1: new low-speed USB device number 7 using ohci input: USB-compliant keyboard as /devices/platform/ohci.0/usb1/1-1/1-1.4/1-1.4.1/1-1.4.1:1.0/0003:0B38:0003.0001/input/input2 hid-generic 0003:0B38:0003.0001: input: USB HID v1.10 Keyboard [USB-compliant keyboard] on usb-ohci.0-1.4.1/input0 input: USB-compliant keyboard as /devices/platform/ohci.0/usb1/1-1/1-1.4/1-1.4.1/1-1.4.1:1.1/0003:0B38:0003.0002/input/input3 hid-generic 0003:0B38:0003.0002: input: USB HID v1.10 Mouse [USB-compliant keyboard] on usb-ohci.0-1.4.1/input1
root@ev3dev:~# lsusb Bus 001 Device 007: ID 0b38:0003 Gear Head Keyboard Bus 001 Device 006: ID 058f:9254 Alcor Micro Corp. Hub
(o teclado tem embutido um hub USB de 2 portas daí o segundo device USB reportado)
O sistema operativo cria entradas do tipo ‘event#’ em ‘/dev/input’ assim como apontadores com descritivos mais legíveis:
ls /dev/input/by-id/ -la lrwxrwxrwx 1 root root 10 Aug 13 23:38 usb-0b38_USB-compliant_keyboard-event-if01 -> ../event2 lrwxrwxrwx 1 root root 10 Aug 13 23:38 usb-0b38_USB-compliant_keyboard-event-kbd -> ../event1
De modo que o teclado pode ser referido por um destes dois ficheiros:
- /dev/input/event1
- /dev/input/usb-0b38_USB-compliant_keyboard-event-kbd
Enquanto que o sufixo “event1” é variável, o descritivo “by-id” não é – no meu laptop Ubuntu o mesmo comando retorna:
~$ ls /dev/input/by-id/ -la lrwxrwxrwx 1 root root 10 Aug 13 23:38 usb-0b38_USB-compliant_keyboard-event-if01 -> ../event19 lrwxrwxrwx 1 root root 10 Aug 13 23:38 usb-0b38_USB-compliant_keyboard-event-kbd -> ../event18
por isso é preferível utilizar o descritivo “by-id”.
Não é suficiente ler os valores deste ficheiro – o primir de uma tecla gera gera um código de vários caracteres aparentemente ininteligiveis:
~$ cat /dev/input/event1 w��S�VSw��S�VEw��S�Vw��S�Ww��S�Ww��S��Sw��S��Ew��S��^C
A solução é usar o comando ‘showkey -s’ para descodificar. Por exemplo premindo a tecla ‘4’ com e sem ‘NumLock’ activo resulta:
cat /dev/input/by-id/usb-0b38_USB-compliant_keyboard-event-kbd > showkey -s
- Sem Numlock: “^[[D”
- Com NumLock: “4”
Felizmente isto só é necessário se quisermos ler directamente o teclado. Em situações normais, quando os nossos programas estão a correr, o próprio sistema operativo pode fazer esse trabalho por nós. No caso do ev3dev podemos ler uma única tecla a partir da consola com o seguinte comando bash:
read -s -n 1 Tecla < /dev/tty1
O parâmetro ‘-s’ serve para correr em modo silencioso (i.e. a tecla não é simultâneamente escrita na consola) e o parâmetro ‘-n 1’ força a leitura de um único caracter (quanto ao pipe ‘< /dev/tty1’ descobri entretanto que tanto faz referir /dev/tty0 como /dev/tty1 portanto a partir daqui refiro a consola do ev3dev como /dev/tty1… porque sim)
O script abaixo junta esta informação com a obtida anterior a respeito dos motores e permite controlar a rotação do motor com as teclas ‘4’ (LEFT) e ‘6’ (RIGHT), terminado com a tecla ‘ENTER’.
#!/bin/bash #chmod +x controlkey.sh tput clear > /dev/tty1 setfont /usr/share/consolefonts/Lat15-TerminusBold32x16.psf.gz echo -n "Prima tecla" > /dev/tty1 while true; do read -s -n 1 char < /dev/tty1 if [[ "$char" = "" ]]; then break fi case "$char" in 4) echo "LEFT" > /dev/tty1 echo 0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp echo 1 > /sys/class/tacho-motor/tacho-motor0/run echo 50 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp sleep 1s echo 0 > /sys/class/tacho-motor/tacho-motor0/run echo 0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp ;; 6) echo "RIGHT" > /dev/tty1 echo 0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp echo 1 > /sys/class/tacho-motor/tacho-motor0/run echo -50 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp sleep 1s echo 0 > /sys/class/tacho-motor/tacho-motor0/run echo 0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp ;; esac done echo "Bye!" > /dev/tty1