ev3dev – webcam

This post is part 2 of 9 of  AD4M4ST0R - um rover LEGO

A webcam USB utilizada no AD4M4ST0R é uma Logitech C170.

Depois de ligada são reconhecidos dois devices: uma webcam propriamente dita do tipo UVC (USB Video Class) gerida pelo v4l2 e um microfone gerido como uma placa de som pelo ALSA:

root@ev3dev:~# dmesg
(...)
usb 1-1.3: new full-speed USB device number 5 using ohci
Linux video capture interface: v2.00
uvcvideo: Found UVC 1.00 device Webcam C170 (046d:082b)
input: Webcam C170 as /devices/platform/ohci.0/usb1/1-1/1-1.3/1-1.3:1.0/input/input3
usbcore: registered new interface driver uvcvideo
USB Video Class driver (1.1.1)
usbcore: registered new interface driver snd-usb-audio

O microfone não aparece como dispositivo USB, apenas a webcam:

root@ev3dev:~# lsusb
Bus 001 Device 005: ID 046d:082b Logitech, Inc.
(...)

mas se formos ver ao alsamixer  temos lá uma nova placa de som: “Webcam C170”.

A parte mais crítica, a criação de um dispositivo video, também funcionou:

root@ev3dev:~# ls /dev

mostra entre outros “video0”.

Como a webcam foi também reconhecida como um dispositivo OHCI temos ainda:

root@ev3dev:~# ls /dev/input/by-id/ -la
(...)
lrwxrwxrwx 1 root root   9 Aug 18 12:13 usb-_Webcam_C170-event-if00 -> ../event3
(...)

 

Para capturar imagens da webcam optei pelo fswebcam

apt-get install fswebcam

Como já o tinha experimentado com esta mesma webcam no meu Ubuntu, avanço para um comando que sei que funciona:

fswebcam -d /dev/video0 -p YUYV -r 640x480 teste.jpg

E efectivamente funciona só que quando fui ver a imagem esta tinha apenas 176×144 e não 640×480 (e o próprio comando devolve isso: “Adjusting resolution from 640×480 to 176×144”). Mas que raio…?

Perdi algum tempo nisto por isso vou alongar-me um pouco mais para que outros que passem pelo mesmo possam beneficiar também.

Descobri que a câmara permite despejar video em dois formatos diferentes: YUYV e MJPG:

root@ev3dev:~# v4l2-ctl --list-formats
ioctl: VIDIOC_ENUM_FMT
    Index       : 0
    Type        : Video Capture
    Pixel Format: 'YUYV'
    Name        : YUV 4:2:2 (YUYV)

    Index       : 1
    Type        : Video Capture
    Pixel Format: 'MJPG' (compressed)
    Name        : MJPEG

MJPG (Motion JPEG) é um formato com compressão (e alguma perda também) e por isso consome menos largura de banda que o YUYV. A minha teoria é de que sendo o bus USB do EV3 apenas 1.1 (11 Mbps) em vez de USB 2.0 (480 Mbps) como no meu Ubuntu a webcam de algum modo se autoconfigura para a largura de banda disponível. Por isso no Ubuntu ao pedir com o fswebcam uma foto 640×480 extraída de video gerado em formato YUV ele consiga mas no EV3 seja obrigado a reduzir para 176×144.

A solução foi indicar ao fswebcam para lidar com MJPG:

fswebcam -d /dev/video0 -p MJPEG -r 640x480 teste.jpg

Agora já funciona, excepto que nalgumas situações ocorre um erro semelhante a este (os dois números hexadecimais do final variam):

GD Error: gd-jpeg: JPEG library reports unrecoverable error: Not a JPEG file: starts with 0x92 0x7

Aparentemente algumas webcams (e pelos vistos a maioria são da Logitech?) demora a estabilizar a captura e por isso produz lixo nas primeiras frames. As soluções passam invariavelmente por descartar umas quantas frames inicais… só ainda não encontrem o número mágico:

fswebcam -d /dev/video0 -p MJPEG -r 640x480 -S 20 teste.jpg

