EV3MP3 – Um MP3 Player em LEGO

Encontrei quase por total acaso um projecto muito interessante: ev3dev.

Trata-se de uma versão de Debian para o LEGO Mindstorms EV3. Não há qualquer alteração ao firmware do EV3 – o bootloader do EV3 arranca a imagem do ev3dev instalada num cartão micro-SD.

Alguras horas depois de começar (a maior parte delas apenas a fazer actualizações de sistema já que o EV3 é cerca de 4x mais lento que um Raspberry Pi e como a versão do chipset USB é apenas 1.1 por a ligação Wi-Fi nunca fará mais que 11 mbps) descobri que o ev3dev se dá muito bem com muito do hardware que utilizo com o Raspberry Pi, nomeadamente:

  • Hub USB
  • ThePiHut Wi-Fi USB card
  • Audio USB card

Com meia duzia de linhas temos um shell script que nos saúda num português macarrónico e toca uma música em formato MP3 após ser premido um touch sensor:

#!/bin/bash

# play deve usar USB sound card
export AUDIODEV=hw:1,0

# saudar utilizador

tput clear > /dev/tty0
figlet -f small "Carregue" > /dev/tty0
figlet -f small "para" > /dev/tty0
figlet -f small "ouvir" > /dev/tty0
figlet -f small "musica" > /dev/tty0

espeak -v pt-pt "olá  queres ouvir uma música?" --stdout | play -t wav -

BOTAO=0
while [ $BOTAO -ne "1" ]; do
  BOTAO=$(cat /sys/class/msensor/sensor0/value0)
done

tput clear > /dev/tty0
figlet -f small "No ar:" > /dev/tty0
figlet -f mini "Highway To Hell" > /dev/tty0
figlet -f small "(AC/DC)" > /dev/tty0

mpg321 -a hw:1,0 HighwayToHell.mp3 -g 20

tput clear > /dev/tty0

Para quem tmabém possa estar interessado, após os updates de sistema a versão do kernel é a 3.14.7:

root@ev3dev:~# uname -a
Linux ev3dev 3.14.7-2-ev3dev-pre1 #2 PREEMPT Tue Jul 15 22:29:55 CDT 2014 armv5tejl GNU/Linux

e o htop diz que estou a usar 25 dos 57 MB de RAM disponíveis além de 7 dos 63 MB de swap.

O processador é reconhecido como um ARM926EJ-S rev 5 (v5l):

root@ev3dev:~# cat /proc/cpuinfo
processor    : 0
model name    : ARM926EJ-S rev 5 (v5l)
Features    : swp half thumb fastmult edsp java
CPU implementer    : 0x41
CPU architecture: 5TEJ
CPU variant    : 0x0
CPU part    : 0x926
CPU revision    : 5

Hardware    : LEGO MINDSTORMS EV3 Programmable Brick
Revision    : 0000
Serial        : 0000000000000000

 

SmartBrick – em breve num LEGO perto de si

A campanha KickStarter atingiu o primeiro objectivo, 7 dias antes da deadline e posso orgulhar-me de ter dado o meu contributo. Espero poder ajudar ainda mais nos próximos meses, vamos a ver.

To everyone who has made this possible,

We want to thank you from the bottom of our hearts for all the help you have given us over the last three weeks. All the support you have given has led this project to success. We know the hard part only begins now, as we have just placed our order for the first shipment of BLE chips 🙂

We want to thank you for the all the work you have put into spreading the news about the project. You are responsible for the wonderful karma that has been with us all along the way!

Dear Friends,  and we think we can call you that by now, we have worked really hard over the last 8 months in building SBrick for you. Now that we have reached our funding goal, our common dream will become a reality,  and you will be there with us to enjoy all the fun that this project will bring!

Thank you again for all your support, and keep on supporting the SBrick!

Estou ansioso por poder testar um bichinho destes com o Raspberry Pi e com o LEGO Mindstorms EV3. Acho que é desta que vou aprender a programar decentemente em Python 😉

Crowdfunding: SmartBrick

Decidi apoiar um novo projecto de crowdfunding: SmartBrick.

Basicamente um bloco WeDO mais poderoso e sem o cabo USB, apenas Bluetooth.

Para quem estiver interessado, o site do produto e da empresa-mãe, a Vengit.

[actualização de 28 de Julho]

O projecto tem o apoio de figuras como o Philo e o Sariel. Este último participou numa review de um protótipo:

[adição de 6 de Agosto]

O conhecido Nico71 também participou numa review:

 

 

Caixa de música LEGO – o software

This post is part 2 of 2 of  Caixa de Música LEGO

Tópicos:

  • Pré-requisitos
  • Preparação do cartão SD
  • Configurações do sistema
  • Script em python
  • Automatismo
  • Vários

Pré-requisitos

Convém ter um cartão SD com capacidade 4 GB ou superior, categoria 4 ou superior. O cartão pode ser micro- ou mini-SD desde que se disponha de um adaptador para o formato SD.

É também necessário um computador equipado para lidar com cartões SD ou então um adaptador SD USB.

