树莓派(香橙派)通过.NET IoT 操作SPI编写屏幕驱动 顺手做个四足机器人(一)

摘要

这片文章主要是记录自己的整活过程,涉及到的技术包括.NET IoT, .NET Web, .NET MAUI,框架采用的也是最新的.NET 7。

本人是用的树莓派Zero 2 W(ubuntu-22.04)进行开发测试,但是.NET IoT库也有社区张高兴提交的香橙派GPIO引脚的映射,香橙派型号对应的驱动。主要预算不够的.NET开发老哥可以尝试用香橙派改改代码跑跑看,回头我再实机测试。

项目开源地址-Verdure.Kame.DotNet

.NET IoT操作SPI编写屏幕驱动

有图有真相

测试图

关于什么是SPI大家可以先看完张高兴的一篇文章温习下:

张高兴的 .NET IoT 入门指南:(四)使用 SPI 进行通信

在知道什么是SPI之后,大概应该知道我们要做什么了,我们买的屏幕通讯协议有很多种,我呢恰好选择了这个SPI协议的屏幕,厂家的文档中心,会有详细介绍。

SPI初始化=>传输图片数据=>屏幕正常显示

屏幕使用文档

屏幕使用的时序图

上图表示我们需要如何传输图片数据,才能正常使用,下面我引用文档的介绍。

本款LCD使用的内置控制器为ST7789V3,是一款240 x RGB x 320像素的LCD控制器,而本LCD本身的像素为172(H)RGB x 320(V),同时由于初始化控制可以初始化为横屏和竖屏两种,因此LCD的内部RAM并未完全使用。
该LCD支持12位,16位以及18位每像素的输入颜色格式,即RGB444,RGB565,RGB666三种颜色格式,本例程使用RGB565的颜色格式,这也是常用的RGB格式
LCD使用四线SPI通信接口,这样可以大大的节省GPIO口,同时通信是速度也会比较快

我买的屏幕分辨率是172 * 320的,支持16位色,一张图片传输的总数据为172 * 320 * 2字节。

大家可以参考文档里的python代码和我的实现进行学习屏幕驱动的简单编写,由于我不是专业的嵌入式我就不展开了。

屏幕芯片驱动程序的构造函数

        public ST7789V3(int dataCommandPin,
            SpiDevice sensor,
            int resetPin = -1,
            PwmChannel? pwmBacklight = null,
            PinNumberingScheme pinNumberingScheme = PinNumberingScheme.Logical,
            GpioController? gpioController = null,
            bool shouldDispose = true)
        {
            if (dataCommandPin < 0)
            {
                throw new ArgumentOutOfRangeException();
            }
            _dataCommandPin = dataCommandPin;
            _pwmBacklight = pwmBacklight;
            _pwmBacklight?.Start();

            _sensor = sensor ?? throw new ArgumentNullException(nameof(sensor));

            _gpio = gpioController ?? new GpioController(pinNumberingScheme);
            _resetPin = resetPin;
            _shouldDispose = shouldDispose || gpioController is null;
            Initialize();
        }

数据传输的代码如下:

      public void SpiWrite(bool isData, ReadOnlySpan<byte> writeData)
        {
            Console.WriteLine($"writeData length:{writeData.Length}");

            _gpio.Write(_dataCommandPin, isData ? PinValue.High : PinValue.Low);

            if (writeData.Length > 4096)
            {
                for (int i = 0; i < 26; i++)
                {
                    var query = writeData[(i * 4096)..((i * 4096) + 4096)];
                    _sensor.Write(query);
                }

                var dataLcdList1 = writeData[(26 * 4096)..110080];

                _sensor.Write(dataLcdList1);
            }
            else
            {
                _sensor.Write(writeData);
            }
        }

SPI对数据一次传输的长度有限制,也就是4096字节,所以大家要注意手动分段传输。

1.47寸显示屏c#驱动

目前驱动部分测试是OK的,但是由于图片数据转换到RGB565的时候会有问题,导致有些彩色不太正常,不过黑白ok,就暂时这样使用了。

.NET IoT操作I2C控制16路舵机驱动器

这个舵机驱动部分,社区已经有贡献了,所以我直接通过.NET IoT进行一次封装就可以控制16路舵机驱动器了,有兴趣的可以看下源码和我COPY官方的测试程序。

Pca9685 16路舵机驱动板测试程序

Pca9685 – I2C PWM Driver

16路舵机驱动板

服务端搭建

先来张架构图:
架构图

树莓派主要是用来跑用.NET编写的web服务,然后调用上面提到的驱动驱动屏幕和舵机驱动板,进行相关硬件的操作。

协议文件主要定义了播放图片到屏幕,播放视频到屏幕,四足机器人的舵机控制。

协议文件

服务端很简单,只做简单的数据转发,不处理数据,数据处理放在客户端也就是MAUI程序里进行。

客户端搭建

客户端采用MAUI框架,用到了MAUI对应的windows的特有的库,比如opencvsharp,MAUI客户端的功能目前比较单一,还是等我测试完毕,再加新功能吧。
客户端应用

总结

对于使用.NET进行全场景的开发进行了实践,发现其实还是大有可为的,能够很快的实现一些功能,而不用再花很多的时间学习其他的技术栈。但是MAUI由于平台的不同,有些功能还是需要针对特定的平台进行单独处理,这个就增加了开发的复杂性。

来张四足机器人的全图吧,代码是实现完了,可惜因为疫情,有些零件快递收不到,先来张实体图吧,到时候会把屏幕也放上去,有比较感兴趣的话可以关注我B站账号,到时候放视频上去。

绿荫阿广

组装过后的样子

推荐项目

.NET IoT Libraries

nanoFramework IoT.Device Library repository

RaspberryPi-Minikame

Verdure.Kame.DotNet

Tags: