In part so I don’t lose the recipe, here are some notes for getting up and running with IPython on a Lego EV3 brick.
The command lines are prefixed to show whether we’re running them on the Mac or the brick…
To start with, we need to flash a microSD card with an image of the ev3dev operating system. The instructions are on the ev3dev site – Writing an SD Card Image Using Command Line Tools on OS X. – , but I repeat the ones for a Mac here for convenience.
- Download an image from the repository – I used the ev3dev-jessie-2015-12-30 image because the current development version is in a state of flux and the python bindings don’t necessarily work with it just at the moment…
- Assuming you have downloaded the file to your home Downloads directory (that is, ~/Downloads), launch a new terminal and run: cd Downloads
[Mac] unzip ev3-ev3dev-jessie-2015-12-30.img.zip
[Mac] diskutil list
- Put the microSD card (at least 2GB, but no more than 16GB, I think? I used a 4GB microSD (HC) card) into an SD card adapter and pop it into the Mac SD card reader. Check that it’s there and what it’s called; (you’re looking for the new disk…):
[Mac] diskutil list
- Now unmount the new disk corresponding the the SD card: diskutil unmountDisk /dev/disk1s1

If you don’t see the /dev/desk1 listing, check that the write protect slider on your SD card holder isn’t in the write protect position.
- We’re going to write some raw bits to the card (/dev/disk1 in my example), so we need to write to /dev/rdisk1 (note the r before the disk name). The write will take some time – 5 minutes or so – but if you’re twitchy, ctrl-T will show you a progress message). You’ll also need to enter your Mac password. (NOTE: if you use the wrong disk name, you can completely trash your computer. So be careful;-)
[Mac] sudo dd if=~Downloads/ev3-ev3dev-jessie-2015-12-30.img of=/dev/rdisk1 bs=4m
GOTCHA: when I tried, I got a Permission Denied message at first. It seems that for some reason my Mac thought the SD card was write protected. On the SD card adapter is a small slider that sets the card to “locked” or “unlocked”. The SD card reader in the Mac is a mechanical switch that detects which state the slider is in and whether the card is locked. I don’t know if it was a problem with the card adapter or the Mac reader, but I took the card reader out of the Mac, changed the slider setting, put card reader back in, and did the unmount and then sudo dd steps again. It still didn’t work, so I took the card out again, put the slider back the other way, and tired again. This time it did work.
- Once the copy is complete, take the SD card adapter out, remove the microSD car and put in in the EV3 brick. Start the EV3 brick in the normal way.
Hopefully, you should the brick boot into the Brickman UI (it may take two or three minutes, include a period when the screen is blank and the orange lights are ticking for a bit…)
Navigate the brick settings to the Networks menu, select Wifi and scan for your home network. Connect to the network (the password settings will be saved, so you shouldn’t have to enter them again).
By default, the IP address of the brick should be set to 192.168.1.106. To make life easier, I set up passwordless ssh access to the brick. Using some guidance in part originally from here, I accessed the brick from my Mac terminal and set up an ssh folder. First, log in to the brick from the Mac terminal:
[Mac] ssh robot@192.168.1.106
When prompted, the password for the robot user is maker.

This should log you in to the brick. Run the following command to create an ssh directory into which the shh key will be placed, and then exit the brick commandline to go back to the Mac command line.
[Brick] install -d -m 700 ~/.ssh
[Brick] exit
Create a new key on your Mac, and then copy it over to the brick:
[Mac] ssh-keygen -R 192.168.1.106
[Mac] cat ~/.ssh/id_rsa.pub | ssh robot@192.168.1.106 'cat > .ssh/authorized_keys'
You will be prompted again for the password – maker – but next time you try to log in to the brick, you should be able to do so without having to enter the password. (Instead, the ssh key will be used to get you in.)