Descartar 20 frames funciona sempre mas parece-me um exagero. Além disso descobri que à medida que se vai utilizando podemos baixar o número, até mesmo deixar de descartar qualquer frame… Parece que a câmara “aquece” ou se vai auto-ajustando, será?

Para facilitar a utilização a partir de outros programas criei um script ‘saycheese.sh’ que ao ser invocado tira uma fotografia e guarda-a com um nome correspondendo à data:

#!/bin/sh
 filename=$(date +"%d-%m-%y_%Hh%Mm%Ss")
 fswebcam -d /dev/video0 -p MJPEG -r 640x480 -q -D 1 -S 10 -s brightness=8 -s contrast=10  $filename.jpg

Utilizo alguns outros parâmetros:

  • “-D 1” força um atraso de 1 segundo entre a activação da câmara e o íncio da captura
  • -s brightness=8 aumenta ligeiramente o brilho
  • -s contrast=10 diminui ligeiramente o contraste

Os valores de brightness e contrast, bem como outros aceites pela webcam, podem ser questionados à própria câmara:

root@ev3dev:~# v4l2-ctl --all
Driver Info (not using libv4l2):
    Driver name   : uvcvideo
    Card type     : Webcam C170
    Bus info      : usb-ohci.0-1.3
    Driver version: 3.14.7
    Capabilities  : 0x84000001
        Video Capture
        Streaming
        Device Capabilities
    Device Caps   : 0x04000001
        Video Capture
        Streaming
Priority: 2
Video input : 0 (Camera 1: ok)
Format Video Capture:
    Width/Height  : 640/480
    Pixel Format  : 'MJPG'
    Field         : None
    Bytes per Line: 0
    Size Image    : 921600
    Colorspace    : SRGB
Crop Capability Video Capture:
    Bounds      : Left 0, Top 0, Width 640, Height 480
    Default     : Left 0, Top 0, Width 640, Height 480
    Pixel Aspect: 1/1
Streaming Parameters Video Capture:
    Capabilities     : timeperframe
    Frames per second: 30.000 (30/1)
    Read buffers     : 0
                     brightness (int)    : min=-64 max=64 step=1 default=0 value=0
                       contrast (int)    : min=0 max=30 step=1 default=13 value=13
                     saturation (int)    : min=0 max=127 step=1 default=38 value=38
                            hue (int)    : min=-16000 max=16000 step=1 default=0 value=0
 white_balance_temperature_auto (bool)   : default=1 value=1
                          gamma (int)    : min=20 max=250 step=1 default=100 value=100
           power_line_frequency (menu)   : min=0 max=2 default=1 value=1
      white_balance_temperature (int)    : min=2800 max=6500 step=1 default=5000 value=5000 flags=inactive
                      sharpness (int)    : min=0 max=100 step=1 default=35 value=35
         backlight_compensation (int)    : min=0 max=1 step=1 default=0 value=0
                  exposure_auto (menu)   : min=0 max=3 default=3 value=3
              exposure_absolute (int)    : min=2 max=5000 step=1 default=312 value=10000 flags=inactive
         exposure_auto_priority (bool)   : default=0 value=1
                   pan_absolute (int)    : min=-72000 max=72000 step=3600 default=0 value=0
                  tilt_absolute (int)    : min=-54000 max=54000 step=3600 default=0 value=0
                  zoom_absolute (int)    : min=1 max=2 step=1 default=1 value=1

(embora nem todos os comandos aceites pela câmara sejam perceptíveis, só experimentando vários valores para ver a diferença)

AD4M4ST0R – um rover LEGO

This post is part 1 of 9 of  AD4M4ST0R - um rover LEGO

Na continuação das experiências com o ev3dev, dois dispositivos USB um pouco mais complicados:

  • wireless gamepad
  • webcam

Desta vez mostro primeiro o resultado e preocupo-me depois com as explicações 🙂

ad4m4st0r-01

