Search code examples
c#windows-10-iot-coreservo

Control a Servo by C#, Windows 10 IoT and the Magellanic.ServoController - CPU issues and how to resolve them?


i am currently in the process of learning C# and the first thing i tried is to build an universal app, run it on Windows 10 IoT and to control an Servo Motor by it. My idea is to have an slider which controls the direction of the servo. For controlling the servo i use the NuGet plugin Magellanic.ServoController (by Jeremy Lindsay)

https://jeremylindsayni.wordpress.com/2016/05/16/a-servo-library-in-c-for-raspberry-pi-part-3-implementing-the-interface/

The calculations and movement based on the slider is working fine, the only issue i have, is that when i execute a movement of the servo, this process takes 30 % of the CPU capacity (event when the movement is completed). This results in the situation that i can execute 3 Movement and after this the CPU is at nearly 100 % and the 4th movement will not be executed correctly (as hardware i use a raspberry pi 3).

This is the code i use

 using Windows.UI.Xaml;
 using Windows.UI.Xaml.Controls;
 using Magellanic.ServoController;
 using System;
 using System.Threading.Tasks;

 namespace App5
 {

 public sealed partial class MainPage : Page
 {
    public MainPage()
    {
        this.InitializeComponent();           
    }



    private async Task MoveServoToCentre(double MovementTime, double CalculatedFrequency)
    {
        using (var servo = new ServoController(5))
        {
            servo.Frequency = Convert.ToInt32(CalculatedFrequency);
            await servo.Connect();
            servo.SetPosition(90).AllowTimeToMove(Convert.ToInt32(MovementTime)).Go();
            servo.Dispose(); 
        }
    }

    private async void Slider_Value_ChangedAsync(object sender, Windows.UI.Xaml.Controls.Primitives.RangeBaseValueChangedEventArgs e)
    {
        Slider slider = sender as Slider;

        if (slider.Value < 50)
        {
            await CalculationAsync(slider.Value);

        }
        else if (slider.Value > 50)
        {

            await CalculationAsync(slider.Value);

        }

    }

    public string PreviousValue;
    public double RequiredFrequenz;



    private async Task CalculationAsync(double value)
    {
        if (PreviousValue != null)
        {
            double Result = System.Math.Abs(Convert.ToDouble(PreviousValue)) - value;


            if (Result < 0)
            {
                RequiredFrequenz = 100;
            }
            else if (Result > 0)
            {
                RequiredFrequenz = 200;
            }

            double TimeToMove = System.Math.Abs(((int)Math.Round(Result * 3.8)));

            System.Diagnostics.Debug.WriteLine(TimeToMove);
            System.Diagnostics.Debug.WriteLine(Result);
            System.Diagnostics.Debug.WriteLine(value);
            System.Diagnostics.Debug.WriteLine(PreviousValue);
            System.Diagnostics.Debug.WriteLine(RequiredFrequenz);

            await MoveServoToCentre(TimeToMove, RequiredFrequenz);

            TimeToMove = 0;
        }
        else
        {
            if (value > 50)
            {
                double TimeToMove = ((int)Math.Round((value - 50) * 3.8));
                RequiredFrequenz = 100;

                System.Diagnostics.Debug.WriteLine(TimeToMove);
                System.Diagnostics.Debug.WriteLine(value);
                System.Diagnostics.Debug.WriteLine(PreviousValue);
                System.Diagnostics.Debug.WriteLine(RequiredFrequenz);

                await MoveServoToCentre(TimeToMove, RequiredFrequenz);

                TimeToMove = 0;

            }
            else if (value < 50)
            {
                double TimeToMove = System.Math.Abs(((int)Math.Round((value - 50) * 3.8)));
                RequiredFrequenz = 200;

                System.Diagnostics.Debug.WriteLine(TimeToMove);
                System.Diagnostics.Debug.WriteLine(value);
                System.Diagnostics.Debug.WriteLine(PreviousValue);
                System.Diagnostics.Debug.WriteLine(RequiredFrequenz);
                await MoveServoToCentre(TimeToMove, RequiredFrequenz);

                TimeToMove = 0;
            }
        }


        PreviousValue = value.ToString();
        value = 0;
    }
}
}

My current guess is that some code provider is not unloaded correctly or something like that.

Many thanks in advance for your help!

PS: Here a link to the code of the NuGet PlugIn:

https://github.com/jeremylindsayni/Magellanic.ServoController/blob/master/ServoController.cs


Solution

  • This issue looks like caused by repeatedly call this line ServoGpioPin = pwmController.OpenPin(ServoPin); of ServoController.Connect() method but I am not sure what's the underlying cause.

    There is a workaround: Instantiate the ServoController and call ServoController.Connect() only one time at first instead of doing this work every time in MoveServoToCentre() method. Code sample like this:

        ServoController servo = new ServoController(5);
    
        protected override async void OnNavigatedTo(NavigationEventArgs e)
        {
            await servo.Connect();
        }
    
        private void MoveServoToCentre(double MovementTime, double CalculatedFrequency)
        {
            servo.Frequency = Convert.ToInt32(CalculatedFrequency);
    
            servo.SetPosition(90).AllowTimeToMove(Convert.ToInt32(MovementTime)).Go();
        }