Using Grove devices to the EV3

After David Lechner announced ev3dev support for it I’ve been planning to offer myself a couple of BrickPi 3 from Dexter Industries (just one is not enough since the BrickPi 3 suports daisy chaining).

While I wait for european distributors to sell it (and my budget to stabilize) and since I’m also playing with magnets, I ordered a mindsensors.com Grove adapter so I can start testing Grove devices with my Ev3. Also got two Grove devices from Seeed Studio at my local robotics store, will start with the easiest one: Grove – Electromagnet.

ev3dev doesn’t have a Grove driver yet but since the adapter is an I2C device it recognizes it and configures it as an I2C host:

[  563.590748] lego-port port0: Added new device 'in1:nxt-i2c-host'
[  563.795525] i2c-legoev3 i2c-legoev3.3: registered on input port 1

Addressing the Grove adpter is easy, just need to follow the ev3dev documentation (Appendix C : I2C devices):

robot@ev3dev:~$ ls /dev/i2c-in*
/dev/i2c-in1

robot@ev3dev:~$ udevadm info -q path -n /dev/i2c-in1        
/devices/platform/legoev3-ports/lego-port/port0/i2c-legoev3.3/i2c-3/i2c-dev/i2c-3

So the Grove adapter is at I2C bus #3. According to mindsensors.com User Guide, it’s address is 0x42. That’t the unshifted address but fot i2c-tools we need to use the shifted address (0x21 – at the end of the ev3dev Appendix C doc there is a table with both addresses).

robot@ev3dev:~$ sudo i2cdump 3 0x21

     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f    0123456789abcdef
00: 56 31 2e 30 32 00 00 00 6d 6e 64 73 6e 73 72 73    V1.02...mndsnsrs
10: 47 61 64 70 74 6f 72 00 00 00 00 00 00 00 00 00    Gadptor.........
20: 4a 61 6e 20 30 34 20 32 30 31 35 00 31 32 46 31    Jan 04 2015.12F1
30: 38 34 30 00 00 00 00 00 00 00 00 00 00 00 00 00    840.............
40: 00 97 03 32 00 00 00 00 00 00 00 00 00 00 00 00    .??2............
50: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
60: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
70: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
90: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
a0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
b0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
c0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
d0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
e0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................
f0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00    ................

Acording to the User Guide, this is the expected content of the first 24 registers:

0x00-0x07: Software version – Vx.nn
0x08-0x0f: Vendor Id – mndsnsrs
0x10-0x17: Device ID – Gadptor

So I have a v1.02 Grove adapter.

To use the Grove – Electromagnet I just need to send a “T” (0x54) to the Command Register (0x41) to set the Grove Adapter into “Transmit” mode and next set the Operation Mode, which can be “Digital_0” (sending 0x02 to the Operation Mode register at 0x42) or “Digital_1” (sending 0x03 to the Operation Mode register).

So to turn the electromagnet ON:

sudo i2cset -y 3 0x21 0x41 0x54
sudo i2cset -y 3 0x21 0x42 0x03

And to turn it OFF:

sudo i2cset -y 3 0x21 0x41 0x54
sudo i2cset -y 3 0x21 0x42 0x02

Just a warning: with an operating current of 400 mA when ON the electromagnet gets hot very quickly – not enough to hurt but don’t forget to switch it OFF after use to prevent draing the EV3 batteries.

The same method (“T” + “Digital_0” / “Digital_1”) can be used with several other Grove devices, like the Grove – Water Atomization:

(a great way to add fog effects to our creations – just be careful with short circuits; if you add some kind of parfum you can also have scent effects)

Final note: you can use the mindsensors.com Grove Adapter with native EV3 firmware (just import the available EV3-G block) but if you are using ev3dev like me be sure to use a recent kernel (as of today, “4.4.61-20-ev3dev-ev3”) because older versions had a bug that caused some communication problems with I2C devices (the Grove Adapter is an I2C device).

Triplex – an holonomic robot

A few months ago, trying to find an use for a new LEGO brick found in NEXO Knights sets, I made my first omni wheel. It worked but it was to fragile to be used in a robot so I decided to copy one of Isogawa’s omni wheels and keep working on an holonomic robot with 3 wheels.