If you login to the brick again – from the Mac commandline, run:
[Mac] ssh robot@192.168.1.106
you should be able to run a simple Python test program. Attach a large motor to input A on the brick. From the brick commandline, run:
[Brick] python
to open up a Python command prompt, and then enter the following commands to use the preinstalled ev3dev-lang-python Python bindings to run the motor for a few seconds:
[Python] import ev3dev.ev3 as ev3
[Python] m = ev3.LargeMotor('outA')
[Python] m.run_timed(time_sp=3000, duty_cycle_sp=75)
Enter:
[Python] exit
to exit from the Python interpreter.
Now we’re going to install IPython. Run the following commands on the brick command line (update, but DO NOT upgrade the apt packages). If prompted for a password, it’s still maker:
[Brick] sudo apt-get update
[Brick] sudo apt-get install -y ipython
You should now be able to start an IPython interpreter on the brick:
[Brick] ipython
The Python code to test the motor should still work (hit return it you find you are stuck in a code block). Typing:
[Brick] exit
will take you out of the interpreter and back to the brick command line.
One of the nice things about IPython is that we can connect to it remotely. What this means is that I can start an IPython editor on my Mac, but connect it to an IPython process running on the brick. To do this, we need to install another package:
[Brick] sudo apt-get install -y python-zmq
Now you should be able to start an IPython process on the brick that we can connect to from the Mac:
[Brick] ipython kernel
The process will start running and you should see a message of the form:
To connect another client to this kernel, use:
--existing kernel-2716.json
This file contains connections information about the kernel.
Now open another terminal on the Mac, (cmd-T in the terminal window should open a new Terminal tab) and let’s see if we can find where that file is. Actually, here’s a crib – in the second terminal window, go into the brick:
[Mac] ssh robot@192.168.1.106
And then on the brick command line in this second terminal window, show a listing of a the directory that should contain the connection file:
[Brick] sudo ls /home/robot/.ipython/profile_default/security/
You should see the –existing kernel-2716.json file (or whatever it’s exactly called) there. Exit the brick command line:
[Brick] exit
Still in the second terminal window, and now back on the Mac command, copy the connection file from the brick to your current directory on the Mac:
[Mac] scp robot@192.168.1.106:/home/robot/.ipython/profile_default/security/kernel-2716.json ./
If you have IPython installed on you Mac, you should now be able to open an IPython interactive terminal on the Mac that is connected to the IPython kernel running on the brick:
[Mac] ipython console --existing ${PWD}/kernel-2716.json --ssh robot@192.168.1.106
You should be able to execute the Python motor test command as before (remember to import the necessary ev3dev.ev3 package first).
Actually, when I ran the ipython console command, the recent version of jupyter on my Mac gave me a depreaction warning which means I would have been better running:
[Mac] jupyter console --existing ${PWD}/kernel-2716.json --ssh robot@192.168.1.106
So far so good – can we do any more with this?
Well, yes, a couple of things. When starting the IPython process on the brick, we could force the name and location of the connection file:
[Mac] ipython kernel -f /home/robot/connection-file.json
Then on the Mac we could directly copy over the connection file:
[Mac] scp robot@192.168.1.106:/home/robot/connection-file.json ./
Secondly, we can configure a Jupyter notebook server running on the Mac to so that it will create a new IPython process on the brick for each new notebook.
Whilst you can configure this yourself, it’s possibly easy to make use of the remote_ikernel helper:
[Mac] pip3 install remote_ikernel
[Mac] remote_ikernel manage --add --kernel_cmd="ipython kernel -f {connection_file}" --name="Ev3dev" --interface=ssh --host=robot@192.168.1.106
Now when you should be able to connect to a notebook run against an IPython kernel on the brick.

Note that it may take a few seconds for the kernel to connect and the first cell to run – but from then on it should be quite responsive.

