LEGO WeDO – Temperature Sensor

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:

Or we can just use an old LEGO Mindstorms (RCX) Temperature Sensor 🙂

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 :

RAW Temp (°C)
159 20
158 20
165 36.5
157 19.8
157 19.5
157 19.6
156 18.8
157 19
156 18.9

LEGO WeDO with EV3 – kernel support

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:

nano /etc/udev/rules.d/80-wedo.rules

SUBSYSTEM=="usb", ATTRS{idVendor}=="0694", ATTRS{idProduct}=="0003" ACTION=="add", \
    RUN+="/bin/sh -c 'echo $kernel > /sys/bus/usb/drivers/usbhid/unbind;           \
                      echo $kernel > /sys/bus/usb/drivers/legowedo/bind'"

Now just reboot or refresh the udev rules by

udevadm control --reload-rules

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:

root@ev3dev:~# cat /sys/bus/wedo/devices/hub0/high_power 
1

or check for the USB power quality (in mV):

root@ev3dev:~# cat /sys/bus/wedo/devices/hub0/voltage 
5145

Now if we plug a LEGO Power Functions motor to one of the ports it will immediately be recognized by the kernel:

[ 1736.348469] dc-motor motor0: Bound to device 'port0'

and the motor is seen by the kernel as dc-motor like if we were using an NXT/EV3 to Power Functions or RCX adapter:

root@ev3dev:~# ls /sys/class/dc-motor -la
lrwxrwxrwx  1 root root 0 Nov 25 06:30 motor0 -> ../../devices/platform/ohci.0/usb1/1-1/1-1.2/1-1.2:1.0/hub0/port0/dc-motor/motor0
root@ev3dev:~# ls /sys/class/dc-motor/motor0
command   device      duty_cycle_sp  polarity   power         ramp_up_ms  uevent
commands  duty_cycle  name           port_name  ramp_down_ms  subsystem

So we can make it spin with 35% duty cycle:

echo 35 > /sys/class/dc-motor/motor0/duty_cycle_sp

And it’s the same for WeDo sensors – as I just have a tilt sensor, lets plug it:

root@ev3dev:~# ls /sys/class/msensor/ -la
lrwxrwxrwx  1 root root 0 Nov 25 06:40 sensor0 -> ../../devices/platform/ohci.0/usb1/1-1/1-1.2/1-1.2:1.0/hub0/port1/msensor/sensor0
root@ev3dev:~# ls /sys/class/msensor/sensor0
address   bin_data_format  commands  dp    modes  num_values  power      uevent  value0  value2  value4  value6
bin_data  command          device    mode  name   port_name   subsystem  units   value1  value3  value5  value7

The tilt sensor driver has 3 operation modes:

root@ev3dev:~# cat /sys/class/msensor/sensor0/modes
TILT TILT-AXIS RAW

by default it operates in TILT mode:

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

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

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"

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 ./setup.py 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!")
while(True):
 if(wd.tilt==2): 
   wd.motor_a=35
 elif(wd.tilt==3):
   wd.motor_a=-35
 else:
   wd.motor_a=0