.net, Clean Code, Making, nuget, Raspberry Pi 3, UWP

A servo library in C# for Raspberry Pi – Part #2: Designing the interface, IServoController

Last time I posted an article describing a proof of concept for how to control a servo using a Raspberry Pi 3. This time, I want to improve the code so it’s better than just a rough proof of concept – I’d prefer to write a re-usable library. So the first step of my design is to build an interface through which I can talk to the servo.

There were a few principles that I wanted to adhere to:
1. Make the interface fluent (where it was sensible to do so);
2. Make the interface as small as possible;
3. Add public properties so this could be used for servos which have slightly different profiles.

Finally, I wanted to implement the IDisposable interface – this would be useful to close any connections if that was necessary.

Connecting to the servo

There are a couple of things that need to be done when setting up the servo:
1. Specify the GPIO pin on the Raspberry Pi which is going to output a PWM signal;

int ServoPin { getset; }

2. Once we have specified the pin, we need to open a connection. I knew from my proof of concept code that this used asynchronous methods, so I needed the return type to be a Task (as asynchronous methods cannot return void in C#).

Task Connect();

Moving the servo wiper

The first and most obvious thing to tell a servo to do is move to a particular rotational position. This position would be most commonly measured in degrees.

However, one issue is that the source program has no means of knowing when the servo’s blade has reached position. In Arduino code, I’ve seen this handled by just putting a delay in after the instruction to move to a particular position.

I liked the idea of a chain of commands, which would tell the servo the position to move to, specify the amount of time allowed to move to this position, and then go.

// This moves to 45 degrees, allowing 500ms to reach that position
servo.SetPosition(45).AllowTimeToMove(500).Go();

So this ideal chain told me that I needed to have the methods:

void Go();
 
IServoController SetPosition(int degree);
 
IServoController AllowTimeToMove(int pauseInMs);

Altering frequency duty cycle properties

My research told me that servos usual expected duty cycles of 5% to 10% to sweep from 0 to 180 degrees. However, I also found some people who found these are idealised figures – in fact, with my own servos, I found that a better range of duty cycle went from 3% to 12%. So I realised that any servo controller probably needed to have public properties to set frequency, and minimum and maximum duty cycle values.

int Frequency { getset; }
 
double MaximumDutyCycle { getset; }
 
double MinimumDutyCycle { getset; }

The finished interface

So that described what I wanted my servo controller interface to look like – I’ve pasted the code for this below.

public interface IServoController : IDisposable
{
    int Frequency { getset; }
 
    double MaximumDutyCycle { getset; }
 
    double MinimumDutyCycle { getset; }
 
    int ServoPin { getset; }
 
    Task Connect();
 
    void Go();
 
    IServoController SetPosition(int degree);
 
    IServoController AllowTimeToMove(int pauseInMs);
}

Publishing the interface as a library

The final step I wanted to take was to publish this interface to NuGet. I decided to publish the interface in a separate package to the implementation, so that it would be easy to swap out the implementation if necessary.

Presently this interface is available here, and it can be downloaded from NuGet using the command:

Install-Package Magellanic.ServoController.Interfaces -Pre

It’s presently in an alpha (pre-release) status so the “-Pre” switch is needed for the moment.

Next time, I’ll write about how to implement this interface, and I’ll write a simple UWP app to test this.