To show a list of available kernels for a particular jupyter server, run the following in a Jupyter code cell:
import jupyter_client
jupyter_client.kernelspec.find_kernel_specs()
PS for ad hoc use, I thought it might be useful to try setting up a quick wifi router that I could use to connect the brick to my laptop in the form of an old Samsung Galaxy S3 android phone (without a SIM card). Installing the Hotspot Control app provided a quick way of doing this… and it worked:-)
PPS for a more recent version of IPython, install it from pip.
If you installed IPython using the apt-get route, uninstall it with:
[Brick] sudo apt-get uninstall ipython
Install pip and some handy supporting tools that pip may well require at some point:
[Brick] sudo apt-get install build-essential python-dev
Running:
[Brick] sudo apt-get install python-pip
would run an old version of pip – pip --version shows 1.5.6 – which could be removed using sudo apt-get remove python-setuptools.
To grab a more recent version, use:
[Brick] wget https://bootstrap.pypa.io/get-pip.py
[Brick] sudo -H python get-pip.py
which seems to take a long time to run with no obvious sign of progress, and then tidy up:
[Brick] rm get-pip.py
Just to be sure, then update it:
[Brick] sudo pip install --upgrade setuptools pip
which also seems to take forever. Then install IPython:
[Brick] sudo pip install -y ipython
I’m also going to see if I can give IPythonwidgets a go, although the install requirements looks as if it’ll bring down a huge chunk of the Jupyter framework too, and I’m not sure that’s all necessary?
[Brick] sudo pip install ipywidgets
For a lighter install, try sudo pip install --no-deps ipywidgets to install ipywidgets without dependencies. The only required dependencies are ipython>=4.0.0, ipykernel>=4.2.2 and traitlets>=4.2.0;.
The widgets didn’t seem to work at first, but it seems that following a recent update to the Jupyter server on host, it needed a config kick before running jupyter notebook:
jupyter nbextension enable --py --sys-prefix widgetsnbextension
PPS It seems to take a bit of time for the connection to the IPython server to be set up:

The Timeout occurs quite quickly, but then I have to wait a few dozen seconds for the tunnels on ports to be set up. Once this is done, you should be able to run things in a code cell. I usually start with print("Hello World!") ;-)
PPPS For plotting charts:
sudo apt-get install -y python-matplotlib
Could maybe even go the whole hog…
sudo apt-get install -y python-pandas
sudo pip install seaborn
PPPPS Here’s my current build file (under testing atm – it takes about an hour or so…) – ev3_ipy_build.sh, so:
[Mac] scp ev3_ipy_build.sh robot@192.168.1.106
[Brick] chmod +x ev3_ipy_build.sh
[Brick] sudo ./ev3_ipy_build.sh
sudo apt-get update
sudo apt-get install -y build-essential python-dev
sudo apt-get install -y python-zmq python-matplotlib python-pandas
wget https://bootstrap.pypa.io/get-pip.py
sudo -H python get-pip.py
rm get-pip.py
sudo pip install --upgrade setuptools pip
sudo pip install ipython ipykernel traitlets seaborn
sudo pip install --no-deps ipywidgets
PPPPPS to clone the SD card on a Mac, insert the SD card and run:
[Mac] diskutil list
[Mac] sudo dd if=/dev/disk1 of=~/Desktop/my_ev3dev_image.dmg
The corresponding restore (in the process described at the start of this post) would use /my_ev3dev_image.dmg rather than the ev3-ev3dev-jessie-2015-12-30.img image.
PPPPPPS Connecting to remote kernel on brick – start IPyhton kernel on brick:
[Brick] ipython kernel -f /home/robot/test.json
Copy the connection file over to the host:
[Mac] scp robot@192.168.1.106:/home/robot/test.json ./
Check the path you copied it to
[Mac] pwd
For me, that returned /Users/ajh59.
Start a console on the host using the existing connection file – use a full, explicit path to the file. Also works with things like Spyder:
[Mac] jupyter console --existing /Users/ajh59/test.json --ssh robot@192.168.1.106