Estas indicações são para um sistema Linux (mais concretamente Ubuntu 14.04). Não é difícil adaptar para um sistema Windows mas já há  muito não uso nenhum.

Preparação do cartão SD

É necessário um sistema operativo para Raspberry Pi. Eu prefiro o Raspbian por ser baseado em Debian tal como o Ubuntu que venho utilizando há já alguns anos. A versão mais recente está sempre disponível na Raspberry Pi Foundation – o ficheiro .zip contém um ficheiro único, uma imagem de um cartão inteiro pronto a usar (na versão de Junho de 2014 a imagem tem 3.0 GB pelo que um cartão de 4 GB continua a ser suficiente).

O Ubuntu tem uma aplicação gráfica “Disks” (na linha de comando “gnome-disks”) que permite entre outras coisas escrever imagens. Seleccionamos o cartão SD (qualquer coisa como “4 GB Block Device | /dev/mmcblk0”) e depois “Restore disk image” escolhendo o ficheiro .img do Raspbian.

O cartão tem agora duas partições:

  • BOOT
  • 2.9 GB Volume

A primeira será usada como “/boot” e a segunda como “/” como é habitual ma maioria das instalações Linux. Não existe a habitual partição para swap porque [pelo menos no Raspbian] é utilizado um ficheiro dentro de “/”.

Antes de colocar o cartão no Raspberry é necessário alterar alguns ficheiros para ter um sistema funcional. Se montamos a segunda partição (“2.9 GB Volume”) como /X precisamos criar ou editar 2 ficheiros:

  • /X/etc/hostname
  • /etc/network/interfaces

sudo /X/etc/hostname

Este ficheiro deve conter uma única linha, com o nome pelo qual o sistema operativo vai responder:

caixademusica

sudo /X/etc/network/interfaces

Este ficheiro contém a configuração da rede Wi-Fi:

auto lo

allow-hotplug wlan0
iface wlan0 inet dhcp
   wpa-ssid "RedeWiFi"
   wpa-psk "PasswordDaRedeWifi"

iface default inet dhcp

Podemos mais tarde utilizar um endereço IP estático em vez de recorrer ao cliente DHCP (deve acelerar ligeiramente o arranque e utilizar ligeiramente menos RAM). Neste exemplo defini só uma rede Wi-Fi mas é possível definir várias, ver o meu artigo “Raspberry Pi – headless + wireless” (para mim é suficientemente uma única rede já que tenho um router 3G de  bolso configurado de forma semelhante à rede de casa e assim quando levo um Raspberry Pi comigo para testes ou demonstrações uso sempre a mesma configuração).

O cartão já pode ser colocado no Raspberry Pi, podemos confirmar o endereço IP na página de configuração do router (se estivermos a usar DHCP) e aceder remotamente por SSH:

ssh pi@192.168.1.67

(“pi” é o utilizador pré-configurado no Raspbian – a password é “raspberry”, convém alterar mais tarde com o comando “passwd” – e 192.168.1.67 é o endereço que no router aparece atribuido ao host “caixademusica”).

Configurações do sistema

Tendo acesso remoto à Caixa de Música é necessário expandir o file system do cartão de modo a utilizar toda a capacidade deste (como referi, até Junho de 2014 a imagem ocupa apenas 3 GB pelo que num cartão de 4 GB fica 1 GB por alocar e que pode fazer falta)

sudo raspi-config

Escolher “Expand Filesystem” e no final se não for dada opção de reboot (não recordo) dar o comando

sudo reboot

No próximo login o cartão deverá ter cerca de 1.4 GB disponíveis:

df -h

Filesystem      Size  Used Avail Use% Mounted on
rootfs          3.6G  2.0G  1.4G  60% /
/dev/root       3.6G  2.0G  1.4G  60% /
devtmpfs        211M     0  211M   0% /dev
tmpfs            44M  232K   44M   1% /run
tmpfs           5.0M     0  5.0M   0% /run/lock
tmpfs            88M     0   88M   0% /run/shm
/dev/mmcblk0p1   56M   19M   38M  34% /boot

Já é bastante mas como não vou utilizar ambiente gráfico (desktop) posso libertar mais algum espaço (cerca de 1.2 GB mais) e reduzir o peso de futuros updates com os dois comandos:

sudo apt-get --purge remove cups.* xserver.* x11.*
sudo apt-get autoremove

Vamos agora actualizar o Raspbian para a última versão de todos os pacotes instalados:

sudo apt-get update
sudo apt-get dist-upgrade

E instalar as ferramentas necessárias:

sudo apt-get install htop mpg321 mp3gain
  • htop não é necessário mas gosto de utilizá-lo em vez do top nativo.
  • mpg321 é um player não-gráfico de ficheiros mp3 que vai servir para tocar a música que acompanha a «bailarina».
  • mp3gain permite ajustar o ganho dos ficheiros mp3, muito útil quando estes parecem ouvir-se pior que a maioria dos restantes
