LEGO Education released the WeDO 2.0 some months ago and I bought a kit. I returned to LEGO thanks to WeDO 1.0 and since I’m already using BLE with the SBrick, using the WeDo 2.0 seemed natural.
But LEGO Education made the Android app very restrictive and only a few Android devices are allowed to install it – I have two different BLE enabled Android phones and none complies with LEGO Education definitions. Although LEGO Education promised a SDK for the new WeDO 2.0, there’s still nothing available and since I don’t own a Windows computer or an Apple device, my WeDO 2.0 kit was rusting on the shelf, waiting for better days.
Then yesterday I found a Microsoft guy’ with some bluetooth code samples with references for the WeDO 2.0 – how ironic!
So it took me only a few hours to achieve what I think is a world premiere: a linux system controlling a LEGO WeDO 2.0 motor. And what better linux system than a LEGO Mindstorms EV3?
I never played with IR before but got curious. I love the idea of remote controlling something. But not manually, it has to be programmatically so one can use it for automation or robotic purposes. So after some weeks I found the LIRC definitions for LEGO Power Functions IR and used it to remote control LEGO from my laptop via the audio output.
Then it was the anniversary of one the kids and he asked granny for a major upgrade of their DUPLO train track:
So I thought it would be great if they could control the train back and forth… and ordered a used DUPLO Train Locomotive Base (5135c01)from BrickLink.
Opening it was difficult but I managed to do it without breaking anything, thanks to these two previous brave pioneers:
(their locomotives are from a different set but the idea is the same)
The locomotive has a pair of free wheels at front and another pair drived by a motor and some gears at back where there is also a piezo buzzer, a printed circuit board and a pair of wires comming from the batteries holder. There are also two rubber buttons that press some small metal rings against the surface of the PCB to act as switches – the smaller one, hidden in a small hole, makes the sound of fuel being pumped into the tank when the fuel hose is inserted, the bigger one controls starts/stops the train but also indirectly controls the sound of the locomotive (when in movement) and the sound of the breaks (when stopping).
The PCB has 6 wires soldered at points labeled J1 to J6:
J1 and J3 – buzzer
J2 and J4 – batteries
J5 and J6 – motor
As the batteries holder is for just 3 AA batteries, the board works with 4.5V. Not much but enough for a LEGO Power Functions IR receiver or a Vengit SBrick.
We could just dessolder the wires at J2/J4 (power) and J5/J6 (motor), get a LEGO Power Functions cable, cut it in half and solder the tips from one half to J2/J4 and the tips from the other half to J5/J6. But that will make the buzzer useless.
As the buzzer is controlled by an IC on the PCB, I choose to keep the power lines going to the PCB (J2/J4) and deriving from there to the Power Functions cable (but still dessoldering J5/J6). This way, when the batteries are inserted, both the remote and the PCB are ON so the two buttons maintain their functionality. This gives us as an unexpected possibility: we can also use the PF cable to power the train instead of using 3 AA batteries – with special caution because LEGO PF batteries or LEGO 9V batteries give more than 4.5V so some reduction has to be done, like adding some 1N4001 diodes or a voltage regulator… but a USB 5.0V battery pack will be perfect.
Since I didn’t want to drill or cut the plastic, I managed to pass the PF cables through the start/stop button hole (before soldering it) but later found out that it was to tight for the rubber button – so no more «tchoo-tchoo!» nor breaks (some may consider this a feature, not a bug).
Yes, the Raspberry Pi can talk to the SBrick. It’s only necessary to install Bluez 5.
But as the standard Raspbian is based on Debian Wheezy, if you install bluez from the repositories
sudo apt-get install bluez
you will get Bluez 4 (today, 1 December 2014, it’s version 4.99). I can make a Low Energy Scan (lescan) and find the SBrick but my gatttool commands fail with
update Raspbian to Debian Jessiea as it already includes Bluez 5
I’m lazy, I don’t like to compile anything. I’m also afraid that any update might brake compatibility and forces me to recompile again. And my laptop (Unbuntu) and my EV3 (ev3dev) are already running a version of Jessie so let’s update.
Warning: Raspbian update from Wheezy to Jessie takes almost a day – so compiling Bluez might appeal to those in a hurry.
We need enough free space on the SD card. I used a 4 GB card and my first try failed miserable after a long night. So the second time I removed some things to assure an happy end.
First I transfered the most recent image available (2014-09-09) to the 4 GB card and edited networking to get wi-fi (I only use SSH with the Raspberry, like I do with the LEGO Mindstorms EV3).
After first boot with the fresh card run rasp-config to expand the file system with all free space available.
sudo rasp-config
after next boot remove some heavy things and clean:
As the WeDo USB Hub uses some kind of ADC (Analog to Digital Converter) to read the tilt sensor values, we can use this ADC for our own analog sensors.
So let’s start with a Temperature Sensor.
The most simple/easy temperature sensor is just a NTC thermistor: every regular resistor has some minor variations when the operating temperature changes and a thermistor is just a resistor designed to have a significant and well-known variation. A NTC (negative temperature coefficient) thermistor has a decrease in it’s value proportional to the temperature increase.
We can buy a cheap (less than €1) 10 kΩ NTC thermistor and use it as a temperature sensor knowing that at 25°C (average ambient temperature) it has a 10 kΩ value – we also need to know its temperature coefficient from the manufacturer datasheet or from our own calibration tests. Just solder two wires and provide some insulation and we’re done:
To use this sensor we can make our own cable with just one 3.9 kΩ resistor between C1 and 0 to makes the WeDo think we have a tilt sensor connected to it. Then we connect our sensor between C2 and 0 or between C2 and 9V.
Our we can piggyback a real tilt sensor with a modded cable and just connect our sensor to it:
In this scenario we must assure that the tilt sensor always stays flat so it doesn’t get in our way when we’re reading the temperature sensor and since the tilt sensor already has a 10 kΩ resistor between C2 and 0 I prefer to connect the sensor between C2 an 9V.
Early first readings, room temperature compared to the readings from a SensorTag :
Last night the ev3dev people released a Linux driver for WeDo. For now it is just for ev3dev so it works only in Mindstorms EV3 but hopefully it will get to other distributions and it will allow anyone with a Raspberry Pi or an Ubuntu laptop (like me) to use WeDo without python WeDo or WeDoMore libraries – just a shell is enough!
We need a ev3dev with kernel 3.16.1-7 or above:
root@ev3dev:~# uname -a
Linux ev3dev 3.16.1-7-ev3dev #2 PREEMPT Tue Nov 25 11:24:38 CST 2014 armv5tejl GNU/Linux
If your kernel is older, just
apt-get update
apt-get dist-upgrade
reboot
After reboot, creat a udev rule for WeDo – it will prevent the kernel to bind it to the usbhid driver, binding it instead to legowedo driver:
If you plug the LEGO WeDo USB Hub and check dmesg it wil show
[ 1222.200538] usb 1-1.2: new low-speed USB device number 5 using ohci
[ 1222.370828] hid-generic 0003:0694:0003.0002: hidraw0: USB HID v1.10 Device [LEGO USB Hub V1.00] on usb-ohci.0-1.2/input0
[ 1222.691293] wedo hub0: Bound 'hub0' to 'usb1-1.2:1.0'
We now have a new device ‘hub0’:
root@ev3dev:~# ls /sys/bus/wedo/devices/ -la
lrwxrwxrwx 1 root root 0 Nov 25 06:21 hub0 -> ../../../devices/platform/ohci.0/usb1/1-1/1-1.2/1-1.2:1.0/hub0
with the following properties:
root@ev3dev:~# ls /sys/bus/wedo/devices/hub0
clear_error error high_power port0 port1 power reset shut_down subsystem uevent voltage
So we may check if the USB port gives enough current for a motor:
This is the expected operation mode with LEGO WeDo software: it returns 0 when flat and 1 to 4 when tilted.
TILT-AXIS mode returns 3 values: -1 or +1 when tilted, one value for each axle, the third value being 1 whenever it’s not flat.
And RAW mode returns the original analogic value read at the C2 pin. Almost useless for a tilt sensor but VERY usefull if we want to make our own sensors (more of it in my next post):
root@ev3dev:~# echo RAW > /sys/class/msensor/sensor0/mode
root@ev3dev:~# cat /sys/class/msensor/sensor0/value0
179
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
listofdevices=scan_for_devices()
#check if there are two hubs
if(len(listofdevices)==2):
# initialize both hubs
wedohub1=WeDo(listofdevices[0])
wedohub2=WeDo(listofdevices[1])
#find which hub has a tilt sensor
if (wedohub1.tilt<>None):
usehub1=True
else:
usehub1=False
# use the tilt sensor as a gamepad
# 1 = LEFT
# 2 = BACK
# 3 = RIGHT
# 4 = FRONT
while(True):
wedohub1.motor_a=0
wedohub2.motor_a=0
if(usehub1):
command=wedohub1.tilt
else:
command=wedohub2.tilt
if(command==1):
#LEFT
wedohub1.motor_a=100
wedohub2.motor_a=100
elif(command==2):
#BACK
wedohub1.motor_a=-100
wedohub2.motor_a=100
elif(command==3):
#RIGHT
wedohub1.motor_a=-100
wedohub2.motor_a=-100
elif(command==4):
#FRONT
wedohub1.motor_a=100
wedohub2.motor_a=-100
sleep(0.25)
else:
print "Number of WeDo USB hubs found was not 2"
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:
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!")
while(True):
if(wd.tilt==2):
wd.motor_a=35
elif(wd.tilt==3):
wd.motor_a=-35
else:
wd.motor_a=0
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:
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).
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!
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:
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
1234
and what kind of transmitter does it understands:
~$ irsend LIST "" ""
irsend: LEGO_Combo_Direct
irsend: LEGO_Combo_PWM
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.