Why 3 wheels?

At first I only had NEXO parts to build 3 wheels but I enjoyed the experience – my first RC experiments seemed like lobsters. Controlling the motion is not easy but I found a very good post from Miguel from The Technic Gear  so it was easy to derive my own equations. But Power Functions motors don’t allow precise control of speed so I could not make the robot move in some directions. I needed regulated motors like those used with MINDSTORMS EV3.

So after assembling three Isogawa’s omniwheels and making a frame that assured the wheel doesn’t separate from the motor it was just a matter of making a triangled frame to join all 3 motors and sustain the EV3:

First tests with regulated motor control seem promising: Triplex is fast enough and doesn’t fall apart.  It drifts a bit so I’ll probably use a gyro sensor or a compass to correct it.

In this demo video I show Triplex being wireless controlled from my laptop keyboard through an SSH session. It just walks “forward” or “backward” (only two motors are used, running at the same speed in opposite directions) or rotates “left” or “right” (all motors are used, running at the same speed and the same direction).

For the code used in this demo I copied a block of code from Nigel Ward’s EV3 Python site that solved a problem I’ve been having for a long time: how do I use Python to read the keyboard without waiting for ENTER and without installing pygame or other complex/heavy library?

#!/usr/bin/env python3

# shameless based on
# https://sites.google.com/site/ev3python/learn_ev3_python/keyboard-control
#

import termios, tty, sys
from ev3dev.ev3 import *

TIME_ON = 250

motor_A = MediumMotor('outA')
motor_B = MediumMotor('outB')
motor_C = MediumMotor('outC')

#==============================================

def getch():
    fd = sys.stdin.fileno()
    old_settings = termios.tcgetattr(fd)
    tty.setcbreak(fd)
    ch = sys.stdin.read(1)
    termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
    
    return ch

#==============================================

def forward():
    motor_A.run_timed(speed_sp=-1200, time_sp=TIME_ON)
    motor_C.run_timed(speed_sp=1200, time_sp=TIME_ON)

#==============================================

def backward():
    motor_A.run_timed(speed_sp=1200, time_sp=TIME_ON)
    motor_C.run_timed(speed_sp=-1200, time_sp=TIME_ON)

#==============================================

def turn_left():
    motor_A.run_timed(speed_sp=1200, time_sp=TIME_ON)
    motor_B.run_timed(speed_sp=1200, time_sp=TIME_ON)
    motor_C.run_timed(speed_sp=1200, time_sp=TIME_ON)

#==============================================

def turn_right():
    motor_A.run_timed(speed_sp=-1200, time_sp=TIME_ON)
    motor_B.run_timed(speed_sp=-1200, time_sp=TIME_ON)
    motor_C.run_timed(speed_sp=-1200, time_sp=TIME_ON)

#==============================================

print("Running")
while True:
   k = getch()
   print(k)
   if k == 'a':
      forward()
   if k == 'z':
      backward()
   if k == 'o':
      turn_left()
   if k == 'p':
      turn_right()
   if k == ' ':
      stop()
   if k == 'q':
      exit()

Thanks for sharing Nigel!

Now let’s learn a bit of math with Python.

For those who might interest, I also have some photos with the evolution of the project.

 

Running LEGO LDD on linux

I’m finally going to try the EV3DPrinter.

3D pen

Now that my 3D pen arrived from China I downloaded Marc-André Bazergui LDD file to understand how to assemble it and then it striked me… dang, need Windows to run LDD!

I still have the Windows VM I used to update the firmware of my EV3 but I don’t want to use it (yes, I’m stubborn) so I decided to try wine. I once had LDD working with wine but never really used it and now that I got a new laptop I didn’t even bothered to install wine again.

So after a few tweaks I got LDD running – it seems that running 32-bit MS Windows programs on wine on a 64-bit linux breaks some things but essentially one just needs to add some 32-bit gstreamer plugins to make LDD work fine.