sudo apt-get install python-pip python3-pip
sudo pip install sh
sudo pip3 install sh
  • sh é uma library de python que permite invocar comandos da shell (do sistema operativo) e que vou usar no meu programa por isso preciso de instalar primeiro.
  • pip é um gestor de libraries para python (instalo duas versões – para python v2 e python v3 – provavelmente bastará a última)

 

Script em pyhton

[por completar]

Automatismo

[por completar]

Vários

[por completar]

 

Caixa de música LEGO

This post is part 1 of 2 of  Caixa de Música LEGO

Esta caixa de música foi a minha prenda de aniversário para a minha marida:

A feliz proprietária abre uma pequena painel lateral para ligar a Caixa e enquanto esta «aquece» (≈25 s) levanta o painel superior, retira a «bailarina» do «guarda-jóias» e insere-a no local apropriado. Por essa altura já a Caixa está pronta para ser usada sendo ouvido um «tcham!» indicador de que já se pode carregar no botão dissimulado dentro do «guarda-jóias» para activar a música e a «bailarina».

No coração da montagem está um Raspberry Pi que lê o botão e acciona o motor enquanto  toca uma música, armazenada em formato MP3. Opcional (mas útil) uma ligação Wi-Fi permite acesso remoto para controlo, despiste ou apenas actualização da música.

Componentes:

  • controlador: Raspberry Pi
  • módulo GPIO: PiFace Digital
  • cartão SD: de 4 GB ou mais
  • (opcional) adaptador micro-SD low profile
  • adaptador áudio USB
  • micro-altifalantes: 50 Ω
  • auscultadores velhos
  • adaptador Wi-Fi USB
  • extensão USB
  • bateria: LEGO Power Functions Rechargeable Battery Box
    (84599)
  • 3 díodos 1N4001 ou semelhantes
  • motor: LEGO Power Functions Medium Motor (8883)
  • botão: LEGO Touch Sensor (879)
  • cabos eléctricos LEGO canibalizados
  • peças, muitas peças LEGO

O controlador: Raspberry Pi

Em abono da verdade, o Raspberry Pi deveria ser “model A” em vez de “model B” mas [ainda] não tenho nenhum. Como o “model A” não tem interface de rede e tem apenas metade da RAM (256 MB em vez de 512 MB) e metade das portas USB (1 em vez de 2) o consumo eléctrico é bastante menor (este artigo refere 115 mA contra 400 mA).

O módulo GPIO: PiFace Digital

O PiFace Digital também não é essencial – apenas utilizo uma entrada e uma saída pelo que é quase um desperdicio (o PiFace tem 8 saídas e 8 entradas e além disso 2 relés e 4 teclas). A grande vantagem é simplficar duas ligações sem ocupar muito espaço:

  • o motor LEGO é ligado directamente a uma das saídas (sem o PiFace teria de usar um transistor e uma resistência)
  • a bateria a LEGO é ligada directamente ao PiFace que por sua vez alimenta o Raspberry Pi (sem o PiFace teria de injectar a alimentação através da ligação micro-USB do Raspberry Pi e não tenho nenhum adaptador que o permita)

O cartão SD

O cartão SD de 4 GB permite instalar o sistema operativo Raspbian (uma versão de Debian adaptada para o Raspberry Pi com o qual me sinto confortável após vários anos com Ubuntu Linux). O ideal seria um cartão rápido para que o tempo de arranque da Caixa de Música fosse curto. Mas “rápido” é algo relativo e não notei grandes diferenças entre os vários cartões classe 4 e classe 10 (inclusive UHS-I) que experimentei.

O adaptador micro-SD

Uma opção (que foi encomendada mas infelizmente não chegou a tempo) seria um adaptador para formato micro-SD que quase não se prolonga para fora do slot do Raspberry Pi e permitiria ganhar alguns cm² de espaço útil na montagem da Caixa. Fica para uma próxima revisão.

O adaptador áudio USB e os micro-altifalantes

O adaptador áudio USB (semelhante a este mas sem cabo) foi fruto de várias tentativas-e-erros. O Raspberry Pi tem uma saída áudio (ficha standard para jack de 3,5 mm stereo) mas a impedância de saída é alta e o sinal muito fraco – essencialmente serve apenas para auscultadores ou eventualmente um amplificador aúdio. Além disso a fidelidade não é muito alta (salvo erro o sinal é gerado por PWM tendo mais ou menos 12 bit de resolução) mas ainda assim seria suficiente para o fim pretendido.

Infelizmente as primeiras experiências com micro-altifalantes de 8 Ω foram frustrantes, o volume era muito reduzido. Experimentei depois umas micro-colunas amplificadas (com alimentação USB) e o som era excelente… mas só quando alimentadas por uma ligação USB independente – quando alimentadas pelo Raspberry Pi captavam (e amplificavam!) interferências e o som tinha um ruído de fundo insuportável. Aparentemente o Raspberry Pi gera demasiado ruído eléctrico (no ar ou na massa) para poder utilizar um amplificador que partilhe a mesma alimentação. Talvez umas colunas semelhantes mas com ligação Bluetooth contornem o problema, um dia pode ser que experimente.

