The LEGO WeDO tilt sensor

I’ve made some reverse-engineering of the WeDO tilt sensor:

R1 = 3k9
R2 = 10k
R3 = 6k8
R4 = 1k2

The circuit is based on Philo photos of the WeDO internals, I just completed it with my own findings.

The value of R1 is critical – this resistor is connected between C1 and Ground (0V) and it is used to identify the tilt sensor – if possible use a 1% tolerance resistor.

The other 3 resistors are not so demanding because the driver of the tilt sensor accepts a range of values for each of the 4 possible states.

So we can make our own pseudo tilt sensors modifying a Power Functions cable. Since I had enough Mindstorms RCX touch sensors, why not use 4 to create a basic gamepad with 4 direction keys?

The RCX touch sensor has an internal resistor, near 600Ω when full pressed so we have to reduce R3 and R4 to near 6k2 and 0k6.

Here is a quick demo with an EV3 and 2 WeDo USB hubs. Each hub has a Power Functions L-motor in port A and one of the hubs has the 4-key gamepad. I didn’t have the right resistors so I had to use some combinations of serial and parallel, pretty ugly but it works.

How do I use two WeDo USB hubs? Since they are both seen as the same kind of device and they don’t seem to have an individual ID, I scan for all hubs (expect to find just 2) and test for the presence of a tilt sensor.

I don’t have more hubs to test but it seems that there is no limiti to the number of WeDo hubs we can use (the software from LEGO allows only 3), we just need some kind of initialization procedure (like at the beginning of our program we ask the user to connect a tilt sensor on hub #1, then hub #2 and so on until all hubs are identified – or make a motor spin a bit and ask for confirmation).

#!/usr/bin/env python

from wedo import *
from time import sleep


#check if there are two hubs

  # initialize both hubs

  #find which hub has a tilt sensor

  if (wedohub1.tilt<>None):

  # use the tilt sensor as a gamepad
  # 1 = LEFT
  # 2 = BACK
  # 3 = RIGHT
  # 4 = FRONT






  print "Number of WeDo USB hubs found was not 2"

LEGO WeDO with Linux

After almost 2 years of procrastination I finally offered myself a LEGO WeDO USB Hub:

I just love the WeDO idea: with just a small and somewhat simple interface (the USB Hub) anyone can use a PC (nowadays a ubiquitous appliance) to control a motor or read a sensor. Great for educational uses, specially with STEM (Science, Technology, Engineering and Mathematics).

Sadly the LEGO WeDO family got much less attention than his older and bigger related, LEGO Mindstorms (at least in my country, Portugal). Although a bit less expensive than an NXT or an EV3, it’s not cheap so the EV3 seems a better investment (more pieces, more diversity, more power).

Early this year I used a Raspberry Pi with a Piface Digital board as a clumsy but much more powerful DIY alternative to the WeDO. This was in fact the trigger to start using LEGO again, event registering myself in a LUG.

This week someone opened an issue with ev3dev asking for “Any chance of adding Lego WeDo hub + motor and sensors?“. Right after I suggested wedo (a python library for WeDO) Ralph Hempel announced he was working in linux kernel support for WeDO (not just for ev3dev, could be used with other systems… like my laptop). Wow!

So I got a pair of WeDO USB hubs and a tilt sensor. And while waiting for Ralph’s work, I’m using WeDo with a variant of the wedo library: WeDoMore.

This is what you need to get WeDoMore working with Linux (both Ubuntu 14.10 and ev3dev tested, no need to use sudo in ev3dev because I’m already root): first download it and extract it, then:

sudo apt-get install python-pip
sudo pip install pyusb
cd WeDoMore-master
sudo ./ install

With Ubuntu it was necessary to remove Ubuntu’s version of pyusb, much older than pypi version:

sudo apt-get remove pyusb

Now connect the WeDO USB Hub and check with ‘dmesg’ and ‘lsusb’.

On Ubuntu:

413.597110] usb 2-1.3: new low-speed USB device number 10 using ehci-pci
[  413.695628] usb 2-1.3: New USB device found, idVendor=0694, idProduct=0003
[  413.695639] usb 2-1.3: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  413.695644] usb 2-1.3: Product: LEGO USB Hub V1.00
[  413.700722] hid-generic 0003:0694:0003.0009: hiddev0,hidraw3: USB HID v1.10 Device [LEGO USB Hub V1.00] on usb-0000:00:1d.0-1.3/input0
Bus 002 Device 013: ID 0694:0003 Lego Group

