当前位置: 首页 > article >正文

如何从零编写自己的.NET IoT设备驱动

本文将以 NV3030B LCD 设备驱动为例详细介绍如何从零开始一个.NET IoT设备编写驱动。这里我们使用树莓派作为硬件平台,并参考.NET IOT 官方的 Ili934x TFT LCD 驱动库。

1. 背景

在前面的 《使用.NET玩转IOT的入门建议》 文章中,我们提到.NET IOT 开发驱动的方法,借力打力跨界学习,可以先按照这些示例代码操作一遍,然后再用 .NET 重写。这里我们就以 NV3030B LCD 设备驱动为例,详细介绍如何从零开始一个.NET IoT设备编写驱动。

2. 准备工作

在开始编写驱动之前,我们需要确保以下内容:

  • 树莓派(本文以 Raspberry Pi Zero 2 W 为例)
  • 微雪 1.5寸 LCD 屏幕,NV3030B驱动芯片
  • SPI 接线
  • .NET 8.0 或更高版本
  • 微雪官方的 Python 驱动示例代码

树莓派的 40 Pin 接线基本一致,可以参考 树莓派 GPIO 接口图。

请添加图片描述

显示屏和树莓派的接线如下:

请添加图片描述

请添加图片描述

3. 验证SPI接线和设备

在编写.NET驱动之前,我们首先需要验证SPI接线和设备是否正常工作。我们可以使用微雪显示屏提供的示例 Python 代码进行测试,里面包含了 Python 版本的驱动代码。

需要注意的是:如果之前没有安装 numpy 和 pillow 库,需要先安装:

sudo apt install python3-numpy python3-pillow

然后运行示例代码,观察显示屏是否正常,如果屏幕亮起并显示内容,则说明接线和设备正常,我们可以进入下一步。

4. 编写.NET驱动

前面的文章我们提到过,想接设备先看官方驱动库的支持情况。能用支持的设备就买支持的,没有支持的,可以参考官方的驱动库,或者参考其他人的开源项目。再不行我们找官方的类似的驱动,改巴改巴,也能用。这里我就找到了官方的 Ili934x TFT LCD 驱动库,我们可以参考这个库的设计思路,来编写 NV3030B LCD 的驱动。

这个库的大部分代码都是可以拿来直接用的,我们只需要修改一些初始化和一些细节代码就可以了。这里我们就以这个库为基础,来编写 NV3030B LCD 的驱动。

4.1 使用 Github Copilot 快速进行项目搭建

当然,大模型时代,谁还自己写代码呢?写是不可能写的,这些脏活累活,都是交给 AI 去做。我们只需要告诉 AI 我们要做什么,AI 就会帮我们生成代码。现在,我们直接祭出 Github Copilot 大法,当他参考 Python 驱动按照 Ili934x 库的实现,帮我们完成 NV3030B 驱动:

请添加图片描述

当然,AI 生成的代码不是百分百准确的,我们还是需要自己进行逐个审核,确保代码的正确性。这里我们就不一一列举了。然后,逐步根据 AI 的生成情况,或自行修改或引导 AI 生成正确的代码。

对于 GitHub Copilot 目前最好用的 IDE 我感觉还是 VS Code,至少比 Visual Studio 里面集成的 GitHub Copilot 使用体验更好一些。这两个 IDE 各有优缺吧,我一般是配合使用。

再次强调,一定要做好审核,这里画个重点,后面要考。

对于这个驱动,因为我们是参考的 Ili934x 驱动库,这库继承自 GraphicDisplay 类,所以我们也继承这个类,需要安装下面的库:

dotnet add package Iot.Device.Bindings.SkiaSharpAdapter

4.2 需要修改的地方

虽然 AI 帮我们生成了大部分代码,但是还是有一些地方需要我们手动修改的,使其符合我们的偏好,并纠正一些错漏的地方。相对于原始的 Ili934x 驱动库,我们需要修改的地方其实不多,主要是在构造类主文件和 Command 文件中。

对于 Command 文件,我们需要根据 NV3030B 的数据手册,修改一些初始化命令,以及一些特殊的命令。这里直接按照 Python 驱动的初始化命令来修改即可。AI 这里虽然帮了大忙,但是最后因为调试没通过,后面将这个命令还有初始化的实现代码,一个一个核对了好几遍 o(╥﹏╥)o

除了初始化代码外以及基础配置信息,如频率和屏幕大小外,还有一些细节代码需要修改:

SetWindow 方法,按照 Python 的驱动 y0y1 有一个偏移,这里我们也需要做同样的偏移:

/// <summary>
/// Set display window for drawing
/// </summary>
private void SetWindow(int x0, int y0, int x1, int y1)
{
    y0 += 20;
    y1 += 20;
    /* ...  */
}

其他的基本不需要修改,这里我们优化了一下调光,原始的只有高低电平,我们这里增加了一个 PWM 调光,这样可以更好的控制亮度:

public NV3030B(SpiDevice spiDevice, int dataCommandPin, int resetPin, int backlightPin = -1, int backlight_frequency = 1000,
            int spiBufferSize = DefaultSPIBufferSize, GpioController? gpioController = null, bool shouldDispose = true)
{
    /* ...  */
    if (_backlightPin != -1)
    {
        _gpioDevice.OpenPin(_backlightPin, PinMode.Output);
        _backlightChannel = new SoftwarePwmChannel(backlightPin, backlight_frequency,controller: _gpioDevice);
        _backlightChannel.Start();
        SetBacklight(100);
    }
    /* ...  */
}

/// <summary>
/// Set backlight brightness (0-100)
/// </summary>
public void SetBacklight(int brightness)
{
    if (_backlightChannel is null)
        throw new InvalidOperationException("Backlight pin not configured");

    if (brightness < 0 || brightness > 100)
        throw new ArgumentOutOfRangeException(nameof(brightness), "Brightness must be between 0 and 100");

    double dutyCycle = brightness / 100.0;
    _backlightChannel.DutyCycle = dutyCycle;
}

至此,我们应该修改的差不多了,应该算是完成了 NV3030B 的驱动编写。但是这还不算完,半场开香槟,可不可取,还需要测试。

5. 测试驱动

在测试之前,我们需要编写一个简单的测试程序,用于初始化显示屏并显示一些内容,需要有基本的图形绘制还有图片显示测试,图片可以直接使用 Python 驱动的测试图片 LCD_1inch5.jpg

// 测试基本图形
display.ClearScreen(System.Drawing.Color.Red, true);
Task.Delay(10000).Wait();

Console.WriteLine("Testing fill rectangle...");
display.FillRect(System.Drawing.Color.Blue, 0, 0, 100, 100);
display.FillRect(System.Drawing.Color.Green, 100, 0, 100, 100);
display.SendFrame(false);
Task.Delay(10000).Wait();

using var image = BitmapImage.CreateFromFile("LCD_1inch5.jpg");
display.DrawBitmap(image);

发布程序到树莓派上,运行测试程序,观察显示屏是否正常显示内容。如果一切正常,恭喜你,你已经成功编写了 NV3030B 的驱动。然而,这里我们不出意外的出了意外:

请添加图片描述

整个图片展示倾斜割裂,这还是我们的正方形嘛 (▼へ▼メ)

然后,我便开始了四五天之久的 Debug ,期间也问过了各种大模型,试了给出的各种建议,都没有解决问题。经过几番测试,在原始的 LCD_1inch5.pyShowImage 方法增加文件处理后的数据保存后,使用 .NET 读取二进制直接发送到屏幕,竟然是正常显示的。根据这个突破口,最后发现竟然还是 SetWindow 方法的问题,在 Python 中除了 +20 的调整外,还有 -1 的调整,而原始库 Ili9341 直接发送 byteSendBitmapPixelData 方法是有一个 -1 的操作,所以是正常的。

终于是破案了,但是这个问题也是让我头疼了好几天,和大模型的几番较量,有时候是真嘴硬啊,承认,但就是不改。

所有你前面用大模型省下的代码,当有坑的时候,都会变成你爬坑时流下的泪。

不过吧,也算好事,原来是大模型熟悉这个代码,现在我也算烂熟了,等后面有时间,有多个显示屏接入了,提取个基类,把这些共有的部分提取出来,并做个深度优化,方便后面快速接入新的显示屏。

6. 最后

驱动编写完成后,我们可以将其发布到 NuGet 上,方便其他开发者使用。这里我们就不展开了,项目已开源,有兴趣的可以参考 NV3030B。

在这篇文章中,详细介绍了如何从零开始为 NV3030B 编写一个.NET IoT 设备驱动。通过验证SPI接线和设备的正常运行,逐步迁移 Python 代码到 .NET,最终实现了驱动的编写和测试。希望这篇文章能帮助你更好地理解和掌握.NET IoT开发。如果你有任何问题或建议,欢迎在评论区留言。


http://www.kler.cn/a/584684.html

相关文章:

  • 第54天:Web攻防-SQL注入数据类型参数格式JSONXML编码加密符号闭合复盘报告
  • JVM 详解:Java 虚拟机的核心机制
  • k8s中的控制器的使用
  • DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_06带搜索功能的固定表头表格
  • Linux C++ 编程死锁详解
  • MyBatis一对多查询方式
  • uniapp实现 uview1 u-button的水波纹效果
  • Jump Desktop for Mac v9.0.94 优秀的远程桌面连接工具 支持M、Intel芯片
  • 数据结构——顺序表seqlist
  • PostgreSQL16 的双向逻辑复制
  • Netty基础—4.NIO的使用简介一
  • 【贪心算法5】
  • 使用DeepSeek完成一个简单嵌入式开发
  • 如何优化AI模型的Prompt:深度指南
  • 基于jvisualvm的内存监控与远程连接配置指南
  • K8s 1.27.1 实战系列(十)PV PVC
  • C# Unity 唐老狮 No.9 模拟面试题
  • Vue:其他指令
  • Qt的QMenu 和 QAction的样式设置
  • golang从入门到做牛马:第二十篇-Go语言接口:行为的“契约”