Entretanto encontrei uns micro-altifalantes de 50 Ω que sempre ofereciam um som um pouco mais alto mas ainda insatisfatório – apesar da melhor adaptação de impedâncias,o sinal é demasiado fraco. Por isso decidi experimentar um adaptador áudio USB que tinha algures na caixa de spares, ainda suficientemente pequeno para com algum jeito caber na caixa. Com os micro-altifalantes de 50 Ω o resultado foi finalmente satisfatório (com as colunas USB o resultado continuava a ser ruidoso, apesar de o perfil do ruído ser bastante diferente).

Os altifalantes não trazem nenhum cabo, Aproveitei uns auscultadores velhos (deu jeito terem um jack em cotovelo), cortei o cabo para não ficar tão longo, soldei as pontas aos altifalantes e reforcei a zona da soldadura com cola para evitar que algum gesto mais brusco arrancasse os cabos ou mesmo a solda. Colei também um tile redondo (4150) a cada altifalante para facilitar a fixação a outras peças LEGO (“Release the kragle!”).

O adaptador Wi-Fi USB

O adaptador Wi-Fi USB foi precioso na fase de desenvolvimento: em vez de ligar o Raspberry Pi a um monitor e a um teclado, configuro o sistema operativo para ligar-se à minha rede Wi-Fi e acedo remotamente por SSH (“PuTTY” para os que só usam Windows). No final deixa de ser necessário e se o remover até se poupam alguns mA de consumo mas preferi deixar ficar – se quiser alterar a música, mudar o programa ou acrescentar funcionalidades não preciso desmontar a Caixa para retirar o cartão SD (uma funcionalidade que me ocorre é usar como fonte de audio uma Internet Radio ou um Media Center doméstico em vez de um ficheiro local).

Convém um adaptador Wi-Fi de pequenas dimensões (mas que seja reconhecido pelo sistema operativo). O DWA-131 da D-Link é pequeno mas vem a caminho um ainda menor.

A extensão USB

A extensão USB surgiu devido ao tamanho escolhido para a Caixa que não permitia ter o adaptador áudio ligado directamente ao Raspberry Pi. Um cabo USB curto poderia fazer o mesmo efeito mas gostei da extensão, o enrolamento encaixou bem no espaço disponível e o cabo é bastante fino e flexível. Estou a considerar como alternativa um adaptador «em cotovelo» (ou mesmo dois, encadeados), logo se vê.

A bateria e os díodos

A bateria começou por não ser LEGO: queria que a Caixa se ligasse automaticamente quando a tampa fosse aberta por isso montei um pequeno microswitch junto à tampa, ligado (“N.O. – normally open”) a um pack de 4 pilhas AA com um díodo 1N4001 em série (as 4 pilhas AA, alcalinas, fornecem cerca de 6.0 V que o díodo reduz para cerca de 5.3). Infelizmente no dia do aniversário o microswitch partiu-se e apercebi-me que trocar as pilhas quando estivessem gastas ia ser complicado por isso decidi usar uma bateria LEGO Power Functions Li-Po (8878) que é compacta e permite ser recarregada. Só que como não consegui uma forma simples de accionar o botão desta com a abertura da Caixa acabei por fazer uma porta lateral, pequena e discreta, que dá acesso ao botão e à ficha para ligar o carregador externo.

Como a bateria 8878 fornece 7.4 V em vez de 6.0 V utilizei 3 díodos 1N4002 (era o que tinha, qualquer um da famíla server) em série para reduzir a tensão para cerca de 5.3 V. Cortei um cabo Power Functions a meio, aproveitei a metade com a ficha cinza-escura e descarnei os condutores exteriores – com um multímetro identifiquei o positivo (ao qual soldei os 3 díodos) e o negativo. Isolei o conjunto com adesivo isolador e liguei aos terminais de alimentação do PiFace Digital:

Nota: é possível dispensar os díodos e usar os condutores interiores em vez dos exteriores. Nesse caso, com o múltimetro, mede-se a tensão de saída enquanto com um eixo Technic se roda o «controlo de velocidade» laranja que vem na bateria até obtermos algo próximo dos 5.2 V. Mas é imperioso que NUNCA ninguém mexa nesse controlo pois valores superiores a 5.5 V ou negativos convertem o Raspberry Pi e o PiFace Digital num pisa-papéis original e caro.

O motor

O primeiro motor LEGO que utilizei foi um micromotor (2986), a minha preocupação nessa altura era apenas com o espaço disponível. A ligação aos terminais do PiFace Digital é feita com a ajuda de metade de um cabo eléctrico LEGO Technic (a outra metade também é aproveitada para ligar o botão) bastando descarnar as pontas e apertar os parafusos. Como as saídas do PiFace são Open Collector o micromotor não chega a receber sequer 5 V e por isso roda suficientemente devagar para dispensar engrenagens – coloquei a minifig que vai servir de «bailarina» directamente sobre o eixo. Mas o motor é barulhento e as formas trapalhonas que arranjei para o montar deixaram-me a pensar que se calhar não poupava assim tanto espaço quanto isso.

