So far I have been using LabVIEW to transfer files to and from my Brick. Besides swapping the SD card between the Brick and my computer that was the only way I knew of that would work without creating a special cable or getting a wifi dongle. (Which I have ordered but it has not yet appeared. Cursed you Webhallen! )
Yesterday I was poked regarding MonoBrick and I had a look at it, and what does it provide if not a way to communicate with the Brick over Bluetooth! The MonoBrick Communications Library is a C# library that allow you to create an app in C# that can communicate with a EV3 or NXT Brick.
Excited about the possibilities I downloaded the DLL’s and imported them in my favorite C# environment, Unity. Unfortunately Unity isn’t the best C# environment as it only supports .NET 2.0, and it turns out the MonoBrick Communications Library require a higher .NET version. I don’t know which one but it works with .NET 4.0 at least. (I use Unity at work everyday and I still don’t really know my way around the .NET environment and all the different versions of .NET and Mono etc.. Sweet ignorance!)
So after realizing that MonoBrick doesn’t work with Unity I decided to try and build a stand alone app with MonoDevelop and it sort of worked. I booted up the MonoDevelop that comes with Unity and created a solution that built beautifully. But it wouldn’t start. The app was set to build to x86, and there was no way to change to build to Mac. (Who BTW use Intel Core i7 which are x86 compatible, so when MonoDevelop say x86 it doesn’t mean it will build something that run on any x86, MonoDevelop mean it will build a Windows executable)
Since I didn’t find a way to switch to build for OSX I decided to download Xamarin Studio and Mono MDK, but once those where downloaded and installed I could finally have another go at the sample apps that comes with MonoBrick.
After loading the sample apps I realize the project files are made specifically for x86 (i.e. Windows) and there is no way to switch target platform once it has been set. Seriously! What is the point of installing a hardware abstraction layer like Mono if I can’t build apps that run in Mono on all platforms that Mono supports? I’d be super happy if someone who knows this stuff could fill me in!
In any case, I decided to create a completely new project and chose that it should be targeted towards Mac. When doing that I couldn’t find a way to create a console app for OSX, all I found was a template that looks a lot like the template app you get with Xcode. All the classes and files are the same. Except these where written in C#.
Anyhoo, now I had a C# app up and running on my computer and I started to copy the code from the MonoBrick sample project, and I ran into the next problem. The MonoBrick namespace wasn’t recognized. I had added the MonoBrick DLL into my project by simply adding all files from the downloaded MonoBrick package, but for some reason Xamarin Studio didn’t seem to parse the DLL’s when doing that, so what I ended up doing was right click on the “References” folder in my solution and chose “Edit references…”. I went to the “.Net Assembly” tab which seemed to be some form of file browser. I could highlight MonoBrick.dll and LibUsbDotNet.dll and click “Add” and they where properly added and parsed into my project, and now the sample program started.
And now, my lovely friends, the app connected to the Brick! Happy fun time! My first program was this:
var brick = new Brick<Sensor,Sensor,Sensor,Sensor>("/dev/tty.EV3-SerialPort"); brick.Connection.Open(); BrickFile files; string folders; brick.FileSystem.GetFolderInfo( ".", out files, out folders ); Console.WriteLine( "Files" ); foreach( BrickFile file in files ) Console.WriteLine( "File: " + file.FullName ); Console.WriteLine( "Folders" ); foreach( string folder in folders ) Console.WriteLine( "Folder: " + folder );
I don’t remember what the output was but I was listing some folder somewhere on the Brick. The joy and excited I had over this is indescribable! This could mean I have another way of synching my app to the Brick so I don’t have to go through LabVIEW!
After that I spent a good amount of time browsing the files on the Brick by passing in different folders. First I looked at “/”, and then I found my way to “/mnt/card/” and “/home/root/lms2012/” and I had a generally good feeling about it. Sometimes I had the issue of files showing up in the memory browser on the Brick but not when I list files over bluetooth. I still don’t know why and most of the time it seemed to work so I haven’t bothered looking into it.
After that I attempted to poke the Brick, not just peek into it. So I added this:
brick.FileSystem.CreateDirectory( "/mnt/card/bluetooth/" );
And it worked! When listing files in “/mnt/card/” I could see there was a bluetooth folder, and when using the memory browser on the brick the bluetooth folder was there as well. Next I added this:
brick.FileSystem.WriteFile( "/Users/magnusrunesson/Projects/ev3zipper/log.rbf", "/mnt/card/bluetooth/log.rbf" );
And I ran into problems! I got a “permission denied” error message. I suspected there was problems accessing the local file, I was thinking that perhaps there was a security thing going on with Mono not being allowed to access any ol’ file on my drive, so I removed the brick.FileSystem.WriteFile() call and used System.IO.File to open the same local file, and when trying the app again I got the same permission denied error message.
Now I was sure that it was a Mono problem, but then I noticed that the brick.FileSystem.CreateDirectory() call was still there, so I removed it, put the CreateFile back in and tried again, and this time it worked beautifully to create a file. I had transferred my first RBF file to the Brick without using LabVIEW. It worked fine to start the RBF on the Brick using the memory browser. The program generated a log file that for some reason didn’t show up in the memory browser on the Brick, but when listing files remotely it did show up.
The next step was to try and download the log file from Brick to my computer, by using this piece of code:
brick.FileSystem.ReadFile( "/mnt/card/bluetooth/log.txt", "/Users/magnusrunesson/Projects/ev3zipper/megabluetoothlog.txt" );
And again that worked like a charm. So now I have a C# app that at it’s very basic core can upload files to the Brick and download files from the Brick.
With the C# FileSystemWatcher class I’m hoping to have a way of automatically assembling and downloading my app to the Brick as I work with it, so when the FileSystemWatcher notice a change in my LMS file it could automatically assemble it into an RBF file and transfer it to the Brick. That way all I have to do is press Save in my text editor (which is Sublime btw, it kicks ass) wait a few seconds and then start the app on the Brick. Or even automate starting the app, MonoBrick seems to support starting programs remotely through the brick.StartProgram() function. It could be extended so the C# app also notices changes in source assets like graphics and automatically convert a source BMP file to RGF, for example. Same with sound.
A downside to this though seems to be battery usage. I’ve been using the Brick quite extensively for the last week, but only connected via USB, and the batteries have been quite charged still, but after a few hours of being connected with bluetooth I can actually see a drop in battery charge. So I am a bit concerned that bluetooth use a bit too much batteries. But then on the other hand, MonoBrick does support connection over USB so if that use less battery then yay, go USB!