O gamepad é um gamepad genérico para Sony Playstation 3 e PC, penso que a maioria dos gamepads USB serão igualmente reconhecidos. Já com as webcams não será bem assim, será necessário compatibilidade com v4l2 (webcams) ou gPhoto2 (máquinas fotográficas). Neste exemplo estou a usar uma webcam Logitech C170 que funciona com o v4l2 através do uvcvideo. Também utilizei com sucesso uma Canon Digital IXUS 500 com o gPhoto2. E também tentei com 3 webcams antigas sem sucesso (apesar de 2 delas funcionarem no meu Ubuntu… pelos vistos funcionam em modo de compatibilidade v4l1 que não parece existir no ev3dev).

A foto abaixo (não tocada) foi tirada pelo AD4M4ST0R durante o decorrer do video anterior:19-08-14_09h53m54s

[Actualizado a 20 de Agosto]

Para quem estiver interessado, publiquei em artigos distintos os detalhes quanto:

ev3dev – automatic login

Depois do ev3dev terminar a sequência de boot, a consola do EV3 saúda-nos com uma janela de login. Quando queremos utilizar em pleno a consola é necessário “desbloqueá-la” e para isso tive de descobrir como implementar autologin.

Encontrei várias referências a usar o ‘/etc/inittab’ mas não consegui resultados práticos. Encontrei contudo outra abordagem que resultou:

mkdir /etc/systemd/system/getty@tty1.service.d/
nano /etc/systemd/system/getty@tty1.service.d/autologin.conf

No ficheiro autologin.conf bastou colocar estas 3 linhas:

[Service]
ExecStart=
ExecStart=-/usr/bin/agetty --autologin root --noclear %I 38400 linux

Após reboot o ev3dev fez o login automático com o user root, como pretendido.

ev3dev – backup e boot time

Nesta primeira semana de experiências com o ev3dev utilizei sempre o mesmo cartão microSD (um Kingston microSD 2GB penso que classe 4). Os tempos de arranque (desde o carregar no botão de power até ao primeiro ‘ping’) foram sempre de 60 segundos, não é muito mau comparado com o tempo de arranque do EV3 com o firmware LEGO por isso não me preocupei em experimentar outros cartões.

Mas hoje lembrei-me de ter visto alguma utilização de swap e já que as operações de update são longas (mais de 10 minutos só para actualizar o catálogo com ‘apt-get update’) podia ser que a coisa melhorasse com um cartão mais rápido.

Trocar de cartão é simples e faz-se em 5 minutos:

  1. colocar o cartão no meu portátil Ubuntu
  2. criar uma imagem do cartão e guardar como backup
  3. tirar o cartão e colocar outro qualquer
  4. repor a imagem anterior neste novo cartão

Como novo cartão utilizei um SanDisk Ultra de 4 GB (microSDHC classe UHS-I).

Os tempos de arranque desceram de 60 segundos para 50 segundos, nada mau. E a actualização do catálogo (‘apt-get update’) passou para ligeiramente menos de 8 minutos. Não é um ganho espantoso mas se estiver a trabalhar com pilhas ou baterias em vez de regulador DC já é qualquer coisa.

Como o novo cartão é de 4 GB em vez de 2 GB posso aproveitar o novo espaço extendendo o file system. Podia tê-lo feito de dentro do próprio ev3dev mas ainda não domino muito a linha de comando por isso fi-lo em 3 fases:

  1. Colocando o cartão no meu Ubuntu e utilizando o Gparted para criar uma nova partição do tipo ‘lvm2 pv’ com os 1906 MB livres no cartão
  2. Ainda no Ubuntu usando o system-config-lvm para adicionar a nova partição ao Volume Group já existente
  3. Voltando ao ev3dev e extendendo o Logical Volume ‘root’:
root@ev3dev:~# lvextend --extents +100%FREE /dev/ev3devVG/root
  Extending logical volume root to 3.59 GiB
  Logical volume root successfully resized

[editado posteriormente]

faltou indicar como expandir o file system:

resize2fs  /dev/ev3devVG/root

[se não der  no EV3 pode-se fazer no Ubuntu, precedendo o comando com ‘sudo’]

 

DIY: Power Adapter para NXT/EV3

As experiências com o ev3dev saíram-me caras em pilhas. Como a porta USB é 1.1 e o processador é cerca de 4x mais lento que o do Raspberry Pi, uma operação simples de actualização como

apt-get update
apt-get dist-upgrade

pode demorar uma hora (a primeira vez demorou bem mais, tantos foram os pacotes actualizados). E mesmo com as melhores pilhas já é uma sorte se conseguir que durem 4 horas.

O Philo (Philippe “Philo”Hurbain) tem no seu site duas soluções diferentes:

A primeira solução, mais “limpa”, consiste em refazer uma tampa para o brick Mindstorms com uma ficha para um regulador DC externo. A segunda solução, mais fácil, consiste em criar duas pilhas falsas por onde se estabelece a ligação ao regulador DC externo.

Optei por fazer algo semelhante às pilhas falsas mas sem enveredar pelo método do Philo de destruir uma pilha para aproveitar os contactos (demasiados químicos envolvidos e poucas ferramentas disponíveis). Além disso uma outra pesquisa fez-me concluir poder subsitituir uma das pilha falsas por uma simples garra:

Dexter Industries User Manual Wiki: dSolar
Dexter Industries User Manual Wiki: dSolar

O Philo usa um bastão de cola (para pistolas de colagem a quente) mas eu preferi usar do Polymorph que tenho à disposição. E depois de uma expedição de reconhecimento a um armazém chinês optei por usar um rebite para o contacto positivo da pilha (€0,75 um pacote de 6). Uma ficha para o regulador DC, uma garra e fio eléctrico completam a lista de material:

Com um alicate puxei para fora a cabeça do rebite:

Montei a cabeça ao contrário, ligeiramente saída:

Soldei a cabeça em ambos os extremos e dobrei o rebite:

Depois envolvi o rebite em Polyflex moldando mais ou menos da dimensão de uma pilha e tendo o cuidado de não tapar a cabeça do rebite que fará de contacto:

Depois foi só soldar os fios e a garra (falta isolar com fita isoladora ou manga termoretráctil, fica para depois)

Antes de arriscar queimar um Mindstorms testei o funcionamento «em vazio» com um regulador DC da Hama comprado na Mediamarkt:

É um valor um pouco baixo (6 pilhas AA em vazio fornecem entre 9.0 e 10.0 Volt) mas ainda assim superior aos 7.2 V de uma bateria Li-Ion. Talvez o EV3 aceite o valor acima do regulador (12.0 V) mas é um risco parvo que não vou correr [talvez mais tarde, com 3 díodos em série para abater 2.1 V como fiz na caixa de música LEGO]

A pilha falsa encaixa bem, assim como a garra:

Agora é só ligar:

It works!

Estas e algumas fotos mais no meu espaço Brickshelf.

ev3dev – controlando motores

A utilização básica do LEGO Mindstorms EV3 com ev3dev fica completa com a utilização de motores.

Ligando um motor (45503 EV3 Medium Servo Motor) na ficha A, o sistema operativo acusa o evento:

root@ev3dev:~# dmesg
(...)
tacho-motor tacho-motor0: Tacho motor registered.
ev3-tacho-motor outA:motor: A Tacho Motor connected to port outA gpio 91 irq 192

Uma vez mais é necessário consultar a wiki do projecto ev3dev para entender como aceder aos motores. Estes também são mapeados pelo sistema operativo, desta vez em “/sys/bus/legoev3/devices/” e em ” /sys/class/tacho-motor/”:

root@ev3dev:~# ls /sys/bus/legoev3/devices/
in2  in3  in4  outA  outA:motor  outB  outC  outD
root@ev3dev:~# ls /sys/class/tacho-motor/
tacho-motor0
root@ev3dev:~# ls /sys/class/tacho-motor/tacho-motor0
device           port_name      pulses_per_second     reset        speed_regulation_K  subsystem
duty_cycle     position       pulses_per_second_sp  run            speed_regulation_P  time_sp
duty_cycle_sp  position_mode  ramp_down_sp        run_mode        state            type
estop           position_sp    ramp_up_sp        speed_regulation_D    stop_mode        uevent
polarity_mode  power          regulation_mode        speed_regulation_I    stop_modes