O segundo motor LEGO que utilizei foi um “M” (8883). Roda bastante mais rápido por isso foi necessário um par de engrenagens para reduzir 1:24 (fui buscar inspiração ao livro da No Starch Press  “The LEGO Technic Idea Book: Simple Machines” do Mestre Yoshihito Isogawa). Ocupa mais espaço que a opção anterior mas apenas horizontalmente, lá consegui encaixar. Infelimente é também muito barulhento. A ligação é feita com metade de um cabo Power Functions, à semelhança do que foi feito com a bateria.

Já depois de montada a Caixa descobri no fórum Eurobricks que o motor era bastante menos ruidoso e lembrei-me que tinha 1 (um!) algures. A troca foi quase directa e confirma-se: é muito menos ruídoso, já não abafa a música.

Nota: estou a controlar o motor de uma forma muito simples: quando a música começa a tocar a porta de saída do PiFace que controla o motor é activada e só quando a música pára é que é desactivada. Se me esforçar um pouco na programação talvez consiga activar a porta apenas por períodos de 1 ms em cada 24 ms (controlo PWM) e nesse caso dispensar a engrenagem e provavelmente reduzir um pouco no ruído e no consumo eléctrico.

O botão

Finalmente o botão que controla a música e a «bailarina» consiste num sensor de toque da família Mindstorms RCX, ligado directamente a uma das portas de entrada do PiFace Digital por intermédio da outra metade de cabo eléctrico LEGO Technic que sobrou anteriormente.

As peças LEGO

Pois… foram muitas e ainda não as contabilizei. Mas quase todas pretas e algumas cinzentas. Porque «eu só uso preto… e às vezes cinzento mas muito escuro» (mentira… usei azuis também, para fixar os componentes não-LEGO – como estão por dentro ninguém vê).

A montagem

Começando de baixo:

A base

A base da Caixa é uma peça única, um brick 12×24 preto (30072). A toda a volta desta peça ergui paredes com a espessura de 1 stud – as paredes menores à custa de bricks lisos pretos porque vão ficar expostas, já as paredes maiores não precisam ser lisas nem sequer pretas porque vão ser revestidas cada uma com outro brick 12×24 também preto; optei por bricks Technic onde posso ligar pinos Technic (2780)  para encaixar facilmente as paredes exteriores. Em alguns níveis utilizei cantos 2×2 (2357)

Coloquei o Raspberry Pi (já com o Piface Digital encaixado) e toda a parafernália não-LEGO associada por cima e sei peças azuis para fixar a posição destes dentro da Caixa.

Uma das paredes menores não é completamente sólida – é necessária uma abertura para acesso ao botão de ligar/desligar da bateria e à ficha onde encaixa o recarregador. Montei uma portinhola com um pequeno puxador.

Como o cartão SD sai ligeiramente mais que 2 studs para fora do Raspberry Pi (ainda não chegou o adaptador low profile) coloquei duas camadas de plates em torno deste para sustentar a bateria por cima do cartão.

O piso intermédio

Por cima da electrónica monto uma plataforma para sustentar a componente mecânica e simultâneamente servir de fundo ao «guarda-jóias» e dar firmeza à protilnhola:

Por cima da plataforma ergo mais paredes – as duas menores exteriores já completamente sólidas/lisas enquanto que as outras duas exteriores permancem Tecnhic e agora uma parede interior do «guarda-jóias» que aloja o botão de comando:

O telhado

Por cima das componentes mecânicas é montado um telhado revestido de tiles pretos, assim como o topo das paredes envolventes do «guarda-jóias»:

Este telhado tem 3 plates de espessura, sendo colocado um disco Technic 3×3 (2958) na camada intermédia, sem nenhum tile por cima nem e um plate Technic 2×8 (3738) por baixo de modo a ser atravessado por um eixo Technic sem deixar ver mais do que a abertura em cruz.

O revestimento das paredes laterais

Em dois níveis das paredes laterais coloquei pinos Technic para fixar os bricks 12×24:

Hoje penso que se tivesse mais bricks compridos pretos não-Tecnhic à disposição não valia a pena usar este revestimento…

A tampa

A tampa consistem em 3 tiles gigantes (90498) cinzentos sobre uma série de plates pretos que infelizmente não lhe dá nem solidez suficiente, tendo tendência a empenar:

A união entre a tampa e uma das paredes laterais é assegurada por 4 dobradiças (4315 + 4213). Não é lá muito sólido, quando tiver tempo copio o método utilizado na Caixa de Jóias LEGO Friends (set 40114).

A bailarina

Qualquer minifig serve mas a Pequena Sereia é especial para a minha marida. Basta um eixo Technic (4519) e um plate redondo com furo em cruz (4032) para completar:

Software

Fica para outro post, este já está MUITO longo.

O futuro