On ev3dev:

[ 1263.539342] usb 1-1.2: new low-speed USB device number 4 using ohci
[ 1263.698363] hid-generic 0003:0694:0003.0001: device has no listeners, quitting
Bus 001 Device 004: ID 0694:0003 Lego Group

So Ubuntu has a better knowledge of the WeDO USB Hub than ev3dev, don’t know why.

Now let’s test it from the python shell:

~$ python
Python 2.7.8 (default, Oct 20 2014, 15:05:19)
[GCC 4.9.1] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> from wedo import WeDo
>>> wd = WeDo()
>>> wd.motor_a=100

If you have a motor connected to port A, it shell spin (note that as WeDO gets it power from USB the motor will get only 5V instead of ~9V as with Power Functions batteries… so it will spin slower).

To stop the motor and leave the shell:

>>> wd.motor_a=0
>>> exit()

As I also have a tilt sensor I made this simple control script:

#!/usr/bin/env python

from wedo import WeDo
from time import sleep

wd = WeDo()
print("Tilt me!")

IR remote control – speed and position

iConor’s second LIRC configuration file,Combo_PWM.conf, allows us to use LIRC command ‘irsend’ to control the speed of a LEGO Power Functions Motor or the position of a LEGO Power Functions Servo Motor much like the 8879 IR Speed Remote Control.

This shell script sends a sequence of 7 increasingly values then returns to zero and repeat it in the opposite direction:

irsend SEND_ONCE LEGO_Combo_PWM 400B ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 401A ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 4029 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 4038 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 404F ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 405E ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 406D ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 407C ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 4083 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40F4 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40E5 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40D6 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40C7 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40B0 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 40A1 ; sleep  1.2
irsend SEND_ONCE LEGO_Combo_PWM 4092 ; sleep  1.2

There is a total of 256 key codes in the configuration file (16 different values for the red plug x 16 different values for the blue plug). I used just the first subset of 16 so the first byte (for the blue plug) is always ’40’ but it doesn’t matter because I connected both Servo and M-motor to the red plug .

The sequence of key codes is not exactly the same as in the configuration file – I reordered the last 7 key codes.

The ‘sleep 1.2’  makes the script wait 1.2 seconds between each command. It is more or less the time the IR keeps the command active (bigger values would make the Servo return to center and the M-motor stop).

Infrared Remote Control

I discover this week that it is possible to use the headphone jack to send IR signals. The intructions are for a iPhone but one can use almost any audio source… even the computer audio card! And it is already suported in LIRC (Linux Infrared Remote Control), their page even includes a simple circuit!

LIRC – audio IR transmitter

Then I also found this lego-lirc repo in GitHub from a guy nicknamed iConor. It has the source code to generate LIRC configuration files for the LEGO Power Functions Infrared protocol… and also two configurations files:

The first file works like the 8885 – PF IR Remote Control and contains the usual FORWARD / BACKWARD / HOLD / BREAK codes; the second file works like the 8879 – PF IR Speed Remote Control and contains the codes to control the speed (duty cycle) of the motors.

So… why not give it a try?

I searched for more info about ‘lego-lirc’ but found nothing so I opened an issue asking iConor permission to publish those two files (and he promptly agreed, thank you iConor!).

My laptop has Ubuntu 14.10 x64. I installed LIRC and the required Portaudio library for using the audio card:

$ sudo apt-get install lirc libportaudio0

When LIRC is being installed it asks for an IR Receiver and an IR Transmitter, I chose ‘none’ twice.

Then I copied iConor configuration files to LIRC folder:

sudo cp Combo_Direct.conf /etc/lirc/lircd.conf
sudo cp Combo_PWM.conf  /etc/lirc/lircd.conf

