0:03
So this session is all about driving a robot arm with a Raspberry Pi and .NET and Blazor
0:09
and SignalR and then some other bits that we'll talk about later
0:14
And this is a bit of fun in a way, but actually there's some good applications for this sort
0:19
of tech. So it's good to go through this sort of stuff
0:25
Before I get going with that, a little bit about me. So I'm a freelance software developer
0:31
I tend to concentrate in the IoT space mainly, although I'll do pretty much anything
0:36
people will pay me to do at the moment, just like any good consultant
0:40
But I'm also an Azure MVP and a Pluralsight author, where I author content around IoT at the moment
0:47
specifically the AZ220 developer certification. So go and check that out if you like
0:54
I also co-organized .NET Notts, and I organized NotSciOT, two now virtual meetup groups, and I talk about stuff like this on a regular
1:05
basis. I've also got two little girls at home, so being a STEM ambassador is quite important to me
1:11
so that I can democratize the information and the resources out there for people
1:17
So, yeah, that's what drives me on. So, going forwards, we'll start a little bit of groundwork
1:24
just around what .NET is and then how you get .NET 5 installed on a Pi
1:29
And then we'll do a couple of Hello World projects. There's always Hello World in IoT, so we'll start there
1:35
And then we'll talk a little bit about GPIO and the circuit
1:39
and how we control GPIO. And then we'll talk about device bindings
1:43
and how we can drive servos with that. And then we'll move up to controlling things
1:48
with a Blazor and SignalR application. And then actually, there's more than one final demo
1:53
and then we'll do some Q&A at the end. So really briefly about .NET 5
1:59
it's cross-platform open source and we can target pretty much anything we like
2:05
from desktop all the way through to AI and you can see there second from the right
2:09
we've got IoT quite nicely. There's a bunch of new stuff in .NET 5 specifically
2:15
I could have done this with .NET Core but I wanted to use the latest tech
2:19
In fact, I probably could be using .NET 6 now as well
2:23
But, you know, all of this demo is all written. It works all fine in .NET 5
2:27
So we'll start there. We get some nice stuff with .NET 5, though
2:31
We get things like records, which is quite nice. We also get init-only properties
2:36
So we go from something like that down to something like this on a couple of lines
2:40
Pattern matching on types, which is a pretty cool thing to be able to do. top-level programs where we go from not very many lines of code down to just two for a simple
2:51
program. And I think this is quite important for people just starting out in the language where
2:55
it just removes some of the cruft of our basic application. We also get system.txt.json
3:01
so a new JSON library. So James Newton King's json.net library that disappears and we use this
3:08
which makes him a bit sad. But it's all right. They gave him a job at Microsoft, so he's fine
3:13
There's quite a lot of words on this block of data here, but the one that I like actually is the bottom right hand corner where 40% of new .NET programmers are students, which speaks to me
3:25
I think this is great, where normally we'd have people doing Python or even C++, but this shows that .NET's filtering into the education system, which is only going to be a good thing
3:37
The more .NET developers we can get, the better, really. So, getting this fantastic .NET on a Raspberry Pi is usually quite difficult, many steps
3:48
And if you're not particularly familiar with Linux, then some of that can be a little bit onerous
3:55
So, I created a single line install script that makes life a lot easier
4:00
So we just run this single line here, and it installs all of the prerequisites to get
4:04
.NET installed. The only thing we need to do is reboot the pie at the end
4:09
and we get .NET installed. So you can see with the GIF there
4:12
there's a fair few steps that we've got to go through to get this up and running
4:16
But you run that single line, and you're off and running. You can do a .NET dash dash info
4:20
and you're off and running at the end. So normally, I'd spin up just a basic console app
4:26
at this point in time. But we've only got, I don't know, 45 minutes left
4:30
of the session. So I'm going to skip just doing a console app. Most of us have seen a .NET new console app before, and it doesn't really tell us a great deal
4:38
But what I do want to do is talk about the GPIO on the Raspberry Pi
4:43
So if you don't know what GPIO is, that's general purpose input output, and that's all the pins down the side of the Raspberry Pi that help us drive things like basic I.O
4:52
for turning LEDs on and off or reading buttons, but also serial interfaces like SPI and I2C
4:59
and also PWM for driving things like servos. And this library that I've mentioned at the top, system.device.gpio, is what we use
5:10
So a NuGet package that we can pull in. And that gives us the control over the GPIO, which is fantastic
5:16
It actually runs on other boards. So BeagleBoard, HummingBoard, NoDroid, if you're interested in those boards
5:22
But I'm a Raspberry Pi guy. I tend to stick with that board
5:26
So you'll see me in and around that space. Interestingly, it also supports Windows 10 IoT, if you've had a play with that
5:32
I don't tend to use that at all anymore. I'm not sure it's particularly well supported anymore
5:38
So I tend to just stick with Linux. And we can install it with the CLI or the PM, you know, if you're in full Visual Studio
5:45
A little bit more about GPIO. So again, this is the set of pins down the side of the Raspberry Pi
5:50
And each of these pins is numbered. So we've got a board numbering scheme
5:55
And that's this set of numbers closest to the pins. and I tend to stick to this because I can count the pins where pin one is that square pin at the
6:03
top left hand corner it's just the pad that's square this the pin itself is round next to that
6:08
we've got pin two and below it pin three and four and onwards like that so it's quite a logical pin
6:13
numbering scheme once you know that you've got two rows and they go opposite each other there is a
6:18
BCM numbering scheme that you can see here as well and that's referencing the BCM chip that drives
6:23
the GPIO on the Raspberry Pi. I don't tend to use this numbering scheme because now I've got to
6:28
convert from that BCM number to an actual PIN number. So it's just an added step. But it's
6:33
important to know this because when we start looking at the .NET code, there's two different
6:37
ways that we can reference the numbers. So this is where that comes from. I've got a really basic
6:44
circuit set up. Now, if you've ever done any IoT, which I'm guessing you will have done
6:48
then driving an LED and reading a button are what we'd call Hello World in IoT
6:55
And we do that with every project that we do in IoT
7:00
The first thing is we've got a flash and LED. And the next thing we do, we can read a button
7:03
So, of course, we do this. But it's actually quite a valuable thing to see how that works in .NET
7:10
You can see here, if I zoom in a little bit, we've got on pin 10 in the board numbering scheme
7:16
I've got one side of a resistor. and the other side goes down to ground through the LED
7:22
And on pin 26 I got one side of a button and then the other side goes back down to ground And I come back to the circuit diagram again because it time to have a quick look at some demo code again the Hello World demo code
7:38
So if I switch across here, I've got some code that I've spun up now. I'm not going to do any
7:42
live coding. The most I'm going to do is copy and paste an address later. I've got this all set up
7:48
and there's a link to all of this. This is a GitHub repository, and I've got a bunch of branches
7:52
in here and i'm just going to uh navigate my way through these branches and show you how we can
7:57
build up the solution so this piece of code and i think that should be zoomed in uh far enough for
8:04
most people um right at the very top here we're using the system.device.gpio nuGet package
8:09
as i mentioned before so this is what we're going to be driving our gpio with
8:13
so a little bit further down on line 12 here i've got a hello world now i tend to do this i leave
8:20
that hello world in there because if and you'll see in the next demo if all you're going to do is
8:24
read a button you're not sure when that application has actually started so you can be pressed at the
8:28
button it's not doing anything and you don't know what is happening so leave that in there and you
8:33
at least know that something's happened it's started it's ready below that we've got a gpio
8:38
controller that we're creating and we can see here that we're passing in a pin numbering scheme of
8:43
board so we could pass in that bcm numbering scheme if we wanted to here just stick to board
8:48
and everything will be nice and easy. But this controller that we're creating from this GPIO controller
8:53
this is what's going to be doing the heavy lifting of most of what we're going to be looking at today
8:59
Below that, I've got a couple of variables. So if you remember, I've got my one side of that LED
9:05
If I go back here and look at the circuit, it's connected to pin 10. So I'm just defining that here as a variable because then we can just use it
9:12
and change it should we wish to. Next I'm creating a variable for our light time as it's called and this is
9:18
just going to be used for our delay down here. We're going to turn an LED on and
9:23
then wait and then turn it back off again and then wait and then go around that loop. Next thing we do here is we take that controller that we created
9:31
earlier and we open our pin 10 and we open it as an output because we're going
9:35
to drive the LED. So that's pretty straightforward. And then here in that
9:40
try catch we've got a while loop so just forever we're going to write to pin 10 as it is that we've
9:47
defined above a value of high and then we're going to wait for 300 milliseconds and then we're going
9:52
to drive a value of low and then wait for three milliseconds and just go around in a loop so it's
9:57
pretty straightforward we just write a high and a low and that turns the led on and off and i've
10:02
dialed into my pi with putty here and i'm in the right directory and so i can do a dot net new
10:07
in here, and that'll run that code up. But what I've also got is a video stream of the robot
10:15
If I just maximize that, then we can see the LED flashing. This is always a good point because that means my first demo has worked
10:22
which is a bonus. I should just stop now, but that would be boring
10:27
So we can see that's just an LED flashing on and off. But actually, that shows us now we have not only do we have .NET installed
10:34
and running properly, but also we've got control over that GPIO. So we're well on our way now at this point
10:40
So if I just go back to this and make sure I stop it because I've got a habit of leaving that running
10:46
If I then get the code back up again, we can go to the next part
10:50
So we know we can drive out, but now we need to make sure that we can read back in again
10:54
So I can switch to my read button branch, and that will switch the code out
10:59
Sometimes that does this automatically for me, and sometimes it doesn't. Today, it has. Everything in this code is identical at the top here
11:06
so I'm still using the GPIO package. I'm still creating a controller
11:10
but I've got an extra button pin variable on 26. And if you remember from the circuit diagram there
11:16
we've got pin 26 connected to one side of that button. Now, if you look, what I don't have is anything on that button
11:23
that's keeping that at a particular level. Now, if you know anything about electronics and how the Pi works
11:28
these outputs are open collector outputs. so they float normally if you don't do anything with them they'll just sit there doing nothing
11:36
now the way i've got this uh button connected is that when i press it it's going to connect
11:42
that pin to ground which is great when it's pressed because it's definitely going to ground
11:46
but if you don't connect it to ground um or something else on the other side a high level
11:51
then it'll just float and it might work or it might not work so normally what you'd see is
11:55
you'd have a resistor like the led resistor there that would be pulling that line up to a high level
12:01
but we can actually do that internally in the Pi. So here we've got the normal pin mode output for the LED
12:08
but here we're passing in our button pin, we're opening that, and we're using input pull-up
12:14
So inside the Pi, there's got a bunch of little tiny resistors
12:18
that you can assign to pull that pin up internally. So it means we don't need that extra resistor in our circuit
12:25
We can just tell the Pi that when it's an input that it's a pull-up
12:28
and you can do a pull-down as well if you want. but the way I've done it is with a pull-up
12:33
But what's interesting about this is it makes the logic a little bit backwards that we'll see here in a second
12:38
So we see here on line 25 that we read the button pin
12:42
and if the button pin is false, then we turn the LED on
12:46
So it seems a bit backwards but when we're pressing that button, don't forget
12:51
it's going to connect that pin down to ground. So it's going to be low while we're pressing it
12:55
which means while we're pressing it, we're going to read a false
12:59
and that's when we want to turn the LED on. So that might seem a bit backwards here
13:02
but that's the reasoning behind that. And if we don't press it, then we get a low
13:07
So we can run that one up as well. Just .NET Run. And if everything works correctly, just here
13:17
When it's finished, you'll see that LED actually turn off. There we are, so it's turned off
13:23
And we've got Hello World here as well, so we know that it's actually done something. but if i press my button now then we see we've got probably you know a very expensive way of
13:33
connecting an led to a button uh but obviously what we've proven now is that we've got not only
13:38
output control but we can also read inputs through gpio and obviously at that point you the the
13:44
world's your oyster you can you can go off and do a whole heap of stuff because we know we've got
13:48
that level of control but obviously we don't want to stop there that would also be boring
13:54
So I make sure that we stop this. Now, normally what I'd do at this point is I would go through a whole heap of different parts to this particular demo
14:05
But where have we? We've got, I don't know, about half an hour left. So we've still got enough time
14:10
But I'm going to skip to the finished code to drive the robot, and I'm going to explain how that works
14:18
So if I skip to main here, and then I'm going to explain a little bit about how this is going to work in just a second
14:27
So that's that updated. Now, I'm going to talk about PWM. So while that's doing that, let's go through and have a look
14:38
So PWM is great, and it's built into the system.device.gpio NuGet package
14:45
we get PWM control directly in that. And PWM is pulse width modulation
14:50
And I'll go into a bit more detail directly about PWM in a couple of slides time
14:54
But PWM is what we using to drive our servos with Now it great with PWM and we can do all of that if we like but actually servo control is a little bit more complicated
15:05
than just having a handle on PWM. So we can pull in another NuGet package
15:11
called the IoT device bindings NuGet package, and that is a whole heap of somebody else's code
15:17
And they've written a bunch of code that leverages .NET to be able to control other peripherals
15:23
So you can take it and control a BME280 pressure sensor or IO expanders or the Explorer hat or the Sense hat
15:31
If you've not heard of the Sense hat, then there's a couple of Raspberry Pis up on the space station that Tim Peake's mission took up with him
15:38
And children can run experiments on those Raspberry Pis. And the Sense hat, the hardware attached on top, hat stands for, is a little board that's plugged into these Raspberry Pis
15:49
And they've got a display and a couple of buttons and a magnetometer and a gyroscope
15:53
and temperature and humidity sensing and things like that. And there's code written for us to be able to control that with .NET as well
16:01
But specifically why I'm pulling this in is so that we can have some better servo control
16:07
Now, before I talk about PWM, we need to talk about the circuit that I've got to be able to control the robot
16:13
So this is the overall circuit. Now, I've used in the middle of the diagram there, I've used this board called a Servo 6 control board
16:23
Now, there's a load of different ways we could be doing this. We could actually buy a serially controlled PWM controlling board
16:30
and this would handle all this for us. But I wanted to use that device bindings library
16:35
because it offers so much scope for people to be able to go then
16:39
and make solutions using .NET. I didn't want to shortcut it with a board
16:45
So I'm driving the servos, as they are little motors, directly from the Raspberry Pi
16:53
but you can't power them directly from the Raspberry Pi. That's a bit of a problem
16:57
The Raspberry Pi's GPIO pins can only tolerate about 30 milliamps of current draw
17:03
and a servo could take easily 300 on startup or if it gets a lot of load attached to it
17:10
So this servo 6 board, as you can see from the full diagram
17:15
it has a battery pack attached to it, which I always hope doesn't run out of batteries
17:19
part way through one of my demos. I'm sure it'll be fine. But what you can do then is you can just pass the control signals
17:26
from the Raspberry Pi into the board, and then they get passed through as well as the power
17:33
So it keeps all the powers separate, which is fantastic. It's definitely the way you need to do it
17:38
So I've got here for zoom in a little bit more. On pin 25, that's ground
17:43
Now, I'm not a big fan of the numbering layout of the labels on there
17:48
So that confused me a little bit because I missed where ground was. That first pin is ground
17:53
Onwards from that are the channels for the PWM that we're going to be using
17:57
So here on pin 35, I've got that connected to PWM channel 1
18:01
And then on pin 13, I've got that connected to PWM channel number 2
18:06
Now, there are only two what's called hardware PWM channels on the Raspberry Pi
18:11
Hardware PWM channels, you just tell it what to do and the underlying system will handle how to do that, the Raspberry Pi itself
18:20
I've actually connected a third pin here, which we can control with software
18:24
and I'll come back to that in a second. But there's a differentiation there
18:30
It's just an important one. Down at the bottom, there's not much to worry about
18:34
but most servos will have a yellow or an orange wire that's the control wire
18:39
and then you'll either have red and black or red and brown, depending on what you've got for the power and for the ground
18:46
So it's very difficult to see, but there's a little C on this board that you can see
18:51
and that's where you connect the yellow or orange wire to to control your servos. So control power and ground
18:57
So PWM. So we send out a bunch of pulses to the servo
19:03
This is where the pulse width modulation comes in, and the width of those pulses determines where the servo goes
19:08
So if we send short pulses like this, then we get the servo going in one direction
19:14
If we send middle-sized pulses, then we get the servo going towards the middle
19:18
And then if we send longer pulses, then we get the servo going to the other side. Now, this is a simplistic view of how this works
19:25
But that is the basic idea. So pulse width modulation. There's also a few other things that come into it, but that's kind of the main thing
19:34
Now, I'd normally do a full servo demo at this point. But again, we're going to run out of time if I do all of the demos
19:41
But what I can do is I can flick over to the code and show you how that part's working
19:45
So if I go back to the code here, I'm pulling in system.device.pwm
19:51
So instead of GPIO, PWM. So that gives us control over PWM and the drivers
19:56
But I've also got this iot.device.servo motor that I'm pulling in. And that's coming from the device bindings
20:03
And then we'll come back to SignalR in a little minute. So down here I'm creating two PWM channels that the code is almost identical
20:13
but we have PWM channel dot create and we pass in three variables into that one
20:18
of them is the chip number there's only one chip on the Raspberry Pi so that stays at zero starts at zero and then we have the channel number and there's only
20:27
two hardware channels so zero and one and then we also have a frequency there
20:31
that I just left as it is how it just works so that part there that's coming
20:36
from our system.device NuGet package. And then here we have servo motor
20:42
and this is coming from the device bindings. And we pass in a PWM channel into that
20:47
and then we tell it the maximum rotation of a servo. So there's two different types, 180 degrees or 360 degree servos
20:56
And that's entirely up to you which one you choose. But for this robot arm, I'm using 180 degree ones
21:04
Then the next few parts here are a minimum and a maximum pulse width
21:09
And depending on which servos you buy, you might need to fiddle with all three of these numbers here
21:14
this 50, the 700, and the 2400, depending on the calibration of the servos
21:20
I'm just using some dead cheap, I think, S390s. You could probably buy a pack of 10 for about two quid
21:27
They are really cheap, and just do the job for this. So I'm doing that twice
21:31
So I've got the two hardware PWM channels, but I'm also creating a software PWM channel
21:38
So it's almost exactly the same, but this is coming again from the device bindings library
21:44
So somebody has written some code here to do that pulse width modulation in code
21:50
Now, normally, if you would do that, it wouldn't work very well because this part is now going to sit on top of the operating system
21:56
And operating systems are generally not very good, certainly not high level ones like Linux
22:01
timing not this sort of acute timing but if you pass in a true at the end of that
22:07
then it puts it in a high precision mode dedicates more system resources but it
22:12
makes it work really well so you just need to pass it in a pin number and
22:16
that's pin 27 and if you remember from our circuit diagram there if it let me
22:20
do it then all the way back here go too far back now then actually I think I I labeled that incorrectly That should be pin 27 But either way that what we doing there is passing in that pin number
22:35
And then after that, it's exactly the same process. So we've got PWM channel 3, which is what we're creating here
22:41
and then the maximum angle, and then these two numbers, which I just fettled with a little bit
22:46
to get it to work a bit better. And then next, we just start the servo motors up
22:50
And then there's some stuff that we'll talk about after we've talked about Blazor and SignalR
22:55
And then at the bottom here, I've just got a little routine that allows me to be able to move a servo to an angle
23:01
So we have a servo.rightangle. And that's as much code as we need to drive servos
23:06
This would be more difficult if we did it ourselves. So device bindings are great for this sort of stuff
23:12
So if we move on a little bit past all that, we need to talk a little bit about Blazor and SignalR
23:19
Now, the demo that I would have given if we'd had loads of time, that just moves my servos nicely for me
23:25
in a little dancing motion. And it's great. But you have no control at that point
23:31
Now, I've got .NET code here. Now, traditional .NET code is going to be a console application
23:38
You can't create, theoretically, a WPF application and put that on your Raspberry Pi to control it
23:44
because the W part of WPF stands for Windows Presentation Foundation. And we're going to be running on Linux
23:49
and I didn't want to control the robot arm from the terminal. It just wasn't very good
23:54
So actually, this part of the demo came from the fact that I wanted a control mechanism
23:58
I wanted to be able to move sliders. So having a web app allows us to do that
24:05
And obviously, if we're going to do web apps now, Blazor is definitely a good place to start
24:10
So it's a single-page app framework that over on here started out life as a pet project of this guy on the right
24:19
Steve Sanderson. And he demoed it at a Microsoft conference and some Microsoft people saw that demo
24:24
and jumped on him and said, we need to bring this in and use this as what we're going to be using
24:31
from now on. And it is fantastic. And what it allows you to do is write your front end code in
24:37
C Sharp rather than in JavaScript. And I know there's things like Silverlight, which is fantastic
24:44
but this is plugin-less. And there's a couple of different ways of doing it
24:49
But one of them is with WebAssembly. So it just runs natively in most modern browsers
24:56
And you just write it in standard Razor and HTML. So if you've done any ASP.NET, then that's what this will let you do
25:02
And it's great. So it's definitely a good place to start. And I like it
25:07
It feels a little bit like knockout if you've ever done any of that. But unless you add a communications medium in here
25:17
you're stuck with the browser. So SignalR is a great place to be able to add a communication mechanism
25:23
that's real time. And that's kind of the point. So I could do this with something like IoT Hub maybe
25:30
but I wanted the real time nature here to make that work
25:35
And SignalR gives us that. So SignalR is an open source package created by these two fab people
25:41
Dave Fowler and Damian Edwards. And it enables bi-directional real time communications
25:46
and what's good about it is that they've written it in such a way that it supports web sockets out
25:51
the box but if you can't get web sockets to work because ports are blocked or the technology is not
25:56
working over your network then it'll drop down to server-side events and even long polling
25:59
and it really is awesome and if you've ever done any SignalR yourself then the hello world for
26:08
SignalR is a chat app, and you will see that appearing in my code. So this is the demo for driving the robot arm with that
26:17
So we're already at the right part here, but if I go back up to the top, we're pulling in SignalR here, a client SignalR
26:27
We've got HTTP as well because it's predicated on that. And on Live 15, we're creating this hub connection, the SignalR hub, and then we use that down here
26:38
So we create a new connection to the SignalR hub here using this hub connection builder
26:45
And we pass in an IP address. And this happens to be the IP address of my PC
26:50
And we pass in this chat hub as the address. And I'll explain where that comes to in a minute
26:56
I also needed to do a little bit of extra work down here. When I was trying to get this demo to work, and it's quite a while back now, granted
27:05
but it wouldn't let me connect. there were certificate errors. And I tried a bunch of stuff
27:09
People said it was a .NET 5, you know, clear certificates problem. So I tried that and that didn't work
27:14
So I've got this nasty piece of code that just accepts any certificate. This is great for demos
27:20
Don't do this in production. It does say it's dangerous. And that's for a good reason
27:24
Never just trust every single certificate you see. So that's what that's doing
27:28
And then I've got this with automatic reconnect because it's possible that you could lose connection
27:33
to the hub and I just want to make sure that gets reconnected. And then we build that hub connection
27:39
And we're off and running almost at that part. Now, the way SignalR is working is that you send out a message to a hub
27:49
and then the hub then can control where that message goes. And as I mentioned earlier, one of the first things you'll do
27:54
if you do a SignalR application is a chat app. And I've usurped that chat app code
27:59
So I've got a user and a message that gets sent out as this SignalR information
28:04
and I've taken the user to be the servo that I want to control and I've got three servos
28:09
So I have a servo one, a servo two and a servo three and the message I've taken to be the angle
28:15
and I just convert that to an int. And then I've got this move to angle routine
28:19
that I showed you earlier and that just passes in a servo and we write that angle out to the servo
28:25
Down here, I start that signal R connection and just here, I do nothing
28:29
I just wait and the code just sorts itself out. And when the code finishes, we just stop the servos
28:36
So that's the Raspberry Pi side of that code. And I'm actually gonna start that code up now
28:42
and switch across to the web code and show how that part works
28:47
So if I do a .NET new now, and all we'll get there is just hello world
28:55
Oh, .NET, don't want .NET new. What am I doing that for? .NET run. I'm glad it didn't actually do that
29:02
That would have been bad. Let that finish and run up. And I'll know when it's ready
29:11
Don't need to worry about that unreachable code. And hello world has appeared. So that's happy
29:15
So if I pull this down, then we have our code for the Blazor app
29:25
So if I actually show you that first, then it's going to make a little bit more sense
29:30
So where is it? This one here, in fact, where are you? Here
29:34
This is what we want. So if I pull these things to side by side
29:39
then here is my Blazor app. So I've got three sliders on here
29:46
and they're going to control the positioning of this robot arm on the left hand side
29:50
So the UI is pretty simple. But if I explain to you how that's actually working
29:56
So we've got three sliders. Three different parts to this particular project
30:02
I've spun up a Blazor server app essentially, but it's a client app with a server attached to it
30:11
So you create a WASM, so it's .NET new Blazor WASM would be what you'd do at the command line
30:16
But if you tack on a dash dash hosted, then you get a server element to that
30:20
We need the server because that's where the signal our hub is going to live. And then we need the client app because that's what we're
30:25
going to interact with. So over here in our client, which is the part that we interact with
30:32
then we've got a pages folder, and in there, we've got the index.razor page, and that's just the first page we go to
30:39
Now, we pull in the SignalR client, and this is going to work just the same as the robot arm, actually
30:44
Both of these things are going to connect to a central hub, and then all of the communications are going to happen out of that
30:50
Then next, I've got our sliders, and it's worth calling out that I'm using a free and open source UI library called Map Blazer
30:59
And it's fantastic. It's well worth checking out. I'm using it because it gives me sliders
31:04
But there's a whole host of different UI elements that you can pull in
31:09
So, yeah, go and check that out for sure. And I've got three of them
31:14
And I've bound the value of this slider to a property called Servo 1
31:20
And I've done that for Servo 2 and Servo 3. And that's the markup code
31:25
That's as much as we need for the markup code. And down here is where we do the C-sharp code
31:31
in this code element. So just like on the Raspberry Pi, I've got a hub connection
31:36
We've also got a list of messages so we can see them, just like our chat app that this came from
31:41
And then on the page initialized routine here, We create our hub connection just like I did before
31:51
It's going to connect to the chat hub address just like on the Raspberry Pi
31:54
I don't need to worry about accepting certificates because this is on the same PC
31:59
So don't forget the Raspberry Pi code is running on the Pi. This Blazor app is running on my PC
32:05
And then here, when we receive a message just like on the Pi
32:09
then I'm just going to squirt it out onto the screen so you can see that message
32:13
And then we start up the hub. So a little bit further down, we've got our properties
32:18
So when I move the slider, I'm going to send a connection out to the SignalR hub with send message as the message
32:26
servo one as the user, if you will, and then the value of that slider is going to be the message that I'm then decoding on the pie to determine the angle I want to go to
32:36
And I do that for all three servos, and then I default them. So that's as much Blazor code as you really need
32:43
There is a couple of other things. So we've got the actual chat hub, as it's called, the SignalR hub here
32:49
And there's not much to that. So when you invoke that send message routine, which is just here, send message
32:55
then we send a receive message command out, passing in the user and the message to all of the other clients
33:04
So everything that's connected to it will get that particular message. There's also a little bit of bootstrapping that you need to do in the startup.cs for the server
33:13
part so this is living in the server this is going to be hosted there somewhere
33:17
so i'm hosting it on my pc you need to configure the signal our service here
33:22
and then you need to map that end point there that chat hub end point so it knows where it's going
33:28
so they're the two main things that you need to do now as you see i've already already run that up
33:33
so that's all running and i've got my signal r connection started up on the raspberry pi
33:40
and assuming my batteries aren't flat, I should be able to move my robot arm with these sliders
33:47
So they're sending, so you can see the messages down there at the bottom. It's not top-elemented, but that's where it is
33:54
And so I can move it left and right and up and down. Now, it's a very rickety robot arm and it's quite easy for it to fall over
34:02
But, you know, that's kind of the fun of this talk. It's how it works
34:07
And this Survey 3 that is the pincers that you can see there the grab if you will So that now sending SignalR messages from my PC through the SignalR hub that the Raspberry Pi is connected to
34:21
And it's happy. It's running. I'm able to move my .NET Raspberry Pi robot arm with SignalR directly from the browser there
34:33
That's pretty cool all on its own, but I didn't want to stop there. that's great I like it but there's more we can do. So if I close that one and if I just stop my
34:48
code a second what I've done is I've deployed that Blazor application to Azure. So that web app
34:56
is living there in Azure and if I open up this tab and maximize that then this all looks very
35:06
similar but if I switch out the address that I've got over here for my hub
35:13
connection on the pi so this is where I'm connecting and this at the moment is
35:17
connecting to my local PC on that port if I then switch that out to point to
35:22
this address and run that one up see how we didn't do dotnet new I've got a brave
35:31
fade with that today. Let that finish. Hello world, there it is. Then switch back to this
35:42
Now if I move my robot arm, then my robot arm is moving. I can go back up. Now what's cool is
35:50
can you see this address? By all means, go to that address. So that's bcsrobotdevuksapp.azurewebsites.net
36:00
by all means go to that address and you too can drive that robot arm now what's dead cool is that
36:07
the first time I demoed this Shahid one of one of the MVPs he'd recently moved to New Zealand and
36:12
he watched the talk and he dialed in and from New Zealand he was able to move this robot arm
36:18
so I mentioned earlier that although this is kind of a silly demo it's not really this whole concept
36:24
you could think, all right, well, this could be a robot arm that a neurosurgeon is using from the
36:31
other side of the world. And this is real technology. This is happening. So you're able
36:36
to then control this thing directly from anywhere else in the world. I'm amazed that nobody else has
36:41
done this yet. Usually people are leaping on there and doing it. But this is running now. So anybody
36:47
that hits that address up, they can go and control this robot arm. What normally happens is it starts
36:52
flinging itself around all over the place when people do that because it's very rickety it can
36:58
fall over and everything so do by all means you can you can go and hit that address up but now
37:03
the fact that this is sitting up in azure means that again it can be accessed this signal r hub
37:10
specifically can be accessed by anybody so you can take this thing a little bit further and
37:16
you've been paying any attention to my background here you'll see i have an oculus quest
37:22
And what I've done is that I've created a, there you are, you can see me a little bit better
37:28
I've created a VR app in Unity, which is C sharp, which means we have access to SignalR
37:34
So I can then show you this. So if I squiz forward onto this screen over here, then this is the casting screen
37:47
So bear with me, I will start casting and you should be able to see how that's working
37:52
So let's just bring this over here as well so it's not going to complain. Take my headphones off
38:04
And I'll pick the right controller up. Good. That's working. So if I start casting, hopefully this works
38:16
I've had some problems with casting recently. Oh no, that's good. Looks like something's happening
38:22
Right, so if I make that full screen. There we go And I should be able to switch that to that so it makes it a little bit better so this is my silly unity robot arm demo now you won be able to see this but if I move this slider you
38:45
see that inside the robot arm is moving and if I change that and that's changing in there and if
38:53
to change this, then that's changing there too. Now, that's actually moving my real robot arm as well
39:00
So if I flick over to this page, and then actually, yeah, that'll work
39:09
That's fine. Actually, if I get, I don't want to go this one there
39:15
then you should be able to see me moving the robot arm here too. There we go
39:26
So you're able to, with a VR headset, control a robot arm in the real world
39:33
And likewise, if people then hopped on that address and controlled it, it would then control
39:40
the robot in the VR environment as well. So it's quite difficult for me to show that actually
39:48
But normally I'd just ask somebody else to hit that address and they'd be able to do that
39:53
That's exactly what that would do. So, yeah, I quite like that demo, and I had a lot of fun making that app
39:59
But I did want to briefly mention one more thing, and I'm just going to stop my code again here for a second
40:06
And if I flick back to my slides, then I want to talk quickly about Uno Platform
40:11
I think I've got enough time. Yeah, I've got 10 minutes, so it's fine
40:16
So I mentioned earlier that we can't put WPF on a Raspberry Pi
40:21
But what we can do is that we can put UWP on a Raspberry Pi by using the UNO platform
40:27
So UNO platform was created by Jérôme Labon there on the right-hand side
40:32
And this is a UWP bridge to allow us to be able to create XAML and run that as a user interface on a Raspberry Pi
40:40
And it's all open source and cross-platform. They do all their development in public. And it supports WinUI 3
40:46
and it accomplishes WPF and XAML, XAML really, not WPF, UWP on the Pi
40:54
by using Skia and GTK. So I just wanted to quickly show that
40:59
So if I go across to, yes, this page, then I've got some
41:05
I'm not going to go through the code here, but actually the code is very similar
41:09
to what we saw on the Pi for the .NET version of this code
41:15
the standard .NET versions. So some PWM channels and some servo motors
41:19
And I create them here, pass in the same variables, all very similar. Only I've got a UI level on top of this
41:25
So when I move a slider, then just like in the Blazor app, it then moves the servo directly
41:31
Now, this is on my PC, and I can deploy that to my Pi with F5. Just hit F5, and it'll build it and publish it to a compatible ARM32 package
41:41
and I've got some setup on here that will deploy that then with our sync and
41:47
down to the Raspberry Pi and run it and I've got VNC running here so if I dial
41:54
into my VNC session that's terminated itself nicely and pull that down here and
42:00
then on the left hand side we get the robot then all being well it should
42:06
deploy it does take a little a couple of seconds but we've got enough time
42:11
here we go it's doing a fair amount at this point actually my pc is doing a fair amount
42:23
um at this point but here we go so that's going to start now sending the files over so you can see
42:28
that's rsync just there and then it's going to flip over to the debug console so this is going
42:32
to allow me to actually debug the code directly put breakpoints in there if i like and inspect
42:37
variables and then if I get these two windows up side by side then now we got a UI This is written in XAML UWP and I can control my robot arm directly from the Raspberry Pi so you can imagine at this point I could have a tiny little LCD if I wanted to on the Raspberry
42:55
Pi to be able to control the robot arm directly and I thought it was quite important to show that
43:00
we can do this all locally and still all in .NET so that's that's pretty cool I like that and do go
43:10
and check out the UNO platform if you've not looked at that. It's definitely worth checking out
43:16
So I've already spoken there about Unity. I kind of skipped ahead there a little bit
43:20
But that's cross-platform, and it allows you to be able to create 2D and 3D
43:26
And, yeah, .NET Standard 2 or .NET 4. So there was a bit of fiddling I had to do to get NuGet to go in there
43:32
I know having spoken to Cliff Aegis, who was presenting earlier, that if you use Visual Studio rather than VS Code
43:39
then the package management is easier with Unity. Otherwise, you're into kind of doing it manually
43:44
because if you pull a package down, then you get a bunch of directories
43:48
And inside of those directories, you get the .NET 4.5 and you get the .NET Standard and .NET Core
43:54
And you've got to go and copy those individual bits out, the .NET Standard 2 individual bits into the right directory
44:01
And it gets a bit messy. So it took me a little while to get it to work. But once I did, the code was actually relatively straightforward
44:06
and that gave us VR robots, which is quite cool. But this wasn't plain sailing the whole time through
44:14
and I wanted to show people that, you know, things do go kind of wrong. So I've got a blooper reel
44:19
My cat, for some reason, loves the sound of these servos, and every time I go and do that demo
44:24
she jumps up and grabs them. Likewise, you've got to be really careful
44:28
If you don't fasten this thing down, then, you know, it'll just fall over
44:33
which is what this particular demo is going to show you here. So you can see I've not got any screws in the base there
44:38
You can just see. So if you overextend the arm, then the whole thing will fall over
44:43
But you do some learning when you're making demos like these. Some links
44:47
Don't worry too much about copying all of this down, because there's a link to these slides that I'll publish
44:53
later on today. And I'll send out a tweet when I've done that
44:57
But yeah, there's a link to a workshop. And you can run through this whole workshop yourself
45:01
It's got the kit of parts you need and everything. And in fact, the robot arm I'm using is a bit complicated
45:08
So Cliff Agus and his son have made a set of 3D files for a far simpler robot arm
45:15
that you just screw together and using the servo screws that come in the packet
45:19
So definitely check that out. But I know people like John Lund, Johnny Chips, he's been and he's run through this workshop
45:27
And in fact, we've run it for all the Microsoft garages across the world as well
45:31
So that was pretty cool. And then I've got my blog post on how to get .NET 5 on the Pi, and then a bit of information about the NuGet packages we've used, and then the 3D printed robot arm stuff from the presentation, and then the one that I mentioned about Cliffs there at the bottom as well
45:47
Some more information about Blazor, Map Blazor, awesome Blazor. If you're interested in IoT, then I run Notts IoT
45:54
And next month, we've got Andre Podnoff coming along to talk about Azure Digital Twins
46:01
And we've also got .NET Notts. We've got Liam Wesley talking about cloud stuff
46:06
And I also run a Twitch channel called Azureish Live. And on there, I've got a show with Cliff Aegis called IoT Live that we do 9 p.m
46:14
British time, whatever that happens to be, BST or GMT at the time of year
46:18
So come and check us out on there. And if you want to learn a bit more about AZ220
46:23
then hit that link up there and you can see the Pluralsight stuff. And then you can contact me here
46:29
And this is particularly the link that you want to note down. And that will give you the links to everything that I've done
46:36
And that will be up not long after this talk is finished. And with that, that's me
46:41
I'm going to leave that link on the screen, actually. I've got another Contact Me slide, but you might want to grab that link
46:47
So I'll just leave that there. So yeah, thank you very much for tuning in, and I hope you found that interesting