Message Boards Message Boards

GROUPS:

Connecting two Raspberry Pi's using MathLink

Posted 5 years ago
7837 Views
|
2 Replies
|
3 Total Likes
|
This post explains how you can use MathLink to connect two Raspberry Pi's together and evaluate Wolfram Language commands remotely.

For this experiment you will need:
  • Two Raspberry Pi's, connected to the internet.

The first step is to set up passwordless ssh between your RPi's, so that the Wolfram Language can set up an automated connection without the need for entering passwords. To set up passwordless ssh, evaluate the following command in a terminal shell (don't type the 'my-pi>'):
my-pi> ssh-keygen

Hit enter as needed to accept all the prompted defaults. This command will create a .ssh subdirectory in your home directory. Change into that directory:
my-pi> cd .ssh

And then authorize your public key by copying it to a file called 'authorized_keys':
my-pi> scp id_rsa authorized_keys

Next you will need to copy this entire  directory to the second Raspberry Pi:
my-pi> cd ~
my-pi> scp -r .ssh pi@my-other-pi.example.com:/home/pi

For this 'scp' command you will still need to enter your password, but after this you should be able to use 'ssh' and 'scp' without entering your password. In my case I use a machine called 'demo-pi' as the first machine and 'test-pi' as the second machine:
pi@demo-pi ~ $ ssh test-pi
Linux test-pi 3.10.25+ #622 PREEMPT Fri Jan 3 18:41:00 GMT 2014 armv6l
The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.
Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
pi@test-pi ~ $

Exit your remote pi shell. Now, we can work on the Wolfram Language code to make a MathLink connection. Here is the code, explained line by line:
link = LinkCreate[LinkProtocol->"TCPIP"];

This sets up a MathLink connection end point on the local machine. The protocol is TCPIP which means that it uses the network. Next we need to create the end point on the remote machine.
linkname = First[link];

This extracts the linkname from the link object. It is passed to the remote machine.
process = StartProcess[ $SystemShell ];

This launches a local system shell that we can feed shell commands to.
WriteLine[ process, "/usr/bin/ssh pi@test-pi.wri.wolfram.com /usr/bin/wolfram -mathlink -linkmode connect -linkprotocol tcpip -linkname "<>linkname<>" -subkernel -noinit &" ];

This is a shell command which launches the Wolfram Engine on the remote machine. Again we use TCPIP as the link protocol, so the connection will be on the network.
Attributes[PiEvaluate]={HoldAllComplete};
PiEvaluate[e_]:=(LinkWrite[link,Unevaluated[e]];First[LinkRead[link]]);

This is utility function which takes an expression 'e' and sends it to the other Raspberry Pi to be evaluated.
LinkWrite[link,"hi"]; LinkRead[link]; LinkRead[link];

This line is to test out the connection. The extra LinkRead is to read the first InputNamePacket (which the remote machine always writes to the link).

Here is the full code, change 'test-pi.wri.wolfram.com' to your actual remote machine name and save it under 'connect.m':
link = LinkCreate[LinkProtocol->"TCPIP"];
linkname = First[link];
process = StartProcess[ $SystemShell ];
WriteLine[ process, "/usr/bin/ssh pi@test-pi.wri.wolfram.com /usr/bin/wolfram -mathlink -linkmode connect -linkprotocol tcpip -linkname "<>linkname<>" -subkernel -noinit &" ];
Attributes[PiEvaluate]={HoldAllComplete};
PiEvaluate[e_]:=(LinkWrite[link,Unevaluated[e]];First[LinkRead[link]]);
LinkWrite[link,"hi"]; LinkRead[link]; LinkRead[link];


We can now launch the Wolfram Language engine and load the 'connect.m' package:
pi@demo-pi ~ $ wolfram
Wolfram Language (Raspberry Pi Pilot Release)
Copyright 1988-2014 Wolfram Research
Information & help: wolfram.com/raspi

In[1]:= Get["connect.m"]
In[2]:=


After a few seconds (it blocks until the remote engine has started and is connected) you will be able to use the PiEvaluate command. A simple test is to
remotely evaluate $MachineName, which should return the name of the remote machine:
In[2]:= PiEvaluate[$MachineName]
Out[2]= test-pi

In[3]:= $MachineName
Out[3]= demo-pi

In[4]:= $MachineName != PiEvaluate[$MachineName]
Out[4]= True
2 Replies
Thanks, I changed that instance of RemoteEvaluate to PiEvaluate. I like it better too, but it is already a reserved function as a future Wolfram Language function.
Posted 5 years ago
Very nice... thanks. 

You may want to edit your post to ensure that you consistently use "RemoteEvaluate" or "PiEvaluate"  (I prefer "RemoteEvaluate").

-Joe
Reply to this discussion
Community posts can be styled and formatted using the Markdown syntax.
Reply Preview
Attachments
Remove
or Discard

Group Abstract Group Abstract