To show the full process I created a 64-bit virtual machine (1 CPU, 4 GB RAM, 32 GB thin provisioned disk), installed Ubuntu 16.10 (64-bit) on it (default installation, just enabled the download of updates while installing and the installation of 3rd party software).

As I’m using VirtualBox I also installed the VirtualBox Guest Addictions, enabled bi-directional clipboard to allow copy&past of commands between the VM and my desktop and enabled a shared folder to exchange files (just the LDD 4.3.10 setup file and the EV3DPrinter .lxf file).

Then a full last update:

sudo apt update
sudo apt upgrade
sudo apt dist-upgrade

followed by a reboot and a safety snapshot (“trust no one”).

So this is the full process:

sudo dpkg --add-architecture i386 
sudo add-apt-repository ppa:wine/wine-builds
sudo apt-get update
sudo apt-get install --install-recommends winehq-devel

at this moment, I have wine 2.4 installed:

wine --version
wine-2.4

I could install LDD right now but it will not work because at first run it tries to play some music and or video and it fails. The trick is to install some plugins for gstreamer:

sudo apt install gstreamer1.0-plugins-good:i386 gstreamer1.0-fluendo-mp3:i386

So we install LDD by just double-clicking it. As it is the first time wine runs, it first asks to install two dependencies: mono and gecko (that assures some .Net Framework and Internet Explorer compatibility).

LDD setup asks for a language (“English”) then asks us to accept the License Agreement and suggests creating two shortcuts (“Desktop” and “Quick lauch”).

Then it asks to install Adobe Flash Player and to choose a destination folder (default is fine).

When completed, we may check the option to “Run LEGO Digital Designer” but it will not work, it just shows a black window that we need to force close.

But if we launch LDD again, it works now.

Just a last issue: when opening the EV3DPrinter .lxf file we get a request for a FLEXnet license file, it is located at the installation folder:

~/.wine32/drive_c/Program Files/LEGO Company/LEGO Digital Designer/RL278-1000.lic

Everything seems to work, even creating a Building Guide and the HTML Building Instructions.

I recorded everything in this video:

It’s a long (21 min) non edited video so you may want to skip most of it (the download and installation of wine components, the install of LDD and the creation of the Building Guide).

And by the way, this is nothing really new – Marc pointed me this video with LDD running on Ubuntu 7.10 (2007!)

LEGO Voice Control – EV3

And now the big test – will it work with EV3?

So, ev3dev updated:

Linux ev3dev 4.4.47-19-ev3dev-ev3 #1 PREEMPT Wed Feb 8 14:15:28 CST 2017 armv5tejl GNU/Linux

I can’t find any microphone at the moment so I’ll use the mic of my Logitech C270 webcam – ev3dev sees it as an UVC device as you can see with dmesg:

...
[ 1343.702215] usb 1-1.2: new full-speed USB device number 7 using ohci
[ 1343.949201] usb 1-1.2: New USB device found, idVendor=046d, idProduct=0825
[ 1343.949288] usb 1-1.2: New USB device strings: Mfr=0, Product=0, SerialNumber=2
[ 1343.949342] usb 1-1.2: SerialNumber: F1E48D60
[ 1344.106161] usb 1-1.2: set resolution quirk: cval->res = 384
[ 1344.500684] Linux video capture interface: v2.00
[ 1344.720788] uvcvideo: Found UVC 1.00 device <unnamed> (046d:0825)
[ 1344.749629] input: UVC Camera (046d:0825) as /devices/platform/ohci.0/usb1/1-1/1-1.2/1-1.2:1.0/input/input3
[ 1344.772321] usbcore: registered new interface driver uvcvideo
[ 1344.772372] USB Video Class driver (1.1.1)
[ 1352.171498] usb 1-1.2: reset full-speed USB device number 7 using ohci
...

and we can check with “alsamixer” that ALSA works fine with the internal microphone:

First press F6 to select sound card (the webcam is a sound card for ALSA)

Then press F5 to view all sound devices – there is just one, the mic:

We also need to know how ALSA addresses the mic:

arecord -l
**** List of CAPTURE Hardware Devices ****
card 1: U0x46d0x825 [USB Device 0x46d:0x825], device 0: USB Audio [USB Audio]
  Subdevices: 1/1
  Subdevice #0: subdevice #0