Para uma próxima oportunidade há já várias ideias de melhoramentos:

  • diminuir os ruídos mecânicos (menos engrenagens, controlo PWM)
  • aumentar a duração da bateria (Raspberry Pi model A, controlo PWM)
  • melhorar tampa e revestimentos laterais
  • [ideia do forum PLUG] rebater o tecto e substituir tiles por um cenário apropriado ou mesmo cenários substituíveis
  • programação, muita programação

Mais fotos de pormenor estão nesta pasta do Brickshelf e comentários ou sugestões podem ser feitos ou apenas acompanhados nesta thread do fórum da PLUG.

Pitágoras e Base Jumping

Com 2 sensores de toque (é o que tenho neste momento) e um motor ocorreu-me um elevador automático, capaz de desligar ou reverter o motor cada vez que a cabina atinja um dos extremos do percurso:

pitagoras-elevator

O elevador em si não é muito diferente do de elevador de Linda Hamilton e a ideia da sua utilização com um Raspberry Pi e um PiFace Digital também não é original (Reinoud de Lange recorreu a microswitches em vez de sensores LEGO).

O código (um loop infinito que desloca a cabina para cima e para baixo)

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]
in1=pifacedigital.input_pins[1]

subir=True

sleep(2.0)

while(True):
 if(in1.value != 0):
   print("EM BAIXO!")
   led6.turn_on()
   sleep(0.025)
   led6.turn_off()
   subir=True

 if(in0.value != 0):
  print("NO ALTO!")
  led7.turn_on()
  sleep(0.025)
  led7.turn_off()
  subir=False

 if((in0.value ==0) and (in1.value ==0)):
   if (subir):
     print("PARA CIMA!")
     led6.turn_on()
     sleep(0.025)
     led6.turn_off()
   else:
     print("PARA BAIXO!")
     led7.turn_on()
     sleep(0.025)
     led7.turn_off()

Alguns pormenores da montagem:

elevator-bottom-sensor
O sensor no fundo do «poço» do elevador
elevator-winch
O mecanismo que puxa o elevador
elevator-top-sensor
O sensor no topo do «poço» do elevador
elevator-cabin-basejumper
A cabina do elevador levando um assustado base jumper

Pitagoras e a Esfinge

Faltava ainda um tipo qualquer de sensor para ter um sistema verdadeiramente autónomo por isso liguei um sensor de toque LEGO Mindstorms (ainda estilo RCX) a uma das entradas digitais PiFace.

O PiFace tem 8 entradas digitais com pull-ups internos (li algures que se podem desligar, deixando as entradas «flutuantes»). Como o sensor de toque RCX é um mero interruptor basta ligar um dos cabos a uma das entradas e o outro à massa. Com o sensor em repouso (interruptor aberto) a entrada do PiFace vai ler um “1” e quando ocorrer contacto (interruptor fechado) a entrada vai ficar ligada à massa e é lido um “0”.

bricklink.com: Lego Touch Sensor (879)

É muito fácil acompanhar o estado do sensor, basta ler continuamente o estado da entrada. No script abixo usei a entrada #0 e acrescentei um atraso de 200 ms entre cada leitura para não inundar o terminal com mensagens “ON!” ou “OFF!”

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]

