20 years ago, when I first heard about linux, it didn’t attract me much… spending lots ot time compiling the kernel or the drivers on a 486 seemed so crazy, I wasn’t geeky enough for that. Catched the linux train many years later with Ubuntu 6.04 or 6.10 when almost everything “just worked” and a few google searchs were enough when something didn’t work as expected.
And this week I found myself compiling libftdi and LIRC on a LEGO Mindstorms EV3! Gosh… what happened to me?
[end of crazy intro, start of long and probably boring intro]
Two years ago I found a way to use the soundcard of my laptop as a remote controller for my LEGO motors, thanks to LIRC. It worked OK and it even worked with my Android 4.x phone but never worked properly with ev3dev (and, some months later, I found that it also didn’t worked with my Android 5.x phone) and like most everything else I never really gave him a good use.
Last week someone asked at eurobricks forum how to use a HiTech IR controller with EV3. I also found a way to use it with ev3dev (picking up other people work) and once again never really giving it a good use. Hey, but somebody in the forum said it had tried my code! Thats amazing!
So I returned to LIRC and soundcard, decided to update my own howto. LIRC had evolved a bit in last two years and while reading some docs I found that LIRC also supports FTDI adapters. In fact, its extremely easy to make a USB IR emmiter with just a FTDI adapter and an IR LED, not even a resistor is needed!
I already had a few FTDI cables and adapters but they all use the FT232R model and for reliable timings a FT230X is needed. But my “local” supplier had a Sparkfun Beefy 3 that used FT231X, it’s not the FT230X but it seemed similar enough so I gave it a try… and it works!
[end of long boring intro]
So we need a recent version of LIRC that implements ftdix driver. Ubuntu and Debian jessie (so ev3dev also) only have 0.9.0… We need to download the source code directly from LIRC and compile ourselves. I downloaded the last version available, 0.9.4d.
For LIRC to compile the ftdix driver we also need libftdi. Ubuntu and Debian have it but I also compiled it from source – not sure why but at least for ev3dev just installing Debian libftdi packages is not enough and it seems that just compilling libftdi is also not enough, I had to do both.
My EV3 is running ev3dev snaphot 2017-02-06. Two days later there’s already a new snaphot but I only updated with apt:
This takes about an hour, lots of packages (mostly related to libboost)
Before spending lots of time compiling it is better to test if out FTDI adapter works as expected so we can download this “hello ftdi” example:
I saved it as “hello-ftdi.c”.
Now we insert our FTDI adapter and look for it at the end of dmesg:
[47800.964059] usb 1-1.2: new full-speed USB device number 8 using ohci
[47801.111337] usb 1-1.2: New USB device found, idVendor=0403, idProduct=6015
[47801.111424] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[47801.111472] usb 1-1.2: Product: FT231X USB UART
[47801.111515] usb 1-1.2: Manufacturer: FTDI
[47801.111553] usb 1-1.2: SerialNumber: DN01DR29
[47801.306754] usbcore: registered new interface driver usbserial
[47801.414060] usbcore: registered new interface driver ftdi_sio
[47801.423075] usbserial: USB Serial support registered for FTDI USB Serial Device
[47801.437994] ftdi_sio 1-1.2:1.0: FTDI USB Serial Device converter detected
[47801.449290] usb 1-1.2: Detected FT-X
[47801.454135] usb 1-1.2: FTDI USB Serial Device converter now attached to ttyUSB0
We see that it is detected and we take note of the idVendor and idProduct values:
idVendor=0403, idProduct=6015
For later use we also take note of its Serial Number:
DN01DR29
Now we edit the “hello-ftdi.c” program and update the idVendor and idProduct.
/* hello-ftdi.c: flash LED connected between CTS and GND.
This example uses the libftdi API.
Minimal error checking; written for brevity, not durability. */
#include <stdio.h>
#include <ftdi.h>
#define LED 0x08 /* CTS (brown wire on FTDI cable) */
int main()
{
unsigned char c = 0;
struct ftdi_context ftdic;
/* Initialize context for subsequent function calls */
ftdi_init(&ftdic);
/* Open FTDI device based on FT232R vendor & product IDs */
if(ftdi_usb_open(&ftdic, 0x0403, 0x6015) < 0) {
puts("Can't open device");
return 1;
}
/* Enable bitbang mode with a single output line */
ftdi_enable_bitbang(&ftdic, LED);
/* Endless loop: invert LED state, write output, pause 1 second */
for(;;) {
c ^= LED;
ftdi_write_data(&ftdic, &c, 1);
sleep(1);
}
}
Then we compile our “hello-ftdi” test program:
gcc hello-ftdi.c -lftdi -o hello-ftdi
hello-ftdi.c: In function 'main':
hello-ftdi.c:25:5: warning: 'ftdi_enable_bitbang' is deprecated (declared at /usr/include/ftdi.h:413) [-Wdeprecated-declarations]
ftdi_enable_bitbang(&ftdic, LED);
We can ignore that warning, as long as we get a “hello-ftdi” binary file.
To run it we need root permissions:
sudo ./hello-ftdi
If we connect a common led between CTS (A) and GND (K) we will see it blink each second so we can replace it with a infrared LED (940 nm is better but 950 nm will also work). And yes, we don’t need to use a resistor.
If we check dmesg again, we notice that our test program disconnected the ttyUSB device, as required:
[15564.602213] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[15564.602615] ftdi_sio 1-1.2:1.0: device disconnected
This post was to long for my web server so I broke in several.
#!/usr/bin/python3
# EV3 03m58s - video: https://youtu.be/w5aKqmXz_Wk
# based on a python script from Lennart Poettering
# found here http://0pointer.de/blog/projects/mandelbrot.html
from PIL import Image, ImageDraw
import math, colorsys
import ev3dev.ev3 as ev3
from time import sleep
lcd = ev3.Screen()
lcd.clear()
sleep(1)
dimensions = (178, 128)
scale = 1.0/(dimensions[0]/3)
center = (2.0,1.0)
iterate_max = 15
colors_max = 2
img = Image.new("1", dimensions,"white")
d = ImageDraw.Draw(img)
# Calculate the mandelbrot sequence for the point c with start value z
def iterate_mandelbrot(c, z = 0):
for n in range(iterate_max + 1):
z = z*z +c
if abs(z) > 2:
return n
return None
# Draw our image
for y in range(dimensions[1]):
for x in range(dimensions[0]):
c = complex(x * scale - center[0], y * scale - center[1])
n = iterate_mandelbrot(c)
if n is None:
v = 1
else:
v = n/100.0
if v > 0.5 :
d.point((x,y), fill = 0)
else:
d.point((x,y), fill = 1)
lcd.image.paste(img, (0,0))
lcd.update()
del d
img.save("result.png")
sleep(1)
My EV3 is running ev3dev-jessie-2016-12-21 release. No need to install PIL or anything else, just create the script, give execution permissions and run it.
The script takes 3m58s to run. next video shows the result (4x speed):
After yesterday post I received two precious hints from Laurens Valk and David Lechner that finally allowed me to upgrade the firmware of my EV3.
When changing to firmware upgrade mode, the EV3 changes its USB device ID (that’s why it appears as disconnected in the EV3 tool). So we just need to add a new USB filter rule in the VM settings:
0694:0006 "LEGO EV3 Firmware Update"
The original filter, for normal operating mode, is
0694:0005 "LEGO Group EV3"
And of course I made a video showing how to do it:
Yesterday Marc-André Bazergui incentivized me to make a video showing how to use LEGO MINDSTORMS EV3 Software inside a virtual machine. It is a shame that a product running Linux inside can only be used on PC or Mac – and that’s one of the reasons I started using ev3dev as I only have linux systems (laptops, Raspberry Pi’s, old DIY desktops without a Windows license…).
I got my first EV3 exactly 3 years ago as a birthday gift from my wife. I don’t remember if I ever installed the Windows software on a VM before – I did installed one or twice in Ubuntu with Wine (not sure why) and I did installed a Microsoft Robotics Developer Studio in a VMware Workstation virtual machine and do remember having connected it to the the EV3 thorough a bluetooth USB dongle (most modern hypervisors have this nice feature to allow a local device on the host to be passed-through into the guest).
I no longer have VMware Workstation but I have used Innotek VirtualBox in the past and knew that Oracle somehow managed to keep it alive after buying it (Oracle has the morbid habit of poisoning every good thing it owns – Java, Solaris, OpenOffice, MySQL…).
So I installed Oracle VM VirtualBox 5.1.4 (there is even a x64 .deb package for Ubuntu 16.04 “Xenial”) and after that the VirtualBox 5.1.4 Oracle VM VirtualBox Extension Pack.
It was quite easy and also very fast. After that I got a licensed version of Microsoft Windows 8 Professional (x64 also) – this is my work laptop so people immediatlely started making fun of me – hey, he is installing Windows on his laptop, finally!
The rest of the process was also quite easy after all – like I thought, it is possible to use a Bluetooth USB dongle and also just the direct USB cable connection:
create a Virtual Machine
make sure “Enable USB Controller” is checked and USB 2.0 (EHCI) Controller is selected – it might also work with USB 3.0
add an USB Device Filter for each USB device you want to passthrough into the VM (the EV3 itself and/or the Bluetooth dongle)
install Windows
present VirtualBox Guest Additions CD Image and install
define a Shared Folder so you can pass drivers and binaries into the VM
if the Bluetooth dongle is not automatic configured, install the proper drivers
pair the EV3 (or plug the USB cable)
install LEGO Mindstorms EV3 software and run it
I made a video showing every step (just skipped the LEGO Software as it’s pretty straightfoward):
Just one note: although USB cable connection seems to work fine, i tried to upgrade my EV3 firmware several times with no success – every single time it hangs at 0%. Perhaps it behaves better with another Windows version… who knows?
I got a request for help today, Mr. Rocha is trying to use MIT App Inventor to control the WeDo 2.0 Smart Hub RGB LED.
I’ve never used App Inventor before but I had already installed the Companion once in my Android Phone because I read something somewhere and found it quite similar to Snap! and Scratch (and also just because it is from MIT… I have a fetiche for MIT back from when I was at college and read Nicholas Negroponte articles on Wired). So let’s give it a try.
I just wanted to connect to the WeDo 2.0 Smart Hub and change the color to RED. When using gatttool that’s done with just
char-write-cmd 3d 06040109
Just needed to add the BLE extension to start working, getting a connection was easy but writing to the handle took a while since App Inventor BLE extension doesn’t use handles, just UUIDs. So I had to go back to my notes and find the Service UUID and the Characteristic UUID:
Then I tried a block called “call BluetoothLE. WriteStringValue” but I couldn’t find a way to convert an hexadecimal string (“06040109”) to a proper string to send.
So I tried another block, “call BluetoothLE.WriteIntValue”. At first I made an old mistake, converting “06040109h” to “100925705”. Didn’t work.
Then I wrote it in reverse (“09010406h”) and converted it to “151061510”. And now it works!
Now that I finally started, I think I will use App Inventor some more times. Damn easy to create an BLE Android app!
About 10 years ago I offered my wife a M-Audio USB MIDI Keyboard and installed Ubuntu Studio on a computer so she could play some piano at home. She was so amazed with the possibility to generate music sheet while playing that almost accepted the idea of using Linux… almost 🙂
I remember that at that time I used timidity++ as a software MIDI synthesizer, tuned ALSA (one of the several Linux sound systems, perhaps the most generally used) and the preemptive kernel to work almost flawlessly with the Creative Labs sound card. My wife didn’t enjoy the KDE experience, Firefox was OK for her but OpenOffice were terribly with the spreadsheets she used and finally, when our first kid was born, she attended some English lessons at Wall Street Institute and we found out that the online lessons required an odd combination of an old version on Java, ActiveX and IE… so she returned to Windows XP and never looked back.
10 years is a LOT of time in computer systems but ALSA is still around, even on ev3dev. So I installed timidity++ and tried to play a MIDI file… to find that an ALSA module that is not currently available in ev3dev kernel is required just for MIDI.
I googled for alternatives and found fluidsynth with an unexpected bonus: there is a quite interesting python library, mingus, that works with fluidsynth. So I installed it in my Ubuntu laptop and in a few minutes I was playing harp – amazing!
In the previous example I just import the fluidsynth and Note parts of the library, initialize fluidsynth to work with ALSA loading the soundfount that cames with it, choose harp (instrument number 46) and play C3.
Well and polyphony? The correct way is to use a NoteContainer
from mingus.containers import NoteContainer
fluidsynth.play_NoteContainer(NoteContainer(["B-3", "C-3", "F-3"]))
but the lazy way is… just play several notes in a fast sequence.
So, let’s do it in the ev3dev!
Oops, fluidsynth also needs an ALSA module not available in current ev3dev kernel.
I’m not a linux music expert. Not even a linux expert! So after some more googling I gave up and asked for help in ev3dev’ GitHub project. And once again David accepted to include ALSA MIDI suport in future kernels, so I’ll just wait a bit.
Oh, but I can’t wait…
And if I read the color sensors in ev3dev and play the music in my laptop?
ALSA, once again, suports something like client/server MIDI communication with “aseqnet” and “aconnect” commands and some people are already using it with Raspberry Pi!
Yeah, I should have guessed… “aconnect” requires an ALSA MIDI module that is not available in current ev3dev kernel.
OK, let’s use MQTT: configure my EV3 as a publisher and my Ubuntu laptop as a subscriber and just send some notes as messages.
#!/usr/bin/env python
from ev3dev.auto import *
from time import sleep
import paho.mqtt.client as mqtt
DELAY = 0.01
# should have an auto-calibrate function
AMB_THRESHOLD = 9
sensor1 = ColorSensor('in1:i2c80:mux1')
sensor1.mode = 'COL-AMBIENT'
sensor2 = ColorSensor('in1:i2c81:mux2')
sensor2.mode = 'COL-AMBIENT'
sensor3 = ColorSensor('in1:i2c82:mux3')
sensor3.mode = 'COL-AMBIENT'
sensor4 = ColorSensor('in2')
sensor4.mode = 'COL-AMBIENT'
sensor5 = ColorSensor('in3')
sensor5.mode = 'COL-AMBIENT'
sensor6 = ColorSensor('in4')
sensor6.mode = 'COL-AMBIENT'
# there is no sensor7 yet, I need another MUX
s1 = 0
s2 = 0
s3 = 0
s4 = 0
s5 = 0
s6 = 0
s7 = 0
client = mqtt.Client()
client.connect("localhost",1883,60)
print 'Running...'
while True:
key_touched = False
s1 = sensor1.value(0)
s2 = sensor2.value(0)
s3 = sensor3.value(0)
s4 = sensor4.value(0)
s5 = sensor5.value(0)
s6 = sensor6.value(0)
# s7 = sensor7.value(0)
if s1 < AMB_THRESHOLD:
client.publish("topic/Harp", "C-3")
key_touched=True
if s2 < AMB_THRESHOLD:
client.publish("topic/Harp", "D-3")
key_touched=True
if s3 < AMB_THRESHOLD:
client.publish("topic/Harp", "E-3")
key_touched=True
if s4 < AMB_THRESHOLD:
client.publish("topic/Harp", "F-3")
key_touched=True
if s5 < AMB_THRESHOLD:
client.publish("topic/Harp", "G-3")
key_touched=True
if s6 < AMB_THRESHOLD:
client.publish("topic/Harp", "A-3")
key_touched=True
# if s7 < AMB_THRESHOLD:
# client.publish("topic/Harp", "B-3")
# key_touched=True
if key_touched == True:
sleep(DELAY)
On the Ubuntu laptop side:
sudo easy_install paho-mqtt
The subscriber script is “harp-mqtt-sub.py”
#!/usr/bin/env python
import paho.mqtt.client as mqtt
from mingus.midi import fluidsynth
from mingus.containers.note import Note
EV3_IP = "192.168.43.35"
SOUNDFONT = 'Concert_Harp.sf2'
INSTRUMENT = 46 # Harp
NOTES = ['C-3','D-3','E-3','F-3','G-3','A-3','B-3']
def on_connect(client, userdata, flags, rc):
print("Connected with result code "+str(rc))
client.subscribe("topic/Harp")
def on_message(client, userdata, msg):
global i
if (msg.payload in NOTES):
print msg.payload
fluidsynth.play_Note(Note(msg.payload))
client = mqtt.Client()
client.connect(EV3_IP,1883,60)
client.on_connect = on_connect
client.on_message = on_message
fluidsynth.init(SOUNDFONT, "alsa")
fluidsynth.set_instrument(1, INSTRUMENT)
client.loop_forever()
And guess what? It works!!! I just love linux and open source!
I will keep waiting for David Lechner to include ALSA MIDI support in ev3dev’ kernel. I’m not so sure if there is enough horsepower in the EV3 to load a soundfont and play it with acceptable latency but if I can at least use the MIDI client/server functionality I can drop MQTT.
An interesting possibility that this client/server design allows is to scale my harp easily: with just a second EV3 (2 MUX each) I can make a 13-string harp with almost no modification on my code.
This is an idea I’ve been postponing for several months but the time has finally come: an laser harp.
After tinkering with lasers, fog, sound, color sensors and python I found myself wondering how to give a proper use to all that. Then I remembered Jean-Michel Jarre and how his laser harp made such a big impression on me at late 80’s when I finally decided “hey, i wanna study Electronics!”
For a first version, let’s call it “a proof of concept”, I just want a simple 7-string harp that can play the basic 7 notes. Polyphony would be great but I doubt that the EV3 sound capabilities allow that (and I cannot afford the brute force solution of using 7 EV3 so that each one plays only a single note).
So in the last months I’ve been buying EV3 color sensors and I finally have 7. Since the EV3 only has 4 input ports I need some kind of sensor multiplexer but thanks to mindsensors.com I already have one EV3SensorMux (and a second one is on the way, from an european distributor – portuguese customs DO stink!)
With 2 MUX it’s possible to connect up to 8 sensors to the EV3. Since I just want 7 “strings” I am considering using an 8th sensor to control the amplitude of the notes. I’ll try an ultrasonic sensor but I’m not sure if it has enough “wideness” to cover the whole harp, let’s see.
this was suggested to me by David Lechner in another issue, hope will be fixed soon.
To use the color sensors in python I just need to know their ports. With the MUX in port ‘in1’ and 6 color sensors connected, these are the ports to use:
So whenever the light level over one of the color sensor drops bellow AMB_THRESHOLD a note will play for TONE_LENGHT milliseconds.
Unfortunately the sound is monophonic (just one note can be played at a time) and it doesn’t sound like an harp at all – it sounds more like my BASIC games on the ZX Spectrum in the 80’s.
So I tried Sound.play(Wave File) instead. Found some harp samples, converted them to .wav files at 44100 Hz and it really sounds much better… but the length of the samples I found is to big so the “artist” have to wait for the note to stop playing before moving the hand to another “string”. Not good and also not polyphonic.
Next post I’ll show a better approach for both quality and polyphony: MIDI.
I started fiddling with LEGO Dimensions Toy Pad and the Mindstorms EV3. Later I’ll post better and more organized information but for now here is the script I used with the following video – it shows how to read the NGC tags and change the RGB color of each pad.