comments 4

.NET and Raspberry Pi

In the previous post, I looked at getting VS Code setup so we could build and run programs in C#. In this one, we’ll look at deploying to a Raspberry Pi after we’ve tested them. I have a spare Raspberry Pi 3B+ that I want to try running .NET code on.

I used the Raspberry Pi Imager to install Raspberry Pi OS Lite (no desktop environment). There are many images available for download, so if you want a full desktop or different Linux distro, there are others to choose from. I might write another post in the future about setting up Fedora instead.

The first boot will resize the partition to fill the entire SD card then reboot. Once you see raspberrypi login: prompt, you can login as the pi user with default password raspberry. First thing you must do is change your password using the passwd command. Log out then back in again to make sure the new password works.

Next, I enable SSH logins so I can connect remotely from my laptop. We also need to get the current IP address:

$ sudo systemctl start ssh
$ ip -4 addr
1: lo: ...
    inet 127.0.0.1/8 ...
2: eth0: ...
    inet 192.168.1.174/24 ...

Try connecting from another machine and use the same pi user to login:

login as: pi
pi@192.168.1.174's password:
Linux raspberry pi 5.4.83-v7+ #1379 SMP Mon Dec 14 13:08:57 GMT 2020 armv71

pi@raspberrypi:~ $

Now that we’ve successfully connected remotely, I’ll enable SSH automatically at boot:


$ sudo systemctl enable ssh
Synchronizing state of ssh.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install enable ssh
Created symlink /etc/systemd/system/sshd.service → /lib/systemd/system/ssh.service.
Created symlink /etc/systemd/system/multi-user.target.wants/ssh.service → /lib/systemd/system/ssh.service.

You should also run raspi-config and setup localization correctly. Your Pi will reboot and then we should be ready to start installing the necessary software.

Getting .NET onto the Pi

Another reason I picked the Lite OS version is that a minimal number of packages are installed, so doing system updates should go faster. Go ahead and run:

$ sudo apt update
$ sudo apt full-upgrade
$ sudo apt autoremove

apt should let you know if a reboot is required.

Unfortunately, we can’t use apt to install .NET, but Microsoft provides a few ways of getting it. Probably the easiest way on the Raspberry Pi is to manually install it. Download the binary package using wget:

$ wget https://download.visualstudio.microsoft.com/download/pr/1958def3-0dac-4243-8fb9-e906a7f14509/93af2ac9a973d60c7d2ebd168d752a92/dotnet-sdk-5.0.201-linux-arm.tar.gz

Create a directory for .NET to live and unpack the tar file there:

$ mkdir -p ~/dotnet
$ tar xvf dotnet-sdk-5.0.201-linux-arm.tar.gz -C ~/dotnet

We also need to add the dotnet directory to our path so the tools work correctly. Add this to the end of ~/.profile:

if [ -d "$HOME/dotnet" ] ; then
    PATH="$HOME/dotnet:$PATH"
fi

export DOTNET_ROOT="$HOME/dotnet"

Log out then back in and you should be able to run:

$ dotnet --list-sdks
5.0.201 [/home/pi/dotnet/sdk]

Hello Pi

Lets create a new Hello World app again so we can make sure that building and running .NET programs works as expected. Run this in your home directory:

$ dotnet new console -o HelloPi

Change into the HelloPi directory and run:

$ cd HelloPi
$ dotnet run
Hello World!

You could also do something a little more microcontroller-ish like blink an LED:

Remote Development on the Pi

If we wanted, we could do all our development on the Pi. Maybe go back and install a full desktop environment. Unfortunately, the Pi 3B+ only has 1GB of memory and when it starts swapping, it’s frustrating to use. One thing we can try doing is remote development. You’ll need to install the “Remote Development” extension in VS Code to try this.

You also need to make sure you have an SSH client installed. You can test this from Terminal by typing:

$ ssh pi@192.168.1.174
pi@192.168.1.174's password:
Linux raspberrypi 5.10.17-v7+ #1403 SMP Mon Feb 22 11:29:51 GMT 2021 armv71

pi@raspberrypi:~ $

Open the command palette (F1) and type remote ssh. Select Remote-SSH: Connect to Host… from the list. You’ll be prompted to enter a username and host you’d like to connect to. For example, I used pi@192.168.1.174, same as I typed into the Terminal. VS Code will try to connect to your Raspberry Pi and install the VS Code Server. Once it connects, you’ll get a new window showing you’re remotely connected:

In the Terminal window, type:

$ dotnet new console -o HttpHello

Now File > Open Folder will browse folders on the Raspberry Pi. Select the /home/pi/HttpHello folder we just created. You’ll have to enter the pi user’s password again. If we create SSH keys, we can avoid having to retype the password every time.

At this time, it isn’t possible to run the debugger natively in VS Code on an ARM device like the Raspberry Pi. There are workarounds to this, but for now we can try remote debugging instead.

You’ll need to go back to editing the local version of HttpHello on your laptop (no more remote editing). In a Terminal window, run:

$ dotnet publish

This will create a published version of your app that you can deploy. Copy the contents of this folder over to the Raspberry Pi (I saved it into /home/pi/HttpHello). Now you can go to the Run > Add Configuration menu to add a new .NET Launch a Remote Console App configuration. I’m using this example, modified for where I saved my program:

"configurations": [
    {
        "name": ".NET Core Launch (remote console)",
        "type": "coreclr",
        "request": "launch",
        "preLaunchTask": "build",
        "program": "/home/pi/dotnet/dotnet",
        "args": ["/home/pi/HttpHello/HttpHello.dll"],
        "cwd": "/home/pi/HttpHello",
        "stopAtEntry": false,
        "console": "internalConsole",
        "pipeTransport": {
            "pipeCwd": "${workspaceFolder}",
            "pipeProgram": "C:\\Program Files\\PuTTY\\PLINK.EXE",
            "pipeArgs": [
                "-pw",
                "<password>",
                "pi@raspberrypi"
            ],
            "debuggerPath": "/home/pi/vsdbg/vsdbg"
        }
    }
]

Now when you run your program (F5), it will actually run on the Raspberry Pi and connect to the debugger there. Here you can see a breakpoint reached when debugging remotely on the Raspberry Pi:

In the Future

I’m hoping it becomes easier to remotely develop and debug a program on a Raspberry Pi. Everything is so close at the moment, but the ARMv7 support just isn’t quite there yet. So for now, I think I’ll do most of my development and testing on my Windows machine, then copy the published folder over to the Raspberry Pi when I need to. Then I can debug the running program there if necessary.

4 Comments

  1. Jack_Zhou

    hi!kiel:
    on respberrypi you can use winiot system use wpf to control,it’s easy to learn and develop

    Like

    • Hi Jack! I started out with a Windows 10 IoT image because I wanted to try something as close to Crestron 3-series as possible but ran into a couple problems:
      – The boot time took forever and sometimes failed to boot entirely
      – Windows wouldn’t recognize the Ethernet adapter on my Pi 3B+

      I do have another Pi 3B+ to try it on, but I started to feel like I was spending more time troubleshooting Windows than doing anything with .NET. So I switched to Raspbian to get up and running faster. I would like to try Windows 10 IoT again sometime. I’ve used it on an Intel NUC but that’s hardly a $35 computer. 🙂

      Like

  2. Jack_Zhou

    hi!kiel:
    how a bout learn homeassistant? in this project,it can control crestron,use cip protocol.i’m now learn it components develop

    Like

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s