有这个想法的初衷

喜欢电子和DIY硬件的朋友对稚晖君应该都不陌生,他定期都会分享一些自己做的好玩的硬件,他之前做了一个ElectronBot桌面机器人我就很感兴趣,所以就自己也做了一个。



起初我只是自己开发了一个叫电子脑壳的上位机软件,大家在之前的博客里应该也有见到,是个用WinUI(WASDK)开发的Windows应用软件。

ElectronBot机器人要一直和电脑连接通过应用进行控制,很多的网友都想ElectronBot脱离电脑使用,于是我也想着能有什么好办法,所以也就有了这个标题的想法。

项目代码地址

技术选型

大家想到树莓派肯定就会想起python,大学的时候玩树莓派确实用python比较多,但是作为一个.NET开发人员当然要尝试下.NET的跨平台能力到底如何了。

由于先有了之前写的上位机软件电子脑壳,也想着让之前封装的SDK能够直接用在树莓派上,所以选择.NET是顺理成章的事情了。

  • 应用开发选择.NET框架
  • 通讯方式选择GRPC
  • USB操作选择LibUsbDotNet调用libusb

整体方案如下图:

环境配置

1. 树莓派系统安装及网络配置

树莓派支持的系统有很多种,像官方的Debian,Ubuntu等等。

我平时使用Debian比较多,但是测试的时候好像usb操作有些问题,应该是我用的.net互操作库对Debian支持的不太好,所以我选择了ubuntu的系统。

安装烧录工具,下载系统,然后烧录系统。如下图所示:

目前树莓派Zero 2 W的Ubuntu只有Server版本和Core版本,需要使用命令行做操作。

网络配置可以参考下面的文章进行配置。

树莓派4B ubuntu server ssh服务器部署全过程详解(内网穿透)

能正常联网安装软件就可以了。

2. .NET6的运行环境

由于.NET6 Arm64官方没提供包管理安装,所以需要大家通过脚本,或者下载文件安装。

网络好的可以通过脚本安装,简单,本文以脚本安装示例。

参考文档如下:

使用安装脚本或通过提取二进制文件在 Linux 上安装 .NET

下载安装脚本dotnet-install.sh放到用户家目录

执行以下指令添加执行权限

sudo chmod +x ./dotnet-install.sh

执行指令安装

./dotnet-install.sh -c Current

下载解压结束需要我们配置环境变量,就像windows安装软件一样,配置完环境变量,才可以直接通过dotnet直接使用了,不然是提示找不到指令的。

以下指令是编辑环境变量的,我选择了~/.bashrc,在文档最底部添加环境变量内容。

sudo vim ~/.bashrc

内容

export DOTNET_ROOT=$HOME/.dotnet
export PATH=$PATH:$HOME/.dotnet:$HOME/.dotnet/tools

保存并退出,然后执行dotnet如果正常就可以进行下面的操作了。

实践过程记录

1. GRPC服务的开发与调试

首先用创建一个grpc服务

微软官方的文档协议文件编写介绍

协议文件编写和服务编写

以我的协议内容为例包含了float,bool,bytes类型

float 对应 c# float

bool 对应 c# bool

bytes 对应 c# byte[]

syntax = "proto3";

option csharp_namespace = "Verdure.ElectronBot.GrpcService";

package electronbotactiongrpc;

// The electronbotaction service definition.
service ElectronBotActionGrpc {
// Sends a greeting
rpc PlayEmoticonAction (EmoticonActionFrameRequest) returns (EbHelloReply);
} // The request message containing the user's name.
message EmoticonActionFrameRequest {
float J1 = 1;
float J2 = 2;
float J3 = 3;
float J4 = 4;
float J5 = 5;
float J6 = 6;
bool Enable = 7;
bytes FrameBuffer = 8;
} // The response message containing the greetings.
message EbHelloReply {
string message = 9;
}

然后生成对应的服务代码

主要注意点是bytes类型的转换

服务端写好了以后,就可以写调用端代码了,为了图方便我就在电子脑壳代码里加了调用代码。

WinUI调用GRPC注意事项

直接将gprc相关的东西放到winui项目里好像有一些问题,所以我把它放到了一个库项目里进行操作了。

配置协议文件生成client代码

