背景
最近幾年,邊緣計算的需求急劇爆發。人工智能、物聯網和 5G 的演進給邊緣計算帶來了無限的可能性。因為工作原因,有幸在2019開始接觸了英偉達 Jetson 家族的各種邊緣計算設備:Nano,TX2,AGX,NX等,其操作系統使用的是 Ubuntu 18.02。我們可以作為獨立的小型服務器使用,試問又有哪一個程序猿會拒絕擁有一臺自己的小電腦呢?在其上,特別是擁有GPU的服務器上,我們可以折騰無限的可能。
在Jetson設備的開發版載板上,一般都有一個40針引腳的SPIO與GPIO,通過它我們可以擴展出更多好玩的東西。比如說:一塊I2C的OLED顯示屏,然后通過.Net來驅動它顯示一些好玩的東西(軟件狀態,設備狀態,其他關鍵數據指標等)。
屏幕安裝
屏幕這里選用的是一塊0.96寸黃藍雙色OLED液晶屏模塊,一共4個接口:3.3V正極VCC,負極GNG,以及負責I2C通訊的SDA和SCL。
那么如何將顯示器與Jetson設備相連呢?這里演示基于早期的Nano開發者套件的載板,其它系列官方載板的引腳基本類似,你也可以查找硬件說明書或參考官網的指引[1]來找到I2C接口即可。
我使用的是I2C1,接的針腳是 1,3,5,6 ,按照定義安裝好OLED 顯示屏。
配置 I2C 總線
安裝好屏幕后,必須要配置I2C,我們自己登錄的賬戶才能在非Root權限下訪問I2C總線。
將下面命令的 username 改為你登錄的賬戶名
sudo usermod -aG i2c username
最好重啟一下設備,如果執行下面命令可以正常顯示,那就也沒啥問題。
i2cdetect -y -r 1
在下圖中,OLED 顯示屏的地址 3c 被特別突出顯示。
用.NET驅動顯示
驅動這個oled屏幕我們需要用到微軟的IoT相關的庫 "System.Device.Gpio" ,通過這個庫我們可以實現和外接設備的I2C通訊,當然驅動OLED顯示器需要用到熟悉其驅動芯片的各種指令,這里的驅動芯片是SSD1306,擁有最大128*64像素支持,廣泛應用在小尺寸OLED顯示屏的驅動中。
在這里我們不介紹相關的驅動和指令相關原理性的東西,我已經將相關指令封裝為一個庫,可以直接使用,庫已開源,感興趣的同學可自行查閱相關知識和源碼。
下面我們通過在Jetson Nano上的使用演示如何使用 “Sang.IoT.SSD1306” 庫來控制OLED顯示畫面。
安裝.Net開發環境
因為 Jetson 是 arm64 的設備,我們直接前往.Net官網選擇下載.Net6[2]的 Arm64 版本。
執行安裝
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-6.0.301-linux-arm64.tar.gz -C $HOME/dotnet
然后更改用戶目錄下``文件,在末尾加入以下環境配置:
export DOTNET_ROOT=$HOME/dotnet
export PATH=$PATH:$HOME/dotnet
運行dotnet
命令檢查安裝情況。
使用演示
創建控制臺程序
dotnet new console -o i2c_oled
添加驅動庫
dotnet add package Sang.IoT.SSD1306
修改代碼
using Sang.IoT.SSD1306;using (var oled = new SSD1306_128_64(1)) {oled.Begin();// 需要發往顯示器的顯示內容byte[] c = new byte[128*64]{...};oled.SetBuffer(c);oled.Display();
}
要想將數組數據顯示到屏幕,就需要將數據存入SSD1306的RAM。這里的RAM大小為128x64位,分為8頁,從0頁到7頁,用于單色128x64點矩陣顯示。
以上代碼可能平時也用不到,主要是自定義的內容顯示接口。
圖片顯示
這里類庫用到了微軟的 SkiaSharp 跨平臺的圖片處理庫,關于跨平臺的圖片處理庫,如果你也有相關需求,可以看這一篇文章來對比了解[3]?。
這里演示用的圖片為下圖,我們將其在 OLED 顯示屏上展示。

using Sang.IoT.SSD1306;using (var oled = new SSD1306_128_64(1)) {oled.Begin();oled.Image("assets/test.png");oled.Display();
}
效果如下:
顯示文字
那么,如何顯示文字呢?當然,一樣的思路,我們首先通過 SkiaSharp 創建位圖,然后顯示出來就可以了,所以加載字體文件顯示中文字體也不是難事。
using Sang.IoT.SSD1306;
using SkiaSharp;using (var oled = new SSD1306_128_64(1)) {oled.Begin();oled.Clear();using(var bitmap = new SKBitmap(128, 64, true)){SKCanvas canvas = new SKCanvas(bitmap);SKPaint paint = new SKPaint() { Color = new SKColor(255, 255, 255),StrokeWidth = 1, //畫筆寬度Typeface = SKTypeface.FromFile("/home/sangsq/i2c_led/SourceHanSansCN-Normal.ttf"),TextSize = 13, //字體大小Style = SKPaintStyle.Fill,};canvas.DrawText("公眾號:sangxiao99 ", 0, 13, paint);paint.TextSize = 30;canvas.DrawText("桑榆肖物 ", 0, 50, paint);oled.Image(bitmap.Encode(SKEncodedImageFormat.Png, 100).ToArray());}oled.Display();
}
效果如下:
清除顯示
oled.Clear();
結語
如果對IoT這個領域比較感興趣或者想折騰手頭的開發板的話,可以前往官網了解更多.Net的IoT資源[4]。
剛剛到了一個SPI接口的LCD彩色顯示屏,又有新玩具可以玩了。
References
[1]
?參考官網的指引:?https://developer.nvidia.com/embedded/learn/getting-started-jetson[2]
?.Net6:?https://dotnet.microsoft.com/en-us/download/dotnet/6.0[3]
?看這一篇文章來對比了解:?https://devblogs.microsoft.com/dotnet/net-core-image-processing/[4]
?.Net的IoT資源:?https://dotnet.microsoft.com/zh-cn/apps/iot