while(True):
 if(in0.value != 0):
   print("ON!")
 else:
   print("OFF!)
 sleep(0.2)

E se quisermos usar o sensor para controlar o leão basta juntar tudo:

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

DELAY_UP = 0.17
DELAY_DOWN = 0.14
DELAY_WAIT = 0.75

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()
in0=pifacedigital.input_pins[0]

while(True):
 if(in0.value != 0):
   print("Para cima!")
   led7.turn_on()
   sleep(DELAY_UP)
   led7.turn_off()
   print("Espera!")
   sleep(DELAY_WAIT)
   print("Para baixo!")
   led6.turn_on()
   sleep(DELAY_DOWN)
   led6.turn_off()

Para ligar o sensor à entrada #0 do Piface Digital cortei um cabo RCX a meio:

rcx-cableO diagrama abaixo ilustra a configuração final, no que diz respeito às ligações eléctricas:

pitagoras-e-a-esfinge

Raspberry Pi como alternativa LEGO WeDo

Para a primeira aplicação prática montei o Roaring Lion do conjunto LEGO WeDo (as instruções de montagem deste e outros modelos simples estão disponiveis no site LEGO Education).

raspberrypi-lego-roaring-lionO leão é muito simples: fazendo rodar o motor num sentido ele levanta-se nas patas dianteiras, no outro sentido volta a deitar-se (como não há sensor de posição é necessário afinar os tempos à mão)

lego-roaring-lionNuma primeira fase testei comandar o leão remotamente a partir de uma sessão SSH, criando para isso um script (lion.py) em python:

#!/usr/bin/python3

import sys
from time import sleep
import pifacedigitalio

DELAY_UP = 0.17       # o leão custa um pouco mais a subir
DELAY_DOWN = 0.14     # do que a descer

pifacedigital = pifacedigitalio.PiFaceDigital()
led7=pifacedigital.leds[7]
led6=pifacedigital.leds[6]
led7.turn_off()
led6.turn_off()

comando='.'

while(comando!="s"):
 comando=input("Comando: ")
 if (comando=="c"):
   print("Para cima!")
   led7.turn_on()
   sleep(DELAY_UP)
   led7.turn_off()
 elif (comando=="b"):
   print("Para baixo!")
   led6.turn_on()
   sleep(DELAY_DOWN)
   led6.turn_off()
 elif (comando=="s"):
   print("Tchau!")
 else:
   print("?") # comando desconhecido

É necessário dar permissões de execução ao script:

sudo chmod u+x lion.py

Para correr, basta invocar directamente o script:

./lion.py

Os comandos são simples:

  • c – para cima
  • b – para baixo
  • s – para sair

Funciona bem mas seria bem melhor se o leão estivesse sempre à espera de um comando e pudessemos usar o rato em vez do teclado, por exemplo a partir de um browser.

Para isso precisamos de um servidor (daemon) http – poderia ter ido para o apache mas preferi ir à procura de um servidor http mais leve e encontrei o Monkey (no passado tive boas experiências com o lighttpd e existe também o nginx):

Começamos por adicionar o repositório para usar a versão directamente mais recente em vez da que vem do mundo Debian:

sudo nano /etc/apt/sources.list

e adicionar a linha

deb http://packages.monkey-project.com/primates_pi primates_pi main

depois actualizar a cache:

sudo apt-get update

e instalar todos os componentes:

sudo apt-get install monkey          
                  monkey-liana       
                  monkey-logger      
                  monkey-dirlisting  
                  monkey-cgi         
                  monkey-fastcgi     
                  monkey-mandril     
                  monkey-cheetah     
                  monkey-auth

(embora só seja, mesmo necessários o monkey e os módulos liana e cgi )

Para testar basta aceder por browser na porta 2001:

http://192.168.1.123:2001/

(o conteúdo desta página está ficamente em /usr/share/monkey/)

Para poder invocar scripts de python a partir de páginas html é necessário recorrer a CGI (penso que seria possível fastcgi mas esta não é de todo a minha especialidade).

Criei uma pasta só para armazenar os scripts que vão ser acedidos por browser:

sudo mkdir /usr/share/monkey/cgi-bin

É necessário configurar o monkey para carregar o módulo CGI:

sudo nano /etc/monkey/plugins.load

basta descomentar a linha (mentendo os espaços em branco):

Load /usr/lib/monkey/monkey-cgi.so

além disso é necessário mudar a conta com que o monkey corre para poder utilizar as libraries do PiFace:

sudo nano /etc/monkey/monkey.conf

(basta mudar de www-data para root)
E finalmente reiniciar o monkey:

sudo service monkey restart

Para testar, colocar na pasta /usr/share/monkey/cgi-bin o ficheiro hello.cgi:

#!/usr/bin/python3
print("Content-Type: text/html")     # HTML is following
print()                              # blank line, end of headers
print("<TITLE>CGI script output</TITLE>")
print("<H1>This is my first CGI script</H1>")
print("Hello, world!")

(eventualmente dar-lhe permissões de execução – sudo chmod u+x)

E aceder por browser: http://192.168.1.123:2001/cgi-bin/hello.cgi

Confirmado o funcionamento, criar 2 scripts para controlo do leão:

E uma página que se limita a disponibilizar dois links para os dois scripts:

<html><head>
<title>Pitagoras</title>
</head><body>
<p><a href="cgi-bin/cima.cgi">Para cima!</a></p>
<p><a href="cgi-bin/baixo.cgi">Para baixo!</a></p>
</body></html>

E…

funciona!

É pena que o CGI obrigue a que cada vez que é dado um comando seja reinicializado o python e recarregados os módulos – cada comando demora por isso demora 2 ou 3 segundos. Os melhoramentos ficam para outra altura.

Raspberry Pi – headless + wireless

Objectivo: utilizar um Raspbery Pi sem teclado nem monitor nem cabo de rede em momento algum.

Nota: as instruções são para quem usa Ubuntu e deverão servir para a generalidade dos Linuxes mas não para Windows.

Download do Raspbian (neste momento a versão mais recente é a ‘2014-01-07-wheezy-raspbian.zip’) e extrair a imagem (‘2014-01-07-wheezy-raspbian.img’).

Inserir um SD card com pelo menos 4 GB e lançar a aplicação “Disks” (gnome-disks). Seleccionar o SD Card, no meu caso o SD Card é visto como “8 GB Block Device (/dev/mmcblk0)” e carregar em “More Options” (o botão no canto superior direito) e escolher  “Restore Disk Image…”

Escolher o ficheiro com a imagem Raspbian (2014-01-07-wheezy-raspbian.img) e esperar alguns minutos que a operação termine. Ficam 2 partições no SD Card:

  • BOOT
  • 2.9 GB Volume

A segunda partição será utilizada como “/” pelo Raspbian e tem uma estrutura semelhante à do Ubuntu (ambos são baseados em Debian).

Basta editar 3 ficheiros:

  • […]/etc/hostname
  • […]/etc/network/interfaces
  • […]/etc/wpa_supplicant/wpa_supplicant.conf
$sudo nano [...]/etc/hostname

A ideia é ter um nome distinto e reconhecível para podermos depois encontrar o nosso dispositivo no router wireless. Substituí o ‘raspberrypi’ que vem de origem por ‘pitagoras’.

$sudo nano [...]/etc/network/interfaces

Aqui bastou acrescentar uma linha (post-up…) para desactivar a ligação por cabo quando a ligação wi-fi estiver funcional:

auto lo
iface lo inet loopback

allow-hotplug eth0
iface eth0 inet dhcp

allow-hotplug wlan0
iface wlan0 inet manual
    wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
    post-up ifdown eth0
iface default inet dhcp

Assume-se IP dinâmico tanto para ligação por cabo como wireless mas pode-se determinar um endereço IP estático (não o fiz ainda por pura preguiça).

$sudo nano [...]/etc/wpa_supplicant/wpa_supplicant.conf

Neste ficheiro apenas estavam presentes as duas primerias linhas, o resto foi acrescentado.

ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1

network={
    ssid="ID da rede Wi-Fi"
    psk="Preshared Key da rede Wi-Fi"
    id_str="Descritivo opcional"
}

Com um Wi-Pi para a ligação wireless funcionou à primeira (não testei ainda outros dispositivos mas pelo menos o D-Link DWA-131 deverá funcionar, está a funcionar noutro projecto). Para saber o endereço IP bastou ir ao router ver os devices ligados:

00:0f:13:38:1e:38    192.168.1.123    0 dia 0 hora 01 minuto    pitagoras

Para aceder remotamente por ssh:

ssh pi@192.168.1.123

E pronto (no Raspbian a password de origem de ‘pi’ é ‘raspberry’)

pi@pitagoras ~ $

Controlo de motores Lego

Quero utilizar o Raspberry Pi para controlar directamente construções em Lego, um pouco à maneiro do Lego Education WeDo Robotics.

Encomenda à PTRobotics:

Já tinha:

  • Lego Power Functions Rechargeable Battery Box (8878) ou AA Battery Box (8881)
  • Lego Power Functions XL Motor (8882)
  • fio eléctrico
  • carregador com ficha micro-USB
  • SD Card 4 GB com Raspbian instalado e pré-configurado para wi-fi para evitar ter de usar um teclado e um monitor
  • 2 resistências entre 220 Ω e 2.2 KΩ (usei duas de 1 KΩ)

A montagem do PiFace é simples: encaixar o módulo sobre o Raspberry Pi, inserir o SD Card e o Wi-Pi e fornecer energia através do cabo micro-USB.

O PiFace faz uso da interface SPI pelo que é necessário activá-la:

$sudo raspi-config

Escolher no menu “8 Advanced Options” e depois “A5 SPI”, responder “yes” e finalmente “finish”. Não é necessário reboot.

É também necessário instalar o módulo python para o PiFace, que já faz parte do repositório do Raspbian:

$sudo apt-get install python3-pifacedigitalio

Para testar, basta correr o script que vem com o módulo:

$python3 /usr/share/doc/python3-pifacedigitalio/examples/blink.py

O LED #7 acende e apaga segundo a segundo, tudo OK podemos passar ao controlo do motor.

As saídas do PiFace são Open Collector pelo que é necessário um pull up (ligar aos +5 V através de um resistência) para obter algo compatível com as entradas da bridge.

A bridge é alimentada pela bateria Lego Power Functions (usei um cabo Power Functions cortado a meio, aproveitando apenas os 2 condutores exteriores – um para GND e o outro para PWR).

powerfunctions-hbridge-powerUtilizei um voltímetro para confirmar qual o positivo e qual o negativo – no caso do modelo 8878 da foto acima o selector de velocidade ficou rodado até ao extremo no sentido dos ponteiros do relógio; no modelo 8881 é necessário deslocar o selector no sentido da ficha.

O motor é ligado à H-bridge com a outra metade do cabo anterior, desta vez utilizando apenas os 2 condutores interiores.

O script blinky.py anterior serve para testar mas para controlo manual a partir da shell do python optei por usar estes comandos:

$python3
>>>import pifacedigitalio
>>>pifacedigital = pifacedigitalio.PiFaceDigital()
>>>led7=pifacedigital.leds[7]
>>>led6=pifacedigital.leds[6]
>>>led7.turn_off()
>>>led6.turn_off()

Para acender apenas o LED #7 e fazer o motor rodar num sentido:

>>>led7.turn_off()
>>>led6.turn_on()

Para acender apenas o LED #6 e fazer o motor rodar no sentido oposto:

>>>led7.turn_on()
>>>led6.turn_off()

Se acender ambos os LED o motor permanece parado:

>>>led7.turn_on()
>>>led6.turn_on(

E para sair da shell de python:

>>>exit()