电子脑壳注入grpc-client

            services.AddGrpcClient<ElectronBotActionGrpc.ElectronBotActionGrpcClient>(o =>
{
o.Address = new Uri("http://192.168.3.236:5241");
});

数据发送端也要注意bytes类型的转换

grpc服务的打包发布

打包的时候选择目标运行时为可移植(windows和linux都可以运行)

项目代码地址

2. 服务的部署与效果验证

通过ftp工具将grpc服务放到树莓派上,首先需要连接ElectronBot之后再运行服务

进入项目所在目录执行指令如下:

 dotnet Verdure.ElectronBot.GrpcService.dll --urls="http://*:5241"

如果通讯正常,那么应该会报错,提示libusb找不到,系统已经安装了libusb,只是.net调用的时候目录没有找到,需要我们创建软连接。

LibUsbDotNet README最底部有说

树莓派实际操作如下:

  sudo find / -name "libusb-1.0*.so*" //列出库的目录位置
cd /usr/lib/aarch64-linux-gnu/ //进入库所在目录
sudo ln -s libusb-1.0.so.0 libusb-1.0.so //创建链接

通过上面的操作 libusb的操作应该就没有问题了。

运行的效果如下图:

特殊问题与心得体会

最大的一个问题就是在sdk放到linux系统上测试写入数据异常。

  • 需要sdk单独处理linux环境
  • 需要sdk补一些内核驱动卸载逻辑
  • 特别注意otg数据线不要使用那种一拖几的,用一个口的就行不然数据发送不过去

由于使用的LibUsbDotNet上述逻辑没暴露到上层,我只好拉了一个分支改了发了一个包,问pr也没人理我。

sdk内部特别处理的代码如下:

执行了一个设备的SetAutoDetachKernelDriver

if (wholeUsbDevice.DriverMode == UsbDevice.DriverModeType.MonoLibUsb)
{
_logger.LogInformation("MonoLibUsb DetachKernelDriver"); var retDetach = wholeUsbDevice.SetAutoDetachKernelDriver(true); _logger.LogInformation(retDetach.ToString());
}

通过这次的尝试,我算是明白了理想很丰满,现实很骨感的意思,本来觉得树莓派Zero 2 W小巧便携,而且我只是用它接收数据发送数据,结果数据发送的时候屏幕的刷新很慢,不知道是性能差劲,还是usb传输是瓶颈。下次换个4b进行测试一下。

至此整个过程就分享完了,这个项目基本上涵盖了.net技术内的很多东西,如果ElectronBot和树莓派结合独立以后能够很好的使用,我觉得用MAUI开发一个手机端的管理工具也是顺理成章了,可以期待一下,能看到这里的可以在评论区给点意见了。

电子脑壳 GRPC服务项目代码地址

LibUsbDotNet地址

树莓派Zero 2 W(ubuntu-22.04)通过.NET6和libusb操作USB读写的更多相关文章

  1. Qemu/Limbo/KVM镜像 Ubuntu 22.04 精简版,可运行Windows软件,内存占用不到200M

    镜像特征: Ubuntu 22.04系统 内置Wine 7.8,可运行大量Windows 软件 高度精简,内存占用仅200M不到. 自制UI,Windows3.1风格. 完全开源 镜像说明: 用户名为 ...

  2. Ubuntu 12.04下LVM2安装和操作实验

    实验环境: VirtualBox v4.3.20 Lubuntu 12.04LTS 前期准备: 1.添加虚拟盘:菜单"控制"->"设置"->&quo ...

  3. 三十项调整助力 Ubuntu 13.04 更上一层楼

    在Ubuntu 13.04 Raring Ringtail安装完成之后,我们还有三十项调整需要进行. 1.Ubuntu 13.04 Raring Ringtail安装完毕后,我又进行了一系列工作 大家 ...

  4. Ubuntu 20.04安装Docker

    Docker学习系列文章 入门必备:十本你不容错过的Docker入门到精通书籍推荐 day1.全面的Docker快速入门教程 day2.CentOS 8.4安装Docker day3.Windows1 ...

  5. 新版 Ubuntu 中 gnome-terminal 可恶的行间距问题逼我退回了 Ubuntu 20.04

    不知道从什么时候起(可能是 Ubuntu 21.04,也可能是 Ubuntu 21.10),Ubuntu 中的 gnome-terminal 的行间距就加大了,看起来极其不爽,特别是和 Powerli ...

  6. tips of my ubuntu 16.04 LTS

    update_0 : sudo .../idea.sh 才会把idea安装上,不加sudo也会启动,但是不会在开始菜单中找到程序. ---------------------------------- ...

  7. 树莓派初体验,安装Ubuntu 14.04 LTS

    转载自:http://www.polarxiong.com/archives/%E6%A0%91%E8%8E%93%E6%B4%BE%E5%88%9D%E4%BD%93%E9%AA%8C-%E5%AE ...

  8. 树莓派Ubuntu 16.04 MATA系统 修改用户文件夹名后,提示configure it with blueman-service

    自从修改了树莓派的Ubuntu 16.04 MATA 系统的 /home/ 下的用户文件夹名后,使用vncserver远程操作,看到桌面每次都提示 Configured directory for i ...

  9. 树莓派3b+ Ubuntu 16.04 MATA系统 ssh远程登陆后修改主机名、用户密码和用户名

    写在前面: 刚刚开始写博客,记录下自己的学习过程,备忘. 最近在使用树莓派做智能小车的开发,使用的是树莓派3b+,安装的是Ubuntu 16.04 MATA 系统,安装系统后需要修改主机名,登陆密码以 ...

