通过 C# 控制舵机,Windows 10 物联网和 Magellanic.ServoController - CPU 问题以及如何解决它们?
Control a Servo by C#, Windows 10 IoT and the Magellanic.ServoController - CPU issues and how to resolve them?
我目前正在学习 C#,我尝试的第一件事是构建一个通用应用程序,运行 它在 Windows 10 IoT 上并通过它控制伺服电机。我的想法是有一个滑块来控制伺服的方向。为了控制伺服,我使用 NuGet 插件 Magellanic.ServoController(作者 Jeremy Lindsay)
基于滑块的计算和移动工作正常,我唯一的问题是,当我执行伺服移动时,这个过程占用了 CPU 容量的 30%(当运动完成)。这导致我可以执行 3 次运动,此后 CPU 接近 100%,并且第 4 次运动将无法正确执行(因为硬件我使用 raspberry pi 3)。
这是我使用的代码
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;
}
}
}
我目前的猜测是某些代码提供程序未正确卸载或类似的原因。
非常感谢您的帮助!
PS:这里是 link 到 NuGet 插件的代码:
https://github.com/jeremylindsayni/Magellanic.ServoController/blob/master/ServoController.cs
这个问题看起来是由重复调用 ServoController.Connect()
的这一行 ServoGpioPin = pwmController.OpenPin(ServoPin);
方法引起的,但我不确定根本原因是什么。
有一个解决方法:首先实例化 ServoController
并仅调用 ServoController.Connect()
一次,而不是每次都在 MoveServoToCentre()
方法中执行此工作。代码示例如下:
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();
}
我目前正在学习 C#,我尝试的第一件事是构建一个通用应用程序,运行 它在 Windows 10 IoT 上并通过它控制伺服电机。我的想法是有一个滑块来控制伺服的方向。为了控制伺服,我使用 NuGet 插件 Magellanic.ServoController(作者 Jeremy Lindsay)
基于滑块的计算和移动工作正常,我唯一的问题是,当我执行伺服移动时,这个过程占用了 CPU 容量的 30%(当运动完成)。这导致我可以执行 3 次运动,此后 CPU 接近 100%,并且第 4 次运动将无法正确执行(因为硬件我使用 raspberry pi 3)。
这是我使用的代码
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;
}
}
}
我目前的猜测是某些代码提供程序未正确卸载或类似的原因。
非常感谢您的帮助!
PS:这里是 link 到 NuGet 插件的代码:
https://github.com/jeremylindsayni/Magellanic.ServoController/blob/master/ServoController.cs
这个问题看起来是由重复调用 ServoController.Connect()
的这一行 ServoGpioPin = pwmController.OpenPin(ServoPin);
方法引起的,但我不确定根本原因是什么。
有一个解决方法:首先实例化 ServoController
并仅调用 ServoController.Connect()
一次,而不是每次都在 MoveServoToCentre()
方法中执行此工作。代码示例如下:
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();
}