Windows IoT借助树莓派.Net Core用PWM做炫彩灯试验
什么是 PWM
PWM(Pulse Width Modulation)即脉冲宽度调制,简称脉宽调制,通过对一系列的脉冲的宽度进行调制,从而等效出所需要的模拟信号。通过使用 PWM 技术,我们可以在数字电路中模拟出电信号的连续变化。
炫彩灯就是利用PWM产生的连续变化造成了电压变化,从而LED灯亮度有变化。
首次尝试
.Net Core的UWP项目VS自带一个类库Windows.Devices.Pwm,很容易想到和GPIO控制器类似
public async Task InitAsync()
{
var controller = await PwmController.GetDefaultAsync();//失败,controller=null
red = controller.OpenPin(pinNumber: 18);
green = controller.OpenPin(pinNumber: 23);
blue = controller.OpenPin(pinNumber: 24);
}
没想到这段代码无法按逾期执行,更谈不上后面的控制了。查了一下资料据说是树莓派默认没有PWM由GPIO方式,还没确认这种说法是否正确,看到C、Python的例子上PWM都正常。
后来发现微软还单独提供了另外一套IoT开发组件System.Device.Gpio,不同于Windows.Device.Gpio.
有这么一段介绍:
“System.Device.Gpio 是一个全新的 .Net Core 开源库,它旨在使 IoT(物联网)应用程序能够通过其 GPIO 引脚或其他 I/O 控制硬件与传感器、显示器和输入设备进行交互。该库是由社区维护的多个设备绑定集合来进行增强实现的。
正如微软 .NET 项目经理 Richard Lunder 所演示的那样,这个新库通过一组可用于控制外部设备的 API,使开发人员能够控制单板计算机的通用 I/O (GPIO)引脚。这在以前使用.NET Core 时是不太可能实现的,尽管.NET Core 也可以运行在 Raspberry Pi 上。它支持的平台包括 Raspberry Pi、BeagleBoard、HummingBoard 和 ODROID,但是不支持比较流行的 Arduino 板,如 UNO、Mega、Nano 等。
通过 NuGet 包提供的这个新库可以在 Linux 和 Windows 10 IoT Core 上运行,它依赖于这些平台上可用的本地驱动程序。对于基于 Linux 4.8 及更高版本的 Linux 发行版,System.Device.Gpio 使用 libgpiod ,它取代了 GPIO sysfs 接口,后者为较老的 Linux 版本提供了比较有限也比较慢的 GPIO 访问。为了获得最高的性能,尽管是以可移植性为代价, Linux 上的 System.Device.Gpio 还支持通过 /dev/mem 来访问 GPIO,虽然这些板定制的驱动程序在将来可能会被删除。
System.Device.Gpio 有一个配套库,名为 Iot.Device.Bindings ,它通过向开发人员提供更高级别的API 而不是依赖pin 级的协议来访问它们,从而可以更容易地使用很多现有的“哑”传感器、显示器和输入设备。目前, Iot.Device.Bindings 包含了数十种设备的绑定,如 A/D 转换器、加速器、气体传感器、光传感器、气压计等。需要注意的是,Iot.Device.Bindings 是一项社区成果,并没有完全得到微软的支持。
Lunder 演示了如何使用 Mac 上的 Visual Studio Code 运行了一个 LED 控制应用程序,该程序运行在 Raspberry Pi 3 上,它完全支持逐步调试。部分 System.Device.Gpio 是用 C++ 编写的,不过他们正在逐步往 C#上移植,这将使.NET 开发人员更容易对其进行改进和修复。
System.Device.Gpio 仍处于试验阶段,微软正在寻求人们对其 API 的积极反馈,这些 API 可能会在未来的版本中发生变化。”
再次尝试
public class ColorfulLamp
{
PwmChannel red;
PwmChannel green;
PwmChannel blue;
public static ColorfulLamp Instance { get; } = new ColorfulLamp();
private ColorfulLamp()
{
red = new SoftwarePwmChannel(pinNumber: 18, frequency: 1000, dutyCycle: 0);
green = new SoftwarePwmChannel(pinNumber: 23, frequency: 1000, dutyCycle: 0);
blue = new SoftwarePwmChannel(pinNumber: 24, frequency: 1000, dutyCycle: 0);
}
public async Task Start()
{
await Task.Factory.StartNew(() =>
{
red.Start();
green.Start();
blue.Start();
Breath(red, green, blue);
red.Stop();
green.Stop();
blue.Stop();
});
}
private void Breath(PwmChannel red, PwmChannel green, PwmChannel blue)
{
int r = 255, g = 0, b = 0;
while (r != 0 && g != 255)
{
red.DutyCycle = r / 255D;
green.DutyCycle = g / 255D;
r--;
g++;
Thread.Sleep(10);
}
while (g != 0 && b != 255)
{
green.DutyCycle = g / 255D;
blue.DutyCycle = b / 255D;
g--;
b++;
Thread.Sleep(10);
}
while (b != 0 && r != 255)
{
blue.DutyCycle = b / 255D;
red.DutyCycle = r / 255D;
b--;
r++;
Thread.Sleep(10);
}
}
}
执行
private async void btnLamp_Click(object sender, RoutedEventArgs e)
{
while (true)
await ColorfulLamp.Instance.Start();
}
效果图,制作成gif再补充一下...
- 点赞
- 收藏
- 关注作者
评论(0)