随机推荐

  1. C#/VB.NET 将PPT或PPTX转换为图像

    C#/VB.NET 将PPT或PPTX转换为图像 由于大多数便携式设备支持浏览图片而不支持浏览PowerPoint 文件,所以相比较而言,图像对于用户而言更加友好.除此之外,将PowerPoint文档 ...

  2. 11中javascrip教程教不到的小技巧

    1.过滤唯一值 Set对象类型是在ES6中引入的,配合展开操作...一起,我们可以使用它来创建一个新数组,该数组只有唯一的值. 1 const array = [1, 1, 2, 3, 5, 5, 1 ...

  3. 【原创】Magisk Root隐藏模块 Shamiko安装

    本文所有教程及源码.软件仅为技术研究.不涉及计算机信息系统功能的删除.修改.增加.干扰,更不会影响计算机信息系统的正常运行.不得将代码用于非法用途,如侵立删! Root隐藏模块 Shamiko安装 操 ...

  4. Docker 容器虚拟化

    Docker 容器虚拟化 1.虚拟化网络 Network Namespace 是 Linux 内核提供的功能,是实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,它们有独自网络栈信息.不管是虚拟机 ...

  5. ShardingSphere-JDBC实战

    一.环境准备 1.数据库 创建2个库2个表: xdclass_shop_order_0 product_order_0 product_order_1 ad_config product_order_ ...

  6. java学习第一天.day02

    整数类型常量 整数类型的常量JVM默认使用 int 类型来存储 小数类型类型 小数类型的常量JVM默认使用 double 类型来存储 . ASCII表 A在码表的顺序是65,a在码表的顺序是97

  7. 「雅礼集训 2017 Day7」跳蚤王国的宰相(树的重心)

    题面 来源 「 雅 礼 集 训 2017 D a y 7 」 跳 蚤 王 国 的 宰 相   传 统 2000   m s 1024   M i B {\tt「雅礼集训 2017 Day7」跳蚤王国的 ...

  8. 「学习笔记」单调队列优化dp

    目录 算法 例题 最大子段和 题意 思路 代码 修剪草坪 题意 思路 代码 瑰丽华尔兹 题意 思路 代码 股票交易 题意 思路 代码 算法 使用单调队列优化dp 废话 对与一些dp的转移方程,我们可以 ...

  9. Oracle 与 PostgreSQL 函数行为的差异引发性能差异

    对于Oracle,对于数据修改的操作通过存储过程处理,而对于函数一般不进行数据修改操作.同时,函数可以通过 Select 进行调用,而存储过程则不行. 一.对于volatile 函数的行为 1.Ora ...

  10. Java学习笔记:基本输入、输出数据操作实例分析

    Java学习笔记:基本输入.输出数据操作.分享给大家供大家参考,具体如下: 相关内容: 输出数据: print println printf 输入数据: Scanner 输出数据: JAVA中在屏幕中 ...