britguy
Posts: 16
Joined: Mon May 28, 2012 1:34 am

Mono (C#) anyone?

Mon May 28, 2012 1:58 am

Ok, so I hold my hands up, I'm not a Linux guy, and I confess I have years of .NET experience that I would like to use on the Pi. I know Microsoft may be a dirty word in the Linux community, but I, and I hope lots of other Pi users will come to find programming in c# .NET a great (and free) experience on the Pi (sorry, I'm too old to learn a whole new language)

I am wanting to use the Pi for some robot/GPIO stuff. I've only had the Pi a few days but I have achceived some small steps so far:

1) Installing ArchLinux - seems to be a pretty small distro and have read that Mono works on it.
2) Installed Mono (once I updated ArchLinux & Pacman using pacman - Syu command)
3) Wrote a c# hello world app, and compiled it to an exe and ran it
4) Disabled the network and internet time server daemons (temporarily) upon boot so I achieved a boot up time of less than 10 seconds
5) Got it to run my hello world app immediately on startup (great if you want it to start controlling your robot once the Pi has power and has booted (also used mingetty to automatically log me in without a prompt - handy if your pi/robot doesnt have a keyboard - though it does seem to run my c# app before the login so I dont know if this is strictly necessary).

So, I'm hoping next step is to convert the Python GPIO examples to C# (good for non-time critical control of GPIO), then possibly a C# implementation or wrapper of Gert's register addressing GPIO code in C.

I have no-idea if there is anyone out there who wants to achieve a similar thing, but if there is I'm happy to share my learnings with you, and perhaps yours with me?

jools
Posts: 24
Joined: Sun Feb 19, 2012 9:47 pm

Re: Mono (C#) anyone?

Mon May 28, 2012 2:58 am

Yes, I too have installed Mono successfully (from source actually!) and am interested in C#, the GPIO and Gert Board.

I have recently written a blisteringly fast C# asynchronous server that compiles its own source code (like IIS) but has a very small footprint and have installed this on the Pi.

I feel Mono and the Pi are well suited: I've been really impressed how .net dll libraries just run out of the box on ARM, without recompilation and indeed how a .net .exe from Visual Studio will just run on the Pi under mono. Impressive !

jools
Posts: 24
Joined: Sun Feb 19, 2012 9:47 pm

Re: Mono (C#) anyone?

Mon May 28, 2012 2:59 am

Incidentally, there are other people installing mono on the Pi: type 'mono' as a search word here.

emg
Posts: 88
Joined: Wed Jan 11, 2012 11:01 pm

Re: Mono (C#) anyone?

Mon May 28, 2012 5:18 pm

I was looking to do similar GPIO work as well from Mono. What about Iron Python to access existing python GPIO scripts? I'm also looking to add a DS1338 RTC via I2C (the DS1338 is a 3.3/5v DS1307 RTC module that already has rPi support).

I don't understand all the linux fanboi's immediate dismissal (and wrong info) of Mono in just about every Mono thread on this board. If the goal is to get the rPi in front of the widest possible audience, being able to run applications under Mono just adds additional capability to an already great little device. Teach kids C#/VB, teach them python et al, it's all good.

andyl
Posts: 265
Joined: Tue Jan 10, 2012 11:05 am

Re: Mono (C#) anyone?

Mon May 28, 2012 6:02 pm

emg wrote:I was looking to do similar GPIO work as well from Mono. What about Iron Python to access existing python GPIO scripts?.
Why would you use IronPython instead of plain Python?

However access to the GPIO is very easy under linux and can see no reason why the existing libraries wouldn't work with IronPython.

emg
Posts: 88
Joined: Wed Jan 11, 2012 11:01 pm

Re: Mono (C#) anyone?

Mon May 28, 2012 8:24 pm

andyl wrote:
emg wrote:I was looking to do similar GPIO work as well from Mono. What about Iron Python to access existing python GPIO scripts?.
Why would you use IronPython instead of plain Python?

However access to the GPIO is very easy under linux and can see no reason why the existing libraries wouldn't work with IronPython.
I assumed IronPython would provide a cleaner, easier way to make C#/VB native calls to python libs? I am un-familiar with how to access GPIO pins from .net.

andyl
Posts: 265
Joined: Tue Jan 10, 2012 11:05 am

Re: Mono (C#) anyone?

Mon May 28, 2012 8:58 pm

emg wrote:
andyl wrote:
emg wrote:I was looking to do similar GPIO work as well from Mono. What about Iron Python to access existing python GPIO scripts?.
Why would you use IronPython instead of plain Python?

However access to the GPIO is very easy under linux and can see no reason why the existing libraries wouldn't work with IronPython.
I assumed IronPython would provide a cleaner, easier way to make C#/VB native calls to python libs? I am un-familiar with how to access GPIO pins from .net.
OK - probably not the best way to do things. It will pull yet more dependencies in.

Take a look at the python libraries for doing GPIO. It really is dead simple - like most unix things it is based on files. If you can open a file and read and write to it in C# you can do GPIO - it really is that easy.

There may still be a few oddities. Still not setup my Pi yet so I don't know if the files are read-write for a group (maybe called gpio) and if the standard user is a member of that group. If not those are very easy to do.

There are other ways of doing GPIO but accessing the files will get you going.

emg
Posts: 88
Joined: Wed Jan 11, 2012 11:01 pm

Re: Mono (C#) anyone?

Tue May 29, 2012 12:50 am

andyl wrote: Take a look at the python libraries for doing GPIO. It really is dead simple - like most unix things it is based on files. If you can open a file and read and write to it in C# you can do GPIO - it really is that easy.

There may still be a few oddities. Still not setup my Pi yet so I don't know if the files are read-write for a group (maybe called gpio) and if the standard user is a member of that group. If not those are very easy to do.

There are other ways of doing GPIO but accessing the files will get you going.
OK, thanks! Can you fill in any more detail on how this works? Specifically, what is going on 'behind the scenes' is a daemon or process looking for changes in a specific file for each GPIO pin that contains commands, data, etc?

Is this what you are referring to? http://www.raspberrypi.org/phpBB3/viewt ... f=9&t=2916 and http://quick2wire.com/2012/05/safe-cont ... pberry-pi/ and more generically, http://www.acmesystems.it/gpio_sysfs

andyl
Posts: 265
Joined: Tue Jan 10, 2012 11:05 am

Re: Mono (C#) anyone?

Tue May 29, 2012 9:15 am

emg wrote:
andyl wrote: Take a look at the python libraries for doing GPIO. It really is dead simple - like most unix things it is based on files. If you can open a file and read and write to it in C# you can do GPIO - it really is that easy.

There may still be a few oddities. Still not setup my Pi yet so I don't know if the files are read-write for a group (maybe called gpio) and if the standard user is a member of that group. If not those are very easy to do.

There are other ways of doing GPIO but accessing the files will get you going.
OK, thanks! Can you fill in any more detail on how this works? Specifically, what is going on 'behind the scenes' is a daemon or process looking for changes in a specific file for each GPIO pin that contains commands, data, etc?

Is this what you are referring to? http://www.raspberrypi.org/phpBB3/viewt ... f=9&t=2916 and http://quick2wire.com/2012/05/safe-cont ... pberry-pi/ and more generically, http://www.acmesystems.it/gpio_sysfs
Those are the kind of things I was talking about. The quickwire stuff has code you can easily port to C#.

As for what is going on behind the scenes? Those web links seem to discuss at a very low level. You are either using a pin for output or input. If output you can set the value either high or low. If input you can read the value.

The files are just an exposure of the standard GPIO kernel interface into userland. If you look at /sys/class you will see that linux exposes a lot of low level stuff that way.

emg
Posts: 88
Joined: Wed Jan 11, 2012 11:01 pm

Re: Mono (C#) anyone?

Tue May 29, 2012 10:07 am

andyl, got it. Thanks for the help and pointers, this does look pretty straight forward. Time to learn a little more about linux!

gjs
Posts: 148
Joined: Fri Dec 02, 2011 8:04 pm

Re: Mono (C#) anyone?

Tue May 29, 2012 12:32 pm

Just in case it is not apparent to the OP, you do not need to compile your exe using mono, you can use your exe that was compiled by VS and just run it on the pi by including it as a command line argument to mono i.e. "mono your.exe". Same thing for VB exes after you have installed mono-vbnc on the RPi.

So you can write your app with VS on a PC, transfer the exe to the Pi and run it. This is the scheme I intend to use. It should yield all the productivity of VS and result in a program that can run on the Pi. Utopia!

jools
Posts: 24
Joined: Sun Feb 19, 2012 9:47 pm

Re: Mono (C#) anyone?

Wed May 30, 2012 2:39 am

And indeed you can do this: because I've just been experimenting. It impresses me just how portable these .exe and .dll files are, particularly when rendering forms. In fact I'm impressed with the whole ARM thing (except compile times which are pants of course.) One needs to be a bit careful about writing dedicated apps for the PI I think, because we don't know if the spec will change or indeed it will be usurped by another device such as the VIA board. So programming for the comon language runtime makes sense in my view.

pgix
Posts: 34
Joined: Wed Jan 25, 2012 3:53 pm
Contact: Website

Re: Mono (C#) anyone?

Wed May 30, 2012 11:16 am

Hi,

This may be a daft question, but can you actually run .net MF on the Pi as an alternative to Mono? I just wondered if doing this would give better correlation between how the assembly runs in hardware and how it runs in the VS built-in emulator.

Cheers,
Adam

[edit: apologies for the poor google-fu: http://www.raspberrypi.org/phpBB3/viewt ... ono#p53191]

britguy
Posts: 16
Joined: Mon May 28, 2012 1:34 am

Re: Mono (C#) anyone?

Thu May 31, 2012 4:24 am

OK, so I managed to re-write the Python GPIO stuff into C#, and it works great (I have only tested Outputting to PINs, but Input should work - not sure whether you just get a 1 or a 0 back, or a values inbetween representing different voltages/resistances). I compiled the code as a console application in Visual Studio 2010 on my PC, and simply copied the resultant EXE to the Pi (as suggested by other posters... thanks!), and ran it with the command 'mono filegpio.exe'. I've tried flashing an LED about 50 times a second and the code seems to handle it, not sure how the switching will go because its file based, but its a start! I've also (I think) improved it a bit it so you dont have to setup the pins, you just call OutputPin or InputPin, and you can even switch between input and output on the same pin if your really want to, it will unexport and re-export the pin accordingly.

I am also using the Slice of Pi board that plugs into the GPIO connector, and I've put a little cross ref table in the code comments so you can easily see which pin on the slice of pi to connect your LED or whatever to.

I used a 2.2v green LED (20ma current), wired in series with 60ohms resistance (to bring the voltage down from 3.3v that the PI outputs), with the anode (long leg) connected to the GPIO pin, and the cathode (short leg) connected to the resistors and them in turn connected to the GND pin.

Finally, I have tested this on my own Pi and it works great, however as with all electronics, one slight touch of the wrong wires and you could toast your Pi, so be very careful. As a result this code is used at entirely your own risk!

So heres the c# code... enjoy! Let me know if you find it useful and what you end up using it for? 8-)

Code: Select all

using System;
using System.Collections.Generic; //required for List<>
using System.IO;

namespace FileGPIO
{
    public class FileGPIO
    {  
        //GPIO connector on the Pi (P1) (as found next to the yellow RCA video socket on the Rpi circuit board)
        //P1-01 = top left,    P1-02 = top right
        //P1-25 = bottom left, P1-26 = bottom right
        //pi connector P1 pin     = GPIOnum = slice of pi v1.0 board label
        //                  P1-07 = GPIO4   = GP7
        //                  P1-11 = GPIO17  = GP0
        //                  P1-12 = GPIO18  = GP1
        //                  P1-13 = GPIO21  = GP2
        //                  P1-15 = GPIO22  = GP3
        //                  P1-16 = GPIO23  = GP4
        //                  P1-18 = GPIO24  = GP5
        //                  P1-22 = GPIO25  = GP6
        //So to turn on Pin7 on the GPIO connector, pass in enumGPIOPIN.gpio4 as the pin parameter
        public enum enumPIN { gpio0 = 0, gpio1 = 1, gpio4 = 4, gpio7 = 7, gpio8 = 8, gpio9 = 9, gpio10 = 10, gpio11 = 11, 
            gpio14 = 14, gpio15 = 15, gpio17 = 17, gpio18 = 18, gpio21 = 21, gpio22 = 22, gpio23 = 23, gpio24 = 24, gpio25 = 25 };

        public enum enumDirection { IN, OUT };

        private const string GPIO_PATH ="/sys/class/gpio/";

        //contains list of pins exported with an OUT direction
        List<enumPIN> _OutExported = new List<enumPIN>();

        //contains list of pins exported with an IN direction
        List<enumPIN> _InExported = new List<enumPIN>(); 

		//set to true to write whats happening to the screen
        private const bool DEBUG = true; 

        //this gets called automatically when we try and output to, or input from, a pin
        private void SetupPin(enumPIN pin, enumDirection direction)
        {
	        //unexport if it we're using it already
            if (_OutExported.Contains(pin) || _InExported.Contains(pin)) UnexportPin(pin);

	        //export
            File.WriteAllText(GPIO_PATH + "export", GetPinNumber(pin));

            if (DEBUG) Console.WriteLine("exporting pin " + pin + " as " + direction);

            // set i/o direction
            File.WriteAllText(GPIO_PATH + pin.ToString() + "/direction", direction.ToString().ToLower());

            //record the fact that we've setup that pin
            if (direction == enumDirection.OUT)
                _OutExported.Add(pin);
            else
                _InExported.Add(pin);
        }

        //no need to setup pin this is done for you
        public void OutputPin(enumPIN pin, bool value)
        {
            //if we havent used the pin before,  or if we used it as an input before, set it up
            if (!_OutExported.Contains(pin) || _InExported.Contains(pin)) SetupPin(pin, enumDirection.OUT);

            string writeValue = "0";
            if (value) writeValue = "1";
            File.WriteAllText(GPIO_PATH + pin.ToString() + "/value", writeValue);

            if (DEBUG) Console.WriteLine("output to pin " + pin + ", value was " + value);
        }

        //no need to setup pin this is done for you
        public bool InputPin(enumPIN pin)
        {
            bool returnValue = false;

            //if we havent used the pin before, or if we used it as an output before, set it up
            if (!_InExported.Contains(pin) || _OutExported.Contains(pin) ) SetupPin(pin, enumDirection.IN);
         
            string filename = GPIO_PATH + pin.ToString() + "/value";
            if (File.Exists(filename))
            {
                string readValue = File.ReadAllText(filename);
                if (readValue != null && readValue.Length > 0 && readValue[0] == '1') returnValue = true;
            }
            else
                throw new Exception(string.Format("Cannot read from {0}. File does not exist", pin));

            if (DEBUG) Console.WriteLine("input from pin " + pin + ", value was " + returnValue);

            return returnValue;
        }

        //if for any reason you want to unexport a particular pin use this, otherwise just call CleanUpAllPins when you're done
        public void UnexportPin(enumPIN pin)
        {
            bool found = false;
            if (_OutExported.Contains(pin))
            {
                found = true;
                _OutExported.Remove(pin);
            }
            if (_InExported.Contains(pin))
            {
                found = true;
                _InExported.Remove(pin);
            }

            if (found)
            {
                File.WriteAllText(GPIO_PATH + "unexport", GetPinNumber(pin));
                if (DEBUG) Console.WriteLine("unexporting  pin " + pin);
            }
        }

        public void CleanUpAllPins()
        {
            for (int p = _OutExported.Count - 1; p >= 0; p--) UnexportPin(_OutExported[p]); //unexport in reverse order
            for (int p = _InExported.Count - 1; p >= 0; p--) UnexportPin(_InExported[p]);
        }
        
        private string GetPinNumber(enumPIN pin)
        {
            return ((int) pin).ToString() ; //e.g. returns 17 for enum value of gpio17
        }

    }

}
Then to call it, heres what's in my program.cs file that actually executes when the app runs - feel free to modify, you get the gist..

Code: Select all

using System;
using System.Threading;

namespace FileGPIO
{
    class Program
    {
        static void Main(string[] args)
        {
            FileGPIO gpio = new FileGPIO();
            for (int i = 0; i < flashes; i++) //flash pin 17, 5 times on & off (1 second each)
            {
				//NO NEED TO SETUP OR INITIALIZE THE PINS, THATS ALL DONE FOR YOU, JUST USE OUTPUTPIN or INPUTPIN, AND USE CLEANUPALLPINS AT THE END!
                gpio.OutputPin(FileGPIO.enumPIN.gpio17, true);
                Thread.Sleep(1000);
                gpio.OutputPin(FileGPIO.enumPIN.gpio17, false);
                Thread.Sleep(1000);
            }
            //Console.WriteLine( "Value of pin 18 is " + gpio.InputPin(FileGPIO.enumPIN.gpio18) ); //UNTESTED!
            gpio.CleanUpAllPins();
        }
    }
}

akilhoffer
Posts: 2
Joined: Tue Jun 05, 2012 3:47 am

Re: Mono (C#) anyone?

Tue Jun 05, 2012 3:50 am

Great job! You should start a project on GitHub, CodePlex, or Google code for this C# port. I'm sure a lot of people will find it useful.

akilhoffer
Posts: 2
Joined: Tue Jun 05, 2012 3:47 am

Re: Mono (C#) anyone?

Tue Jun 05, 2012 3:51 am

I think that's a very fair question. The .Net MF runs on ARM processors already. Why can't it run on the Pi? I see no reason offhand why not.

godFather89
Posts: 150
Joined: Fri May 18, 2012 9:40 am
Location: Timisoara, RO

Re: Mono (C#) anyone?

Tue Jun 05, 2012 6:54 am

Just a note: FileGPIO should be implemented as static class or a singleton because there is no need to make multiple instances to read/write from/to a I/O pin.

User avatar
melikescheese
Posts: 16
Joined: Sat Mar 03, 2012 1:06 pm
Contact: Website

Re: Mono (C#) anyone?

Wed Jun 06, 2012 9:51 am

Personally I can only deal with three/four languages:

C# (versatile and works brilliantly to develop games, winforms, apps and OS with COSMOS), PHP (fast server side scripting syntax similar to C#),VB.net (my first language) and HTML (CSS) (useful for use with web scripting)

Heck i'm only 13 but python confuses me and i'd love to use my pi to program in C#. Especially some GUI applications. But I have some really basic questions.

+ Can I use Geany to do C#
+ What extra packages would I need to install on debian to use C#
+ How would I compile and run the applications
+ Is there an IDE for mono?

x4m
Posts: 10
Joined: Wed Jun 06, 2012 4:57 pm
Location: Yekaterinburg, Russia
Contact: ICQ

Re: Mono (C#) anyone?

Wed Jun 06, 2012 5:01 pm

britguy wrote: GPIO
Hello!
I have just refactored a bit to common C# style your code. I'd be happy if could take a look at it.
https://dl.dropbox.com/u/7610280/GPIO.cs
If you suppose it is right direction for your code to evolve, I think next step would be cache opened files to reduce CPU usage for GPIO bit manipulations.

Best, Andrew.

x4m
Posts: 10
Joined: Wed Jun 06, 2012 4:57 pm
Location: Yekaterinburg, Russia
Contact: ICQ

Re: Mono (C#) anyone?

Thu Jun 07, 2012 5:35 am

Expored this article http://elinux.org/Rpi_Low-level_peripherals, watched a bit through C example and... well, I think it'd be better to port that tricks with memory mapped files on C#.
First thing I'm going to do is to control stepping motors via gpio. I think it's wrong to open and close file every single motor step. I think it's not good even to use formatted file output.

But most dangerous are memory allocative operations (like concatenating strings), because they can trigger unexpectedly long garbage collection un motors will fall out of syncronize if 5-15 steps are missed out...

x4m
Posts: 10
Joined: Wed Jun 06, 2012 4:57 pm
Location: Yekaterinburg, Russia
Contact: ICQ

Re: Mono (C#) anyone?

Thu Jun 07, 2012 11:23 am

I'm trying to port C program to C#.

https://dl.dropbox.com/u/7610280/GpioProgram.cs

Everything now compiles but should not work.
There are several constants which I can't lookup.

Code: Select all

        //TODO: Find constants for libc open
        private static int O_RDWR;
        private static int O_SYNC;

        //TODO: Find constants for mmap
        private static int PROT_READ;
        private static int PROT_WRITE;
        private static int MAP_SHARED;
        private static int MAP_FIXED;
Can anyone help me setting this consts and testing program?

godFather89
Posts: 150
Joined: Fri May 18, 2012 9:40 am
Location: Timisoara, RO

Re: Mono (C#) anyone?

Thu Jun 07, 2012 12:24 pm

Code: Select all

#define PROT_READ	0x1		/* page can be read */
#define PROT_WRITE	0x2		/* page can be written */
#define PROT_EXEC	0x4		/* page can be executed */
#define PROT_NONE	0x0		/* page can not be accessed */

#define O_RDWR		    02
#define O_SYNC		 010000

x4m
Posts: 10
Joined: Wed Jun 06, 2012 4:57 pm
Location: Yekaterinburg, Russia
Contact: ICQ

Re: Mono (C#) anyone?

Thu Jun 07, 2012 12:56 pm

godFather89 wrote:

Code: Select all

#define ...
Big thanks!
Seems like you missed MAP_SHARED && MAP_FIXED consts, I need them too.

godFather89
Posts: 150
Joined: Fri May 18, 2012 9:40 am
Location: Timisoara, RO

Re: Mono (C#) anyone?

Thu Jun 07, 2012 1:02 pm

Sure, here you go:

Code: Select all

#define MAP_SHARED	0x01		/* Share changes */
#define MAP_PRIVATE	0x02		/* Changes are private */
#define MAP_TYPE	0x0f		/* Mask for type of mapping */
#define MAP_FIXED	0x10		/* Interpret addr exactly */
#define MAP_ANONYMOUS	0x20		/* don't use a file */

x4m
Posts: 10
Joined: Wed Jun 06, 2012 4:57 pm
Location: Yekaterinburg, Russia
Contact: ICQ

Re: Mono (C#) anyone?

Thu Jun 07, 2012 5:10 pm

Once more thx to godFather89.
Installed mono runtime, tried to run monodevelop...well RPi is not enough fast (:

Also tried to run gpio ported program and encountereg with absance of "libc.so"... I do not even know where to look for libc.so ..

Return to “Other programming languages”