Card 1, Device 0 means we should use ‘hw:1,0’

Now we just follow the same process we used with Ubuntu. First we install pocketsphinx:

sudo apt install pocketsphinx
...
The following extra packages will be installed:
  javascript-common libblas-common libblas3 libjs-jquery liblapack3 libpocketsphinx1 libsphinxbase1
  pocketsphinx-hmm-en-hub4wsj pocketsphinx-lm-en-hub4
Suggested packages:
  apache2 lighttpd httpd
The following NEW packages will be installed:
  javascript-common libblas-common libblas3 libjs-jquery liblapack3 libpocketsphinx1 libsphinxbase1
  pocketsphinx pocketsphinx-hmm-en-hub4wsj pocketsphinx-lm-en-hub4
0 upgraded, 10 newly installed, 0 to remove and 0 not upgraded.
Need to get 8910 kB of archives.
After this operation, 30.0 MB of additional disk space will be used.
..

Although Ubuntu and Debian packages seem to be the same, the maintaners made some differente choices because in Ubuntu the ‘pocketsphinx-hmm-en-hub4wsj’ and ‘pocketsphinx-lm-en-hub4’ packages are missing.

So we copy 3 files from our previous work in Ubuntu:

  • keyphrase_list.txt
  • 0773.lm
  • 0772.dic

And we test it:

pocketsphinx_continuous -kws keyphrase_list.txt -adcdev hw:1,0 -lm 0772.lm -dict 0772.dic -inmic yes -logfn /dev/null

We get a “Warning: Could not find Capture element” but… yes, it works!

Of course it is slow… we see a big delay while starting until it displays “READY….” and also a big delay between each “Listening…” cycle. But it works! Isn’t open source great?

So we install expect to use our pipe again:

sudo apt install expect
mkfifo pipe

and we rewrite our ‘transmit.sh’ to command two EV3 motors (let’s call it “controller.sh” this time):

#!/bin/bash

while read -a words
do
case "${words[1]}" in

  move)
    if [ "${words[2]}" = "forward" ]; then
      echo "FRONT"
      echo run-timed > /sys/class/tacho-motor/motor0/command
      echo run-timed > /sys/class/tacho-motor/motor1/command
      sleep 0.2
    fi

    if [ "${words[2]}" = "backward" ]; then
      echo "BACK"
      sleep 0.2
    fi
    ;;

  turn)
    if [ "${words[2]}" = "left" ]; then
      echo "LEFT"
      echo run-timed > /sys/class/tacho-motor/motor1/command
      sleep 0.2
    fi

    if [ "${words[2]}" = "right" ]; then
      echo "RIGHT"
      echo run-timed > /sys/class/tacho-motor/motor0/command
      sleep 0.2
    fi    
    ;;

  stop)
    echo "STOP"
    ;;

  *)
    echo "?"
    echo "${words[1]}"
    echo "${words[2]}"
    ;;
esac
done

