Note
Access to this page requires authorization. You can try signing in or changing directories.
Access to this page requires authorization. You can try changing directories.
So you been looking for some code that actually works with the Netduino 4.3.x & up to control a servo, well now you have found it. I credit most of the code here thanks to Chris Seto from back in 2010 posted on the Netduino forum and it worked great on the 4.0-4.1 framework! However, a lot has changed since then like PMW.SetPulse doesn't exist and now when instantiating a new PMW it requires a PMWChannel and not a Pin as an argument plus a few more required parameters. So, I took what Chris wrote and modified it to fit the current framework and implemented those changes. I do not get into the nitty gritty of explaining the changes here, this is just a implementation and share post. If you want a deeper dive just ask in the comments and maybe if there are enough I will come back to that. For the rest that want to consume, here you go, enjoy:
/*
* Servo NETMF Driver
* Coded by Chris Seto August 2010
* <chris@chrisseto.com>
*
* Use this code for whatever you want. Modify it, redistribute it, I don't care.
* I do ask that you please keep this header intact, however.
* If you modify the driver, please include your contribution below:
*
* Chris Seto: Initial release (1.0)
* Chris Seto: Netduino port (1.0 -> Netduino branch)
* Chris Seto: bool pin state fix (1.1 -> Netduino branch)
*
* Theo Browning: Release (2.0) modified to work with current framework.
*
* */
using System;
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using SecretLabs.NETMF.Hardware;
using SecretLabs.NETMF.Hardware.Netduino;
namespace NetduinoApplication1
{
public class ServoController : IDisposable
{
/// <summary>
/// PWM handle
/// </summary>
private PWM servo;
/// <summary>
/// Timings range
/// </summary>
private int[] range = new int[2];
/// <summary>
/// Set servo inversion
/// </summary>
public bool inverted = false;
/// <summary>
/// Create the PWM Channel, set it low and configure timings
/// Changes here PWM Channel requires Channel, Period, Duration,
/// Scale and Inversion on instantiation.
/// </summary>
/// <param name="pwmChannel"></param>
public ServoController()
{
// Initialize the PWM Channel, set to pin 5 as default.
servo = new PWM(
PWMChannels.PWM_PIN_D5,
20000,
1500,
Microsoft.SPOT.Hardware.PWM.ScaleFactor.Microseconds,
false);
// Full range for FS90 servo is 0 - 3000.
// For safety limits I set the default just above/below that.
range[0] = 600;
range[1] = 2400;
}
/// <summary>
/// Allow for consumer to set own range.
/// </summary>
/// <param name="leftStop", "rightStop"></param>
public void SetRange(int leftStop, int rightStop)
{
range[1] = leftStop;
range[0] = rightStop;
}
/// <summary>
/// Dispose implementation.
/// </summary>
public void Dispose()
{
Disengage();
servo.Dispose();
}
/// <summary>
/// Disengage the servo.
/// The servo motor will stop, and try to maintain an angle
/// </summary>
public void Disengage()
{
servo.DutyCycle = 0; //SetDutyCycle(0);
}
/// <summary>
/// Set the servo degree
/// </summary>
public double Degree
{
set
{
/// Range checks
if (value > 180)
value = 180;
if (value < 0)
value = 0;
// Are we inverted?
if (inverted)
value = 180 - value;
// Set duration "pulse" and start the servo.
// Changes here are PWM.Duration and PWM.Start() instead of PWM.SetPulse().
servo.Duration = (uint)map((long)value, 0, 180, range[0], range[1]);
servo.Start();
}
}
/// <summary>
/// Used internally to map a value of one scale to another
/// </summary>
/// <param name="x"></param>
/// <param name="in_min"></param>
/// <param name="in_max"></param>
/// <param name="out_min"></param>
/// <param name="out_max"></param>
/// <returns></returns>
private long map(long x, long in_min, long in_max, long out_min, long out_max)
{
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}
}
}
That's the class, now here is just a simple example of implementation, the following will infinite loop a servo to full left/right motion. Get past the infinite loop and the sleep as well as this is for simplicity, I would implement a timer and a condition if this were for real application. We can come back and talk about timers in NETMF another time as they are a whole different animal than timers in the full .Net Framework (post in comments if you would like to see more on timers).
public static void Main()
{
ServoController servo = new ServoController();
servo.SetRange(500, 2400);
bool runForever = true;
while (runForever)
{
for (int i = 1; i < 179; i++)
{
servo.Degree = i;
Thread.Sleep(25);
}
for (int i = 179; i > 1; i--)
{
servo.Degree = i;
Thread.Sleep(25);
}
}
servo.Dispose();
}
Enjoy and I hope this saves you some time!
Comments
- Anonymous
February 16, 2016
You can Post it To http://tricksntech.com This Tutorial as A Guest Please Come Always. - Anonymous
February 17, 2016
Absolutely, will do. - Anonymous
May 11, 2016
Hah, I'm Chris Seto. I wrote this like 6 years ago now. Very pleased to see it still lives on. Nice work.- Anonymous
June 13, 2016
Absolutely Chris, code is still alive and kicking, thanks for writing such a solid piece.
- Anonymous