Muito informação para processar mas para começar podemos confirmar apenas o tipo de motor:

root@ev3dev:~# cat /sys/class/tacho-motor/tacho-motor0/type
minitacho

Os motores Mindstorms são inicializados no modo “run forever”, podemos também confirmar isso:

root@ev3dev:~# cat /sys/class/tacho-motor/tacho-motor0/run_mode
forever

Neste modo podemos controlar o motor controlando 2 parâmetros:

  • /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp
  • /sys/class/tacho-motor/tacho-motor0/run

o shell script abaixo faz o motor rodar 5 segundos num sentido e 5 segundos no sentido inverso, com um duty factor de 50%:

 #!/bin/bash
 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 5s
 echo   0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp
 sleep 1s
 echo   -50 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp
 sleep 5s
 echo   0 > /sys/class/tacho-motor/tacho-motor0/duty_cycle_sp
 echo   0 > /sys/class/tacho-motor/tacho-motor0/run

 

 

ev3dev – lendo sensores

Começar a trabalhar com sensores Mindstorms, mais concretamente Touch Sensores. Tenho duas versões: NXT e EV3.

Adicionei touch sensor (NXT) no porto #2. O sistema operativo detecta o acontecimento:

root@ev3dev:~# dmesg
...
msensor sensor0: Mindstorms sensor registered.
touch-sensor in2:nxt-analog-sensor: Touch sensor connected to port in2

Alguma informação útil na wiki do projecto ev3dev:

De acordo com a wiki, os sensores Mindstorms são mapeados em “/sys/class/msensor”:

root@ev3dev:~# ls /sys/class/msensor
 sensor0

Confirma-se a presença de um sensor “sensor0”. Que podemos saber acerca dele?

root@ev3dev:~# ls /sys/class/msensor/sensor0
 bin_data     dp    num_values  subsystem  units   value2  value5
 bin_data_format  mode    port_name   type_id    value0  value3  value6
 device         modes    power        uevent     value1  value4  value7

Muita informação, alguma apenas genérica. Fiquemos por “mode” e “value0”:

root@ev3dev:~# cat /sys/class/msensor/sensor0/mode
 TOUCH

Sim, é um Touch Sensor. E como saber o estado?

root@ev3dev:~# cat /sys/class/msensor/sensor0/value0
 0

O sensor estava em repouso. Vamos repetir enquanto premimos o sensor:

root@ev3dev:~# cat /sys/class/msensor/sensor0/value0
 1

Então e se trocarmos por um sensor EV3?

root@ev3dev:~# dmesg
 ...
 msensor sensor0: Mindstorms sensor unregistered.
 msensor sensor1: Mindstorms sensor registered.
 touch-sensor in2:ev3-analog-sensor: Touch sensor connected to port in2

E qual é o device?

root@ev3dev:~# ls /sys/class/msensor/
 sensor1

Agora é ‘sensor1’ em vez de ‘sensor0’. Talvez a troca tenha sido demasiado rápida ou talvez o sistema operativo nunca liberte os mapeamentos efectuados [até ao próximo boot].

A informação disponível é semelhante:

root@ev3dev:~# ls /sys/class/msensor/sensor1
 bin_data     dp    num_values  subsystem  units   value2  value5
 bin_data_format  mode    port_name   type_id    value0  value3  value6
 device         modes    power        uevent     value1  value4  value7
root@ev3dev:~# cat /sys/class/msensor/sensor1/mode
 TOUCH

E a leitura do estado do sensor funciona da mesma maneira através de ‘value0’.

Este forma do sistema operativo mapear todos os dispositivos no file system dá-nos uma enorme flexibilidade – todas as linguagens de programação permitem aceder a ficheiros… até a própria shell! Eis shell script que se limita a esperar que o sensor seja premido:

#!/bin/bash
 BOTAO=0
 while [ $BOTAO -ne "1" ]; do
 BOTAO=$(cat /sys/class/msensor/sensor0/value0)
 done
 echo "Ouch!" > /dev/tty0

se o ficheiro contendo este script se chamar ’touch.sh’ e tiver permissões de execução podemos invocá-lo directamente da linha de comando:

root@ev3dev:~# chmod +x touch.sh
root@ev3dev:~# ./touch.sh

ou de dentro de outros scripts.

Nota: usei aqui ‘sensor0’, assumo que há apenas um sensor e excepto na situação acima em que retirei um sensor e adicionei outro que por isso ficou ‘sensor1’, será sempre ‘sensor0’.

ev3dev – usando o LCD do EV3

Usando o ev3dev há duas formas de aceder ao LCD do LEGO Mindstorms EV3:

  • modo de texto: terminal via /dev/tty0
  • modo gráfico: framebuffer via /dev/fb0

Ambos os modos estão ainda a sofrer desenvolvimentos mas o segundo modo é seguramente o mais complexo pelo que fico-me por enquanto só pelo modo de texto.

Assim para escrever qualquer coisa basta por exemplo redireccionar o comando echo para /dev/tty0:

echo "Hello world!" > /dev/tty0

Já é qualquer coisa mas para limpar o ecran sem ter de enviar vários “echo” existem formas melhores. Sendo um terminal tty convencional, a maioria dos comandos para terminal devem funcionar (inclusive algumas sequencias de escape). Experimentei o tput:

Para limpar o ecran:

tput clear > /dev/tty0

Para posicionar o cursor:

tput cup linha coluna > /dev/tty0

(tput cup 0 0 envia para o canto superior esquerdo e já agora com tput cols ficamos a saber que o LCD tem 44 colunas)

Para escrever branco sobre negro:

tput smso > /dev/tty0

Para voltar ao negro sobre branco:

tput rmso > /dev/tty0

Muito bem, já escrevo o que quiser em qualquer lado do ecran… mas a fonte é tão pequena que só com uma lupa é que se lê. Como aumentar o texto?

A primeira hipótese que me ocorreu foi instalar o figlet que usa caracteres ASCII para fingir fontes maiores:

apt-get install figlet
figlet -f banner "Teste" > /dev/tty0
figlet -f big "Teste" > /dev/tty0

teste01mas é uma forma um bocado coxa. O melhor mesmo é poder trocar o tamanho dos caracteres e para isso existe o comando “setfont” que felizmente já existe no ev3dev e disponibiliza umas quantas fontes em “/usr/share/consolefonts/”, vejamos só quantas há na variante Lat15 (que serve à maioria das linguas ocidentais incluindo a nossa):

root@ev3dev:~# ls /usr/share/consolefonts/Lat15*
/usr/share/consolefonts/Lat15-Fixed13.psf.gz
/usr/share/consolefonts/Lat15-Fixed14.psf.gz
/usr/share/consolefonts/Lat15-Fixed15.psf.gz
/usr/share/consolefonts/Lat15-Fixed16.psf.gz
/usr/share/consolefonts/Lat15-Fixed18.psf.gz
/usr/share/consolefonts/Lat15-Terminus12x6.psf.gz
/usr/share/consolefonts/Lat15-Terminus14.psf.gz
/usr/share/consolefonts/Lat15-Terminus16.psf.gz
/usr/share/consolefonts/Lat15-Terminus20x10.psf.gz
/usr/share/consolefonts/Lat15-Terminus22x11.psf.gz
/usr/share/consolefonts/Lat15-Terminus24x12.psf.gz
/usr/share/consolefonts/Lat15-Terminus28x14.psf.gz
/usr/share/consolefonts/Lat15-Terminus32x16.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold14.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold16.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold20x10.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold22x11.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold24x12.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold28x14.psf.gz
/usr/share/consolefonts/Lat15-TerminusBold32x16.psf.gz
/usr/share/consolefonts/Lat15-TerminusBoldVGA14.psf.gz
/usr/share/consolefonts/Lat15-TerminusBoldVGA16.psf.gz
/usr/share/consolefonts/Lat15-TomThumb4x6.psf.gz
/usr/share/consolefonts/Lat15-VGA14.psf.gz
/usr/share/consolefonts/Lat15-VGA16.psf.gz
/usr/share/consolefonts/Lat15-VGA28x16.psf.gz
/usr/share/consolefonts/Lat15-VGA32x16.psf.gz
/usr/share/consolefonts/Lat15-VGA8.psf.gz