For some reason I don’t yet understand I had to change 2 things that worked fine with Ubuntu:

  • increase the index of the arguments (“${words[1]” and “${words[2]” instead of “${words[0]” and “${words[1]”
  • use capital letters for the keywords

This script sends “run-timed” commands to the motor file descriptors (you can read a good explanation on this ev3dev tutorial: ‘Using the Tacho-Motor Class’). I didn’t write commands for “move backward” this time (it would require extra lines to change direction, not difficult but I don’t want to increase the script to much).

Before we can use this script, we need to initialize the motors so we can use this other script, “init.sh”

#!/bin/bash

echo 1050 > /sys/class/tacho-motor/motor0/speed_sp
echo 200 > /sys/class/tacho-motor/motor0/time_sp
echo 1050 > /sys/class/tacho-motor/motor1/speed_sp
echo 200 > /sys/class/tacho-motor/motor1/time_sp

(it just sets maximum speed to motor0 and motor1 and the timer to 200 ms for the duration of each “run-timed” command).

So we open two a second ssh session to our EV3 and we ran in the first session:

unbuffer pocketsphinx_continuous -kws keyphrase_list.txt -adcdev hw:1,0 -lm 0772.lm -dict 0772.dic -inmic yes -logfn /dev/null > pipe

and in the second session:

cat pipe | ./controller.sh

And presto!

The robot is a RileyRover, a “very quick to build” design from Damien Kee.

LEGO Voice Control

This is going to be (I hope) the first of a series of posts about voice recognition.

Decided to control my LEGO  RC Tracked Racer with my recent FTDI based IR Transmitter. While reading some blogs I find my self thinking… hey, I can use voice control on my Ubuntu laptop, doesn’t seem to dificult!

So, in a nutshell:

  • install pocketsphinx
  • create a keyhphrase list
  • write a bash script to parse commands and control the LEGO
  • glue it all

So there are a few open source speech recognition projects. I picked Sphinx from Carnegie Mellon University, mainly because it is available in Debian and Ubuntu and they have lighter version, pocketsphinx, for lighter devices like Android or Raspberry Pi (of course I also thought that, with some luck and sweat, it could be used with ev3dev later on).

pocketsphinx is a command line tool but can be also used with python with a library, I made some fast tests but gave up when complexity started to increase – pyaudio and gstreamer may be OK on Ubuntu or Raspberry Pi but the EV3 will most probably choke, so let’s try just shell scripts first.

I decided to have 5 commands for my LEGO (4 directions and STOP). Documentation suggests that it is best to use sentences with at least 3 syllables so I created this keyphrase-list.txt file:

move forward /1e-12/
move backward /1e-5/
turn left /1e-12/
turn right /1e-14/
stop /1e-20/

The numbers represent detection threshold values, I started with /1e-10/ for all and then adapted for better results by trial and error. Not quite happy yet and will probably use just “front” and “back” instead of “forward” and “backward”.

I also created a Sphinx knowledge base compilation with CMU’s Sphinx Knowledge Base Tool, using a file with the same keyphrases:

move forward
move backward
turn left
turn right
stop

Your Sphinx knowledge base compilation has been successfully processed!

This generated a ‘0772. TAR0772.tgz’ file containing 5 files:

[TXT] 0772.dic                110    Pronunciation Dictionary
[   ] 0772.lm                 1.3K   Language Model
[   ] 0772.log_pronounce      100    Log File
[   ] 0772.sent                98    Corpus (processed)
[   ] 0772.vocab               43    Word List

I made some tests with these files as parameters for the pocketsphinx_continuous command as also the pyhton library but for the next examples they don’t seem to be required. But they will be used later 🙂

Now to test is, just run this command and start speaking:

$ pocketsphinx_continuous -inmic yes -kws keyphrase_list.txt -logfn /dev/null
READY....
Listening...
READY....
Listening...
stop
READY....
Listening...
^C

So I just use pocketsphinx_continuous command to keep listening to what I say to the microphone (“-inmic yes”) and find my keyphrases (“-kws keyphrase_list.txt) without filling my console with log messages (“-logfn /dev/null”).

Each time a keyphrase is detected with enough confidence it is displayed so I just need to redirect the output of these command to a shell script that parses it and sends the right IR codes to my LEGO:

#!/bin/bash

while read -a words
do

case "${words[0]}" in

  move)
    if [ "${words[1]}" = "forward" ]; then
      echo "FRONT"
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct FORWARD_BACKWARD
      sleep 0.2
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BRAKE_BRAKE
    fi
    if [ "${words[1]}" = "backward" ]; then
      echo "BACK"
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BACKWARD_FORWARD
      sleep 0.2
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BRAKE_BRAKE
    fi
    ;;
  turn)
    if [ "${words[1]}" = "left" ]; then
      echo "LEFT"
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct FORWARD_FORWARD
      sleep 0.2
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BRAKE_BRAKE
    fi
    if [ "${words[1]}" = "right" ]; then
      echo "RIGHT"
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BACKWARD_BACKWARD
      sleep 0.2
      irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BRAKE_BRAKE
    fi    
    ;;

  stop)
    echo "STOP"
    irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct BRAKE_BRAKE
    ;;

  *)
    echo "?"
    ;;

esac

Not pretty but it works – we can test in the command line like this:

$ echo "move forward" | ./transmitter.sh
FRONT

Of course, the ‘irsend’ commands only work if lircd is running and controlling an IR transmitter.

Now to glue everything we need to use a trick: Ubuntu version of pocketsphinx doesn’t flush stdout so the piping its output to my script wasn’t working, I found that I need to use the “unbuffer” command from “expect” package:

$ sudo apt install expect
$ make pipe

So in one console window I send the output, unbuffered, to the pipe I created

$ unbuffer pocketsphinx_continuous -inmic yes -kws keyphrase_list.txt -logfn /dev/null > pipe

And in another console window I read the pipe and send it to the trasmitter.sh script:

$ cat pipe |./transmitter.sh

And that’s it.

 

 

 

 

 

Using a FTDI adapter as an IR emitter – 4

We finally have LIRC but if we run it now it will fail looking for “liblirc.so.0” so we need to configure ev3dev to look for it in the right place:

sudo nano /etc/ld.so.conf.d/lirc.conf

  include /usr/local/lib

sudo ldconfig

We could also build LIRC with proper prefix options in order to prevent this last step but I’m lazy and this also helps when searching the web for common problems.

We also need to create a folder for LIRC to place a pid file:

sudo mkdir /var/run/lirc

and at least one remote control configuration file that tells LIRC how to talk with the Power Fucntions IR Receiver. So after two years I’m back to Connor Cary’s GitHub and find that he now has 3 configuration files available:

  • Combo_Direct
  • Combo_PWM
  • Single_Output

The last one was contributed by Diomidis Spinellis, the author of a very nice post “Replace Lego’s $190 Intelligent Brick with MIT’s Scratch and a $40 Raspberry Pi” I read a few months ago – what a small world we live 🙂

We should save these 3 files with a “.conf” extension under the folder

/usr/local/etc/lirc/lircd.conf.d/devinput.lircd.conf

There is already a “devinput.lircd.conf” file there but it only works with LIRC default device so we should rename it:

sudo mv /usr/local/etc/lirc/lircd.conf.d/devinput.lircd.conf /usr/local/etc/lirc/lircd.conf.d/devinput.lircd.dist

And that’s it, next post we’ll finally start LIRC!

Using a FTDI adapter as an IR emitter – 3

Now back to where we extracted LIRC:

cd lirc-0.9.4d
./configure

If all conditions are satisfied we get this at the end:

...
checking for FTDI... no
checking for FTDI... yes
...
Summary of selected options:
----------------------------------------
prefix:                         /usr/local
sysconfdir:                     ${prefix}/etc
x_progs:                        
host:                           armv5tejl-unknown-linux-gnueabi
host_os:                        linux-gnueabi
forkpty:                        -lutil
usb_libs                        -lusb -lusb-1.0
lockdir:                        /var/lock/lockdev

Conditionals:

BUILD_ALSA_SB_RC:no
BUILD_DSP:yes
BUILD_FTDI:yes
BUILD_HIDDEV:yes
BUILD_I2CUSER:yes
BUILD_LIBALSA:no
BUILD_LIBPORTAUDIO:no
BUILD_USB:yes
BUILD_XTOOLS:no
HAVE_DOXYGEN:no
HAVE_LIBUDEV:no
HAVE_MAN2HTML:no
HAVE_PYMOD_YAML:no
INSTALL_ETC:yes
NEED_PYTHON3:no
SYSTEMD_INSTALL:yes
DEVEL:no
HAVE_UINPUT:yes
DARWIN:no
LINUX_KERNEL:yes

We may now proceed with

make

and in a perfect world or at least with my Ubuntu it will build everything fine. But on my EV3 for two times I got this:

CDPATH="${ZSH_VERSION+.}:" && cd . && /bin/bash /home/robot/lirc-0.9.4d/missing aclocal-1.15 -I m4
/home/robot/lirc-0.9.4d/missing: line 81: aclocal-1.15: command not found
WARNING: 'aclocal-1.15' is missing on your system.
         You should only need it if you modified 'acinclude.m4' or
         'configure.ac' or m4 files included by 'configure.ac'.
         The 'aclocal' program is part of the GNU Automake package:
         <http://www.gnu.org/software/automake>
         It also requires GNU Autoconf, GNU m4 and Perl in order to run:
         <http://www.gnu.org/software/autoconf>
         <http://www.gnu.org/software/m4/>
         <http://www.perl.org/>
Makefile:479: recipe for target 'aclocal.m4' failed
make: *** [aclocal.m4] Error 127

That’s strange because my Ubuntu doesn’t have autoconf installed.

I tried installing several packages but make always failed. After some googling I found a workaround. Is rather strange and honestly I don’t know why but it works:

sudo apt install automake m4 autoconf
autoreconf -i

This wil take a lot of time (at least half an hour) but after that the compiling process works as expected (almost an hour more):

./configure
make
sudo make install

 

Using a FTDI adapter as an IR emitter – 5

sudo lircd -dserial=DN01DR29,output=3 -Hftdix

We gave lircd 3 parameters:

  • “DN01DR29” is the serial number of my FTDI adapter reported by dmesg
  • “output=3″ is the CTS pin we use to control the LED (in the ‘hello-ftdi.c” test we see LED defined as 0x08, that’s because LIRC ftdix drivers calculates the pin by left-shifting, so 2<<3 = 2³ = 8)
  • “ftdix” is the driver to use

We should check if lircd is running. In Ubuntu it writes several messages at “/var/log/messages” but this log doesn’t exist in ev3dev so

pgrep lircd
5411

E also see in dmesg that the ttyUSB device was disconnected by libftdi:

[47897.512814] ftdi_sio ttyUSB0: FTDI USB Serial Device converter now disconnected from ttyUSB0
[47897.513393] ftdi_sio 1-1.2:1.0: device disconnected

We now use ‘irsend’ to check for available transmitter:

sudo irsend -d/var/run/lirc/lircd LIST "" ""

LEGO_Combo_Direct
LEGO_Combo_PWM
LEGO_Single_Output

We can also list all commands avaible for a particular transmitter:

sudo irsend -d/var/run/lirc/lircd LIST LEGO_Combo_Direct ""

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

For first test we’ll just use “FORWARD_FORWARD” command (move both motors, “Red” and “Blue”, forward):

sudo irsend -d /var/run/lirc/lircd SEND_ONCE LEGO_Combo_Direct FORWARD_FORWARD

And our motor do spin!

So, after such a big post, whats the point?

Well, since LIRC can handle several transmitter and for ftdix it uses the serial number of the FTDI adapter to identify each transmitter… we can have as much transmitters as we want as long as our system can handle it. On a laptop or a Raspberry Pi 3 that’s probably 127 (the max number of USB devices we can have). Most probably the Ev3 will gasp will all that USB devices but at least two I know it can handle:

Will show how in a fourth post, later on.

Using a FTDI adapter as an IR emitter – 2

We should now compile LIRC  but as I said before I never got it working  without also compiling libftdi.

I downloaded and extracted ibftdi1-1.3 source code. Then:

cd  libftdi1-1.3
mkdir build
cd build
cmake -DCMAKE_INSTALL_PREFIX="/usr" ../

If everything is OK, we see:

...
-- Building unit test
-- Configuring done
-- Generating done
-- Build files have been written to: /home/robot/libftdi1-1.3/build

Then

make

If everything OK:

...
[100%] Built target test_libftdi1

And finally:

sudo make install

 

 

Using a FTDI adapter as an IR emitter

[Crazy intro, just talking to myself]

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:

sudo apt update
sudo apt upgrade
sudo apt dist-upgrade

After reboot my Ev3 is running kernel 4.4.47:

Linux ev3dev 4.4.47-19-ev3dev-ev3 #1 PREEMPT Wed Feb 8 14:15:28 CST 2017 armv5tejl GNU/Linux

First we install all dependencies needed for both LIRC and libftdi:

sudo apt install libftdi-dev build-essential pkg-config xsltproc libusb-1.0 cmake libboost-all-dev

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.