As the previous article was "current-status". Progress brought new insights, and so the following corrections apply:
- I develop in VS2015 under Windows, so I didn’t need to install Akka.Net on the RPi; installing fsharp for Debian/Ubuntu Linux is enough;
- The Self-Hosted Websharper template does not work -fully- as was described, see below;
Control Panel
The goal is to write a web application, which provides a Control Panel for the Robot Arm. I want to run the Control Panel via my home-network on my iPad.
The web application should show all four Servo-motors, and two buttons per motor, with which I can turn the motor clockwise or anticlockwise. If the buttons are untouched, the motors don't move. If a button is pressed, the motor should rotate at a constant speed, and not too fast.
It almost crashed when my 2-year-old showed his interest..
Application Architecture
The visual part of the Control Panel is written using FSharp and Websharper. Websharper enables the visual interface and to send events (button pressed) to the Webserver on the Raspberry Pi.
At the server side a user event is sent to a "Directional Controller" (later more about this) which is created using Akka.Net. The directional controller receives the events and converts this into motion of the Servo-motors. There is one "Directional Controller" per motor.
We are going to use the ServoBlaster installed in part 1. According to this article, the following Linux shell command will rotate one of the Servo motors:
Akka.Net provides a good way to throttle. We just create a "device-actor" which writes to the device. If the directional controller wants to invoke motion, it send a move command to the device-actor. The device-actor handles all messages in order, and one per time, so we'll have no Sharing Violation issues.
Another reason to use Akka.Net is to gain a bit experience; we are considering using Akka.Net at work, in C# though, but still.
Directional Controller
For the directional controller, I modelled a strange kind of pressure based structure. For the metaphor, I assume that water delivers the pressure. I couldn't find a real-world product, so I made up a name. The schematics are below:
I used this metaphor of the "directional controller" in my source code, which you can find here on GitHub.
Running the Control Panel
Get the code from GitHub, and compile it in Visual Studio 2015. In part 1 you made a shared drive on your Raspberry Pi, and you should copy the relevant files to this share, from your Windows machine. Copy everything except .fs source code files, "packages" file, "Visual Studio Project" file.
This little summer project had lessons to learn. Some in the code (I've added comments), and some in the bigger picture.
Screw around
While screwing the parts into a Robot-Arm, I was just following orders, with no experience whatsoever. And some joints are just rough, which is why they resist rotating well. I was just screwing around, and felt sorry later. However, if I paid a bit more attention in the beginning, I would probably have made similar mistakes. Currently I am re-screwing (around) to ease up the joints. Not satisfied yet, so I carry-on screwing.
Soldering
It has been quite a while the last time I soldered something. A few pins needed to be soldered onto the card, which interfaces on the RPi, and to which you can connect the Servo's. I didn't do a good job the first time, and when I plugged in my RPi, something got smelly. Later on, I found my Micro SD card was melted and broken in two. Lessons learned? Don't under-estimate this, things can really break.
Webserver
Initially, my plan was to run Websharper as WebApp framework, under a webserver from the F# community. Unfortunately my plan failed. I tried Suave.io with Websharper, but I could not find any way to connect these two. From Freya I understood that it still requires some work 5) for Freya to run Websharper. As time was running out, I decided to use Websharper's Warp. First I tried the self-hosted template, mentioned in part-1, but at closer look, only the server-side HTML worked, while the dynamic HTML created with Javascript did not work. Another possibility is that I did something wrong, but like I said - time was running out, I did not follow-up.
I used the self-hosted client-server template from Websharper to create the project, but deleted the code in the Main.fs and replaced it with Warp code (example).
It worked fine, but sometimes I copied all the stuff from my Windows machine to the Raspberry Pi, ran it, and it showed no changes, even when I erased the whole WebApp. Caching anyone? No there wasn't.
As I moved stuff around to make my deploy procedure much easier, I found out that the folder "Scripts" was created in unexpected locations. Then it came to me. I used the relative folder ".." as WebApp-root. In some cases Websharper uses this relative to the binary's location and in other cases relative to the execution folder (which caused "Scripts" in unexpected locations). When I cd'd to the bin folder and executed the binary from there, the issue was gone.
Mono Crashes
So I created everything. First proof of concept of all parts, ran it on my PC, then ran it on the Raspberry Pi 2B. And when I felt confident, I put it all together, in one FSharpArm solution, with Websharper, Akka and Websharper.UI.Next v3.4 (which is awesome). It worked on my Windows PC, but when I copied everything to the Raspberry Pi, I got this screen:
Akka.Net
The first thing I received from Akka.Net was a "DeadLetterNotification", when the first message was send. It appeared that I used keyword "use" instead of "let" to create the actor system in a function. When the function exited, the actor-system was disposed. With "let" you don't have this problem. That "use" came from example code.
Did Akka.Net add any value? I think it did. It worked perfectly for throttling the writes to the device. You can press two buttons in the Control Panel at the same time, and I did almost nothing to solve this concurrency problem. The "pressure" in the controller is done by (see source code) a "pulsar", which sends a message to the controller at a fixed time-interval. Thanks to the scheduler (and a co-worker who tipped me this feature) I didn't need "Quartz for .Net" or write something myself. Using a structure which open/closes valves to block or let messages through, I have a system with which I can give the Servo-motors a constant slow speed. I experimented with higher speeds and found that the Robot-arm may lose its balance.
To Conclude
This was it for the FSharpArm summer-project. Summer is finished here in Northern Europe and I will fly for holidays to the City of the Sun in Brazil, in September. It was nice to see, how little is needed to have an interesting learning experience.