Bold e 32×16 parece-me bem por isso:

tput clear > /dev/tty0
setfont /usr/share/consolefonts/Lat7-TerminusBold32x16.psf.gz
echo "Hello World" > /dev/tty0

helloworldOs 11 caracteres de “Hello World” encheram uma linha (onde antes, com a fonte default, cabiam 44). Pelo menos já não é precisa a lupa.

ev3dev com USB Hub e USB Audio

Depois de ter Wi-Fi decidi testar mais alguns dispositivos USB que uso com o Raspberry Pi.

Para começar, uma vez que o EV3 apenas tem uma porta USB, imprescindível um hub, de preferência pequeno:

Hub KUNFT 4 Portas USB 2.0 H-088 (na Worten por €6,99)

Com o EV3 ainda desligado liguei-o e a ele o dongle Wi-Fi (ThePiHut).

Da primeira vez não obteve rede, não sei se não esperei tempo suficiente. Retirei o hub, liguei novamente (sem o dongle Wi-Fi) esperei um pouco e depois liguei o dongle e desta vez obtive rede. E a partir daqui cada boot/reboot com tudo ligado funcionou sempre bem.

root@ev3dev:~# lsusb
(...)
Bus 001 Device 002: ID 05e3:0608 Genesys Logic, Inc. USB-2.0 4-Port HUB

Agora o audio:

[Nota: o EV3 já tem uma placa de audio interna, suportada pelo ALSA, e um altifalante interno também. Mas tanto quanto percebi funciona de modo semelhante ao jack audio do Raspberry Pi, por PWM, consumindo CPU… além de ser mono e não permitir ligação externa a um amplificador]

DIY USB to Audio Module for Raspberry PI / Arduino / MAC / PC + More – Green (SKU 315287 na DX – DealExtreme, US$10.88)

root@ev3dev:~# dmesg
(...)
input: Burr-Brown from TI               USB Audio DAC    as /devices/platform/ohci.0/usb1/1-1/1-1.4/1-1.4:1.2/0003:08BB:2704.0001/input/input2
hid-generic 0003:08BB:2704.0001: input: USB HID v1.00 Device [Burr-Brown from TI USB Audio DAC   ] on usb-ohci.0-1.4/input2
(...)
root@ev3dev:~# lsusb
(...)
Bus 001 Device 004: ID 08bb:2704 Texas Instruments Audio Codec
(...)

O ALSA reconhece de imediato a nova placa de som:

root@ev3dev:~# aplay -l
**** List of PLAYBACK Hardware Devices ****
card 0: legoev3 [LEGO Mindstorms EV3 speaker], device 0: LEGO Mindstorms EV3 [LEGO Mindstorms EV3]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
card 1: DAC [USB Audio DAC], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0
root@ev3dev:~# alsamixer
┌───────────────────────────── AlsaMixer v1.0.28 ──────────────────────────────┐
│ Card: LEGO Mindstorms EV3 speaker                    F1:  Help               │
│ Chip:                                                F2:  System information │
│ View: F3:[Playback] F4: Capture  F5: All             F6:  Select sound card  │
│ Item: Playback                                       Esc: Exit               │
│                                                                              │
│                                     ┌──┐                                     │
│                                     │  │                                     │
│                                     │  │                                     │
│                       ┌───────── Sound Card ─────────┐                       │
│                       │-  (default)                  │                       │
│                       │0  LEGO Mindstorms EV3 speaker│                       │
│                       │1  USB Audio DAC              │                       │
│                       │   enter device name...       │                       │
│                       └──────────────────────────────┘                       │
│                                     │▒▒│                                     │
│                                     │▒▒│                                     │
│                                     │▒▒│                                     │
│                                     │▒▒│                                     │
│                                     └──┘                                     │
│                                      75                                      │
│                                  <Playback>                                  │
│                                                                              │
└──────────────────────────────────────────────────────────────────────────────┘