and edited /etc/lirc/hardware.conf to create a LEGO_Combo_Direct transmitter associated to the audio card output:

#Chosen IR Transmitter

My audio card accepts sampling at 96 kHz but others may require lower values like 48 kHz.

I also edited /etc/lirc/lircd.conf to include both iConor configuration files

include "/etc/lirc/Combo_Direct.conf"
include "/etc/lirc/Combo_PWM.conf"

but I’m not sure if it is really needed since hardware.conf already has the right path.

I am also not sure if it is really needed or not but somewhere between my several tries I had to create a folder for lirc where it writes 2 files (one I think is a lock, the other contains just the process id)

~$ sudo mkdir /var/run/lirc/

Now let us start the lirc daemon:

~$ sudo service lirc start

and check if it is working:

~$ pgrep lirc

and what kind of transmitter does it understands:

~$ irsend LIST "" ""
irsend: LEGO_Combo_Direct
irsend: LEGO_Combo_PWM

and also  what codes are available:

$ irsend LIST LEGO_Combo_Direct ""
irsend: 000000000000010e FLOAT_FLOAT
irsend: 000000000000011f FLOAT_FORWARD
irsend: 000000000000012c FLOAT_BACKWARD
irsend: 000000000000013d FLOAT_BRAKE
irsend: 000000000000014a FORWARD_FLOAT
irsend: 000000000000015b FORWARD_FORWARD
irsend: 0000000000000168 FORWARD_BACKWARD
irsend: 0000000000000179 FORWARD_BRAKE
irsend: 0000000000000186 BACKWARD_FLOAT
irsend: 0000000000000197 BACKWARD_FORWARD
irsend: 00000000000001a4 BACKWARD_BACKWARD
irsend: 00000000000001b5 BACKWARD_BRAKE
irsend: 00000000000001c2 BRAKE_FLOAT
irsend: 00000000000001d3 BRAKE_FORWARD
irsend: 00000000000001e0 BRAKE_BACKWARD
irsend: 00000000000001f1 BRAKE_BRAKE

OK, we’re ready! Now suppose we want to make both motors spin forward:


Yeah! The motor(s) spin for about 1 second.

So if we want shorter runs we can send a BREAK or a FLOAT after a short time, say 0.1 second:

~$ irsend SEND_ONCE LEGO_Combo_Direct FORWARD_FORWARD; sleep 0.1; irsend SEND_ONCE LEGO_Combo_Direct FLOAT_FLOAT

I faced some strange behaviours (delays, lags) until I better read the LIRC audio page and saw this warning:

“It takes some time to set up (50 ms or so) so when no clients are connected to lircd the first transmission will have some higher latency.

A workaround for this is to keep irw running with a bash script like this:

 while [ true ]; do
 irw || true
 sleep 1


So i created a ‘’ file, gave it execution permissions and executed in the background:

~$ chmod +x
~$ ./ &

And it makes a REALLY BIG difference.

For anyone who might get interested in this, I suggest first trying with just a headphone or 2 common LEDs (I used a pair of red). If there is a click or a blink then use 2 IR LEDs. Mine are L-934F3C – IR Emitter 3mm 940nm (€0.25 each) and no resistor at all but if you want to play safe use a small resistor like 8Ω.

You also need a cable (just cut the cable of a old headphone set) and a soldering iron. I also used heat shrinking tube but any kind of insulation material is OK.

The required materials:

And the completed cable:

Now about the LEDs…

These LEDs are from Kingbright, their specs say

1.2V Typ @ 20mA, 940 nm, 50° angle, 10 mW/sr Typ @20 mA

I also tried a pair of TSAL6100 950nm High Power Infrared Led from Vishay:

1.35V Typ@ 100 mA, 10° angle, 170 mW/sr @100 mA

but I got more or less the same results and as their emission angle is much smaller I needed to point more carefully to the PF RC receiver. so I kept the first pair. The audio output is intended for headphone so it isn’t much powerfull and might not give enough current to notice a difference – or i just made a mistake.

My first tests achieved a respectable 3 meter range. Not bad for something so simple and costing less than €1 – now everyone can programmaticaly control their LEGO models. Kudos for LIRC people for being so open-minded and for iConor for creating this configuration files.

