Raspberry Pi: novo modelo

Depois das melhorias trazidas com o modelo B+ surge agora um nova revisão do modelo A, o Raspberry Pi A+:

Raspberry Pi A+
  • menos 21 mm de comprimento
  • menor consumo (55% do B+)
  • microSD
  • mais portas GPIO
  • mehor audio
  • menos $5

Para aplicações vocacionadas para o «embedded» que se contentem com 256 MB de RAM, não precisem de rede este modelo torna-se muito apelativo.

Relés USB

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

 

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

Montagem do Rover

Para montar o Rover resta agora:

  • ligar os blocos maiores entre si (o conjunto bateria + Raspberry PI e o Mindstorms NXT) tendo o cuidado de não dificultar a troca de pilhas do NXT nem o acesso aos vários botões e fichas do conjunto:

IMG_2531-2IMG_2535-2IMG_2537-2IMG_2539-2IMG_2540-2IMG_2543-2IMG_2544-2IMG_2546-2

  • depois ligar os dois motores e as três rodas (uma roda por motor e uma terceira roda livre que serve apenas para sustentar o Rover e facilitar as curvas à esquerda ou à direita):

IMG_2547-2

  • e finalmente os cabos, o cartão SD e o adaptador WiFi USB:

IMG_2558-2IMG_2559-2

Esta foi a primeira versão, serviu para o primeiro video de demonstração mas o comportamento deixava muito a desejar (sobretudo devido ao centro de gravidade muito alto e à roda livre instável. Mais à frente mostrarei versões melhoradas, inclusive com sensores (um Rover para poder ser um robot autónomo precisa de algum tipo de sensor para entender o mundo à sua volta).

Legoficação de um Raspberry Pi

Material necessário (aconselho consultar a wiki RPi VerifiedPeripherals):

  • 1 Raspberry Pi (à venda na PTRobotics e na Portugal-Didáctico)
  • 1 Cartão SD 4GB (à venda em todo o lado)
  • 1 bateria com ficha USB (PNY PowerPack 5200mAh, à venda na FNAC)
  • 1 cabo USB-MicroUSB (vem com a bateria)
  • 1 adaptador WiFi USB, preferencialmente mini (D-Link DWA-131 à venda na FNAC)
  • 1 cabo USB A-B o mais curto possível (arranjei um cabo «prolongador» USB extremamente curto numa loja chinesa e juntei um adaptador A-B mas há cabos à venda no eBay)

Poderá ser conveniente, mas não indispensável:

  • 1 hub USB 2.0* (à venda na Worten)
  • 1 teclado USB (à venda em todo o lado, na Mediamarkt há uns muito pequenos)
  • 1 rato USB (à venda em todo o lado)
  • 1 monitor/TV com ligação HDMI ou DVI (neste caso é também necessário um adaptador HDMI-DVI)
  • 1 caixa para Raspberry Pi

* infelizmente nem todos servem, há alguns como o Targus ACH114EV que não seguem devidamente as normas e apesar de funcionarem num PC normal não funcionam no Raspberry Pi. Os modelos KUNFT H-088 e Mitsai H-092 funcionam (este último tem inclusive uma ficha para alimentação externa que poderá dar jeito se quisermos ligar dispositivos USB que consumam mais corrente do que o Raspberry Pi consegue fornecer)

É necessário ligar as duas peças mais volumosas (o Raspberry Pi e a bateria) às restantes peças Lego de um modo prático mas sólido. Optei por colar duas vigas Technic a cada uma de modo a poder tratá-las como se fossem blocos Lego normais.

Raspberry Pi + Bateria USB
Raspberry Pi + Bateria USB antes de serem legoficados

Usei uma cola de contacto própria para plásticos ABS tendo apenas o cuidado adicional de espaçar as vigas a colar com outras peças lego de modo a assegurar que a distância entre as duas respeita os padrões Lego.

Para a bateria usei duas vigas 1×9 (40490):

IMG_2519-2 IMG_2520-2

Para o Raspberry Pi (com caixa) usei duas vigas 1×11 (32525):

IMG_2521-2 IMG_2512-2

Como o espaço entre as vigas da bateria é duas unidades inferior ao espaço entre as vigas do Raspberry Pi podemos ligar os dois num só módulo:

IMG_2527-2