E para tocar um ficheiro mp3 (previamente trasnferido por ssh):

root@ev3dev:~# apt-get install mpg321
root@ev3dev:~# mpg321 -a hw:1,0 Thunderstruck.mp3

Rock’n Roll!!!

Durante a execução o mpg321 consome entre 22 a 25% de CPU. É um bocado alto (quando se utiliza a rede em simultâneo, por exemplo um update, ocorrem soluços) e como dizem que o SoX consome menos CPU…

root@ev3dev:~# apt-get install sox libsox-fmt-all
root@ev3dev:~# export AUDIODEV=hw:1,0
root@ev3dev:~# play Thunderstruck.mp3

Durante a execução o play consome  20 a 22% de CPU, apenas marginalmente melhor.
Mas como SoX permite vários formatos (wav, ogg…) permite o redireccionamento (pipe) de outros comandos como o espeak:

root@ev3dev:~# espeak -v pt-pt “olá” –stdout | play -t wav –

E temos o nosso EV3 a falar português 🙂

EV3 wireless com ev3dev

Depois de instalar a última versão do ev3dev (ev3dev-jessie-2014-07-12) experimentei ligar 2 dos dongles Wi-FI que uso com o Raspberry Pi:

  • ThePiHut
  • Wi-Pi

Para o kernel são o mesmo dispositivo:

root@ev3dev:~#lsusb
ID 148f:5370 Ralink Technology, Corp. RT5370 Wireless Adapter

Mas não foram carregados nenhuns drivers por isso actualizei:

root@ev3dev:~#apt-get update
root@ev3dev:~#apt-get upgrade
root@ev3dev:~#apt-get dist-upgrade
root@ev3dev:~#reboot

Agora o Debian já tem os drivers:

root@ev3dev:~#dmesg
(...)
usbcore: registered new interface driver rt2800usb
(...

mas surge uma outra mensagem sobre não carregar o firmware por isso

root@ev3dev:~#dmesg
apt-get install firmware-ralink
ieee80211 phy1: rt2x00_set_rt: Info - RT chipset 5390, rev 0502 detected
ieee80211 phy1: rt2x00_set_rf: Info - RF chipset 5370 detected
ieee80211 phy1: Selected rate control algorithm 'minstrel_ht'
ieee80211 phy1: rt2x00lib_request_firmware: Info - Loading firmware file 'rt2870.bin'
ieee80211 phy1: rt2x00lib_request_firmware: Info - Firmware detected - version: 0.29

E para a ligação wireless, à semelhança do Raspbian no Pi, editei o ficheiro ‘interfaces’:

root@ev3dev:~#nano /etc/network/interfaces
# interfaces(5) file used by ifup(8) and ifdown(8)
# Include files from /etc/network/interfaces.d:
source-directory /etc/network/interfaces.d

### acrescentar as linhas abaixo ###
auto lo
iface lo inet loopback
allow-hotplug wlan0
iface wlan0 inet dhcp
   wpa-ssid "WI-Fi SID"
   wpa-psk "Wi-Fi Password"

iface default inet dhcp

Confirma-se:

root@ev3dev:~#ifconfig
wlan0     Link encap:Ethernet  HWaddr 00:0f:55:a8:ac:0a  
          inet addr:192.168.1.69  Bcast:192.168.1.255  Mask:255.255.255.0
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:11 errors:0 dropped:0 overruns:0 frame:0
          TX packets:5 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:1447 (1.4 KiB)  TX bytes:1074 (1.0 KiB)

Só não percebo porque motivo só funciona um dos dongles (o ThePiHut) quando aparentam ser iguais. Talvez o firmware não o seja completamente.