Next I’m going to try the same with a LEGO Mindstorms EV3 and also a Raspberry Pi.

SBrick remote control com Snap!

Um controlo remoto simples em Snap! usando as 4 teclas cursoras:

snap-SBrick2A device extension que criei implementa 3 motores: A (canal #1), B (canal #2) e um pseudo-motor P (ambos os canais). Para movimentar o rover para trás e para a frente é usado o motor P, para rodá-lo para a esquerda ou para a direita são usados os motores A e B com direcções opostas.

Depois de uma décima de segunda de rotação dos motores é dado um comando de rotação aos motores com duty cycle de zero (COAST) mas também podia ser usado o comando stop (BREAK).

Small iBeacons da myBeacon

Recebi finalmente os meus primeiros iBeacons, dois Small iBeacons da myBeacon (um preto e outro vermelho). A encomenda demorou 12 longos dias a chegar, a acreditar na data do carimbo Royal Post 10 deles foram passados nos serviços postais.

A encomenda chegou num envelope almofadado pequeno, sem remetente. Dentro apenas 2 saquinhos ziplock – nada de instruções ou sequer um papel com a ordem de encomenda!

Small iBeacon da myBeacon (vermelho)

Dentro de cada saco outros dois saquinhos, um adesivo redondo 3M e 3 peças pretas que formam a caixa do dispositivo; um dos sacos tem uma pilha CR2032, o outro a placa de circuito impresso do beacon propriamente dito.

mybeacon-small-02mybeacon-small-03Para montar é simples: insere-se a pilha CR2032 com a face “+” para cima e a face “-” virada para o circuito impresso. Como não existe qualquer interruptor, assim que inserimos a pilha o beacon liga-se e assim permanece até retirarmos a pilha ou ela se descarregar (é suposto durar entre 6 a 12 meses).

Das 3 peças que forma caixa só 2 são necessárias, permitindo montar:

  • – um cilindro
  • – um cilindro com aba furada para porta-chaves


(mostro o preto, foi o único que montei até agora)

O Small iBeacon é correctamente reconhecido embora como sendo um ibeacon da RF Proximity:

 Updated: ...
 RSSI: -79.0 db/-79.0 db
 UUID: ....
 Major: 0    Minor: 0
 TX Power: -58    Distance: 8.65m
 Descriptor: FAR

Mais uma vez a precisão deixa muito a desejar: não eram 8.65m mas 30cm!!! O que só prova:

  • a implementação do LEGO B3AC0N até está bastante boa;
  • a precisão da maioria das aplicações disponíveis no Google Play é uma desgraça!

Infelizmente a myBeacon apenas fornece software para iOS pelo que não sei ainda como configurá-lo (alterar os valores de Major e Minor, eventualmente também o UUID) mas para o que pretendo por agora serve perfeitamente.

A RF Proximity tem aplicações para Android, incluido uma para encontrarmos o carro quando nos esquecemos onde o estacionámos (assumindo que deixámos o iBeacon dentro do carro e tínhamos o telemóvel a segui-lo quando saímos do carro). Mas infelizmente também não parece ter nenhuma para configurar os seus beacons.

ev3dev – wireless gamepad

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

O gamepad utilizado no AD4M4ST0R é um “Gioteck VX-2 Wireless Controller” comprado na FNAC por €19.99. Qualquer modelo compatível com PC deverá funcionar, desde que use um dongle USB (os modelos por cabo USB também funcionarão mas não servem para o caso). Quando o stack bluetooth estiver funcional no ev3dev também deverão funcionar gamepads desse tipo

gamepadO gamepad é reconhecido automaticamente como um gamepad e como um disposito de classe OHCI:

root@ev3dev:~# dmesg
usb 1-1.4: new full-speed USB device number 4 using ohci
hid-generic 0003:25F0:83C2.0001: usb_submit_urb(ctrl) failed: -1
hid-generic 0003:25F0:83C2.0001: timeout initializing reports
input: Goodbetterbest Ltd Gioteck VX2 2.4G Wireless Controller as /devices/platform/ohci.0/usb1/1-1/1-1.4/1-1.4:1.0/0003:25F0:83C2.0001/input/input2
hid-generic 0003:25F0:83C2.0001: input: USB HID v1.10 Gamepad [Goodbetterbest Ltd Gioteck VX2 2.4G Wireless Controller] on usb-ohci.0-1.4/input0

Mas a implementação USB deixa um bocado a desejar:

root@ev3dev:~# lsusb
Bus 001 Device 004: ID 25f0:83c2

Bela porcaria, nem um descritivo? Vamos inspeccionar com mais detalhe:

root@ev3dev:~#  lsusb -d 25f0:83c2 -v

Bus 001 Device 004: ID 25f0:83c2  
Device Descriptor:
  bLength                18
  bDescriptorType         1
  bcdUSB               1.10
  bDeviceClass            0 (Defined at Interface level)
  bDeviceSubClass         0
  bDeviceProtocol         0
  bMaxPacketSize0        16
  idVendor           0x25f0
  idProduct          0x83c2
  bcdDevice            3.15
  iManufacturer           1 Goodbetterbest Ltd
  iProduct                2 Gioteck VX2 2.4G Wireless Controller
  iSerial                 0
  bNumConfigurations      1
  Configuration Descriptor:
    bLength                 9
    bDescriptorType         2
    wTotalLength           41
    bNumInterfaces          1
    bConfigurationValue     1
    iConfiguration          0
    bmAttributes         0x80
      (Bus Powered)
    MaxPower              500mA
    Interface Descriptor:
      bLength                 9
      bDescriptorType         4
      bInterfaceNumber        0
      bAlternateSetting       0
      bNumEndpoints           2
      bInterfaceClass         3 Human Interface Device
      bInterfaceSubClass      0 No Subclass
      bInterfaceProtocol      0 None
      iInterface              0
        HID Device Descriptor:
          bLength                 9
          bDescriptorType        33
          bcdHID               1.10
          bCountryCode            0 Not supported
          bNumDescriptors         1
          bDescriptorType        34 Report
          wDescriptorLength     137
         Report Descriptors:
           ** UNAVAILABLE **
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x01  EP 1 OUT
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0010  1x 16 bytes
        bInterval              10
      Endpoint Descriptor:
        bLength                 7
        bDescriptorType         5
        bEndpointAddress     0x82  EP 2 IN
        bmAttributes            3
          Transfer Type            Interrupt
          Synch Type               None
          Usage Type               Data
        wMaxPacketSize     0x0020  1x 32 bytes
        bInterval               1
Device Status:     0x0000
  (Bus Powered)

Sendo OHCI temos também:

root@ev3dev:~# ls /dev/input/by-id/ -la
total 0
drwxr-xr-x 2 root root  60 Aug 15 07:16 .
drwxr-xr-x 4 root root 140 Aug 15 07:16 ..
lrwxrwxrwx 1 root root   9 Aug 15 07:16 usb-Goodbetterbest_Ltd_Gioteck_VX2_2.4G_Wireless_Controller-event-joystick -> ../event2

No Ubuntu consigo ver o estado dos vários botões e joysticks do gamepad com o comando ‘jstest’ do pacote ‘joystick’ por isso:

root@ev3dev:~# apt-get install joystick
root@ev3dev:~# jstest --normal /dev/input/by-id/usb-Goodbetterbest_Ltd_Gioteck_VX2_2.4G_Wireless_Controller-event-joystick
Driver version is 0.8.0.
jstest is not fully compatible with your kernel. Unable to retrieve button map!
Joystick (Unknown) has 2 axes and 2 buttons.
Testing ... (interrupt to exit)

jstest: error reading: Invalid argument

“Not fully compatible with your kernel”… Oops!

Podemos sempre aceder directamente:

root@ev3dev:~# cat /dev/input/by-id/usb-Goodbetterbest_Ltd_Gioteck_VX2_2.4G_Wireless_Controller-event-joystick
�S�z    �S�z0�S�z�S��    �S��0�S��

carregar um botão apenas gerou esta sequência de caracteres estranha… pelo menos sabemos que funciona só falta entender o formato. Como sou preguiçoso fui buscar o PyGame, um módulo de python muito usado na comunidade Raspberry Pi que já faz isso – a semelhança do EV3 com o Raspberry Pi é tão impressionante que lhe podemos ir buscar ideias para quase tudo.

root@ev3dev:~# apt-get install python-pygame
root@ev3dev:~# nano
root@ev3dev:~# chmod +x
root@ev3dev:~# python

O script python ‘’:

import traceback, os

os.environ['SDL_VIDEODRIVER'] = 'dummy'

from pygame import joystick, event, display

def main():



    print 'Axes:', num_axes
    print 'Buttons:', num_buttons
    print 'Hats:', num_hats

    while True:

      for i in range(0, num_axes):
        print 'Axis %i: %6.3f' % (i, js.get_axis(i))

      for i in range(0, num_buttons):
        print 'Button %i: %r' % (i, js.get_button(i))

      for i in range(0, num_hats):
        print 'Hat %i: %s' % (i, js.get_hat(i))

  except (KeyboardInterrupt, SystemExit):
    print "Exiting..."
  except Exception:


if __name__ == "__main__":

À custa deste script fiquei a saber que o gamepad tem 4 axes (2 por cada joystick analógico), 13 buttons e 1 hat (o hat é o conjunto de 4 teclas direccionais à esquerda do gamepad) que quando accionados devolvem:

Para cada um dos 13 botões:

gatilho esquerdo = 6
botão sobre gatilho esquerdo = 4
gatilho direito = 7
botão sobre gatilho direito = 5
select = 8
start = 9
home = 12
triangulo = 0
circulo = 1
cruz = 2
quadrado = 3
botão do joystick esquerdo = 10
botão do joystick direito = 11

(o botão “Turbo’ ao centro do gamepad parece não funcionar)

Para cada um dos 4 botões do hat:

cima = (0,1)
direita = (1,0)
baixo = (0,-1)
esquerda = (-1,0)

Para o joystick da direita:

todo para cima: Eixo 3 = -1
todo para baixo: Eixo 3 = 1
todo para direita: Eixo 2 = 1
todo para esquerda: Eixo 2 = -1
=> (x,y) = (axis2,-axis3)

Para o joystick da esquerda:

todo para cima: Eixo 1 = -1
todo para baixo: Eixo 1 = 1
todo para direita: Eixo 0 = 1
todo para esquerda: Eixo 0 = -1
=> (x,y) = (axis0,-axis1)

O gamepad tem também um motor interno para vibração (force feedback?) mas que só funciona com Playstation 3. Curiosamente de vez em quando acontece-me poucos minutos depois de desligar o EV3 o gamepad desatar a vibrar.

Caixa de música LEGO – o software

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


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


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:


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@

(“pi” é o utilizador pré-configurado no Raspbian – a password é “raspberry”, convém alterar mais tarde com o comando “passwd” – e é 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]


[por completar]


[por completar]


Primeiras linhas de código

Com um Rover já em condições de andar, faltava o video de demonstração da praxe (o que está no artigo de abertura desta série).

Antes de me meter à aventura com o Snap! limitei-me a transferir para o Raspberry Pi um script muito básico em python que faz o Rover por 4 vezes andar um troço a direito seguido de uma curva à esquerda (idealmente voltando ao ponto de partida mas como não usei nenhum tipo de sensores a única forma de o conseguir foi afinando os tempos à mão) e no final uma rotação em torno de si mesmo várias vezes para a direita:

import nxt
import nxt
import nxt.locator
from nxt.sensor import *
from nxt.motor import *
from time import sleep

brick = nxt.locator.find_one_brick()
left = Motor(brick, PORT_B)
right = Motor(brick, PORT_C)
both = nxt.SynchronizedMotors(left, right, 0)
leftboth = nxt.SynchronizedMotors(left, right, 100)
rightboth = nxt.SynchronizedMotors(right, left, 100)

for n in range(0,4):

A execução do script foi comandada manualmente (essencialmente acedi de modo wireless a partir do meu portátil por SSH e invoquei o script a partir da shell).