【.NET 與樹莓派】使用 GPIO 庫

東邪獨孤發表於2021-01-16

上回老周在說準備工作的時候,提到過樹莓派用金屬盒散熱的事情。有朋友會說,加了金屬盒子接線不方便,就算用了“T”形板,畢竟是把導線延長了的。其實擴充套件板就是把原有的引腳引出(類似於延長),有的引出後使用並聯電路來“複製”出幾套介面。所以你買一塊插孔多的麵包板,自己也可以並聯出許多擴充套件介面來,何況樹莓派好一點的擴充套件板也比較貴。

如果你不執行桌面,不看島國片,只是執行命令和執行程式碼,完全不用散熱措施。老周直接用裸板試驗過,只是執行程式的話,溫度平均在 40 度上下,受室溫影響不是很大,夏天的時候會高2度。這個溫度問題不大,掛不了。70 度以上才要考慮散熱。

最簡單的散熱方案是貼散熱片,不過你不要貼歪了,想撕下來再貼一次好像不那麼容易,弄不好可能會把晶片扯壞。曾經還聽說有人把處理器扯下來的,不知道是真是假。另外,加個小風扇的方式應該挺好,有點噪音也沒關係的(不要像轟炸機就行)。

好,現在說正題。我們知道,樹莓派有許多 GPIO 引腳,通用方式是發出,或者接收電平訊號。訊號就是兩種——高電平 or 低電平。我們可以簡單地認為,高電平是 3.3 V 電壓,低電平是 0V 電壓,更深層的電路原理你可以不理會,不影響你程式設計。

為什麼是高電平和低電平兩個訊號呢?嗯,問得真TM地好。你想一下啊,計算機只認識兩個數字,哪兩個呢?0 和 1,你給計算機下命令時,其實只要 0 和 1 組合就行。1 開燈,0 關燈;1 向左轉,0 向右轉;0 翻牆,1 撞牆;0 引爆火藥,1 引爆自己……

喲西,這麼一來,兩個電平就可以對應兩個二進位制數字:高電平—— 1,低電平—— 0,完事。

有了兩個明確的值,還需要明確方向。樹莓派自身把電平拉高或者拉低,以此來告訴連線的電子模組要幹什麼活,這是傳送訊號;當一個觸控開關被你的嬌美的小手觸碰後,模組把電平拉高(高電平狀態),告訴樹莓派有人按了按鈕,這時候樹莓派的介面就是接收狀態,然後樹莓派可以控制另一個裝置去做其他事情(比如,衝馬桶)。

由於樹莓派帶有 Linux 作業系統,所以,GPIO 介面的操作方法很多,可以直接呼叫相關的 lib,也可以用一些封裝好的庫。不過,系統整合了一種簡單的操作方法,類似於檔案的方式,你只需要讀寫對應的路徑就能控制 IO 介面。

啟動系統後,你可以進入以下目錄:

cd /sys/class/gpio

然後執行 ls 命令,你會看到目錄下有兩個檔案:

1、export:向這個檔案寫入 GPIO 口的編號,就可以開啟相關介面;

2、unexport:向這個檔案寫入 GPIO 口的編號,關閉對應的介面。

你如果看到這兩個檔案,就可以試驗一下了。不過在試之前,你還要做這件事:

sudo raspi-config

sudo 是為了防止許可權不夠,raspi-config,是樹莓派系統專用的配置程式,在命令模式下也是圖形化操作的。

 

 選第3項,介面選項,回車。

 

 

 用上下箭頭鍵移到最下面的 P8,回車。

 

 

 用 Tab 鍵選中 Yes,預設會選中,然後回車確認,收工。按 Esc 可以退出配置程式(或者選 Finish)。

 

Remote GPIO 選項必須開啟的,不然你連線的電子模組是沒有反應的。

接下來,老周用這個鐳射模組來做演示。

這個模組上面有一個鐳射頭,跟我們小時候在路邊買的裝鈕釦電池的差不多,發出的鐳射比小時候買的玩具還差。那這個模組有什麼鳥用。其實這個模組真沒什麼鳥用,不過用來學習演示挺不錯,現實用途可以拿來逗貓,不過注意不要讓貓碰到微控制器。

這個模組有三個引腳,PCB板上只標註了兩側的引腳。

【.NET 與樹莓派】使用 GPIO 庫

為了提升拍照效果,我在下面墊了一張廁紙。最左邊的引腳旁標註了“-”,意思是接電源負極,即接樹莓派上的 GND 引腳。樹莓派有八個 GND 引腳,你可以隨便接;最右邊的引腳標註了“S”,表示這是訊號腳,接樹莓派的 GPIO 腳,這個有很多了,當然了,最好選預設沒有分配功能的 GPIO 介面。比如下圖中畫了藍線的。

【.NET 與樹莓派】使用 GPIO 庫

 

 左右兩邊的引腳都知道用處了,所以,中間那個引腳就是接電源正極的,可以接樹莓派的 5V,上面的圖上你也看到了,樹莓派兩個 5V 腳都放在了一起(第2、4腳)。

 

下面開始接線,由於樹莓派沒有在板子印有引腳符號(無絲印),所以在接線時要小心,不要接錯。

【.NET 與樹莓派】使用 GPIO 庫

【.NET 與樹莓派】使用 GPIO 庫

訊號線老周選用了 GPIO 17,在樹莓派上是 11 號引腳,也就是左邊一排,往下順數第六個腳。

 

接好線之後,我們回到終端,還記得前面提到的那兩個檔案嗎?先用 cd 命令定位到 /sys/class/gpio 目錄,然後向 export 檔案輸入文字“17”。

cd /sys/class/gpio
echo 17 > export

然後用 ls 列出一下 gpio 下的子項,你是不是發現多了個子目錄?叫 gpio17。

 

這說明 GPIO 的第17口已經準備就緒,可以通訊了。

注意一下,這裡的 GPIO 編號不是樹莓派板子上的順序,而是BCM編號,剛剛接線時接的是左排的第六腳,可以上 pinout.xyz 檢視,這個腳的編號是17。

【.NET 與樹莓派】使用 GPIO 庫

 

 

然後,cd gpio17,進入這個目錄,看看裡面有什麼。

 

這裡面有兩個檔案我們需要用到的。

1、direction:配置 GPIO 口的通訊方向。向其中寫入“in”為輸入,寫入“out”為輸出。

2、value:GPIO 口輸出的值,0 為低電平,1 為高電平。

鐳射頭模組是收到高電平時發射鐳射的,所以這裡要把通訊方向設為 out。

 echo out > direction

向 value 寫入“1”,輸出高電平,發射鐳射,開始逗貓。

echo 1 > value

【.NET 與樹莓派】使用 GPIO 庫

 

逗久了貓也覺得不好玩了,你手也累了,這時向 value 寫入“0”,輸出低電平,關閉鐳射發射。

 echo 0 > value

最後,向 /sys/class/gpio/unexport 寫入GPIO口編號 17,就可以關閉這個介面了。這時候,gpio17 子目錄就不見了。

 

有了上面的試驗,我們可以開始使用微軟封裝的 GPIO 庫了。

這個 Nuget 庫叫 System.Device.Gpio,它已經封裝好了GPIO操作常用的型別。

1、對於Windows平臺,用的是 UWP 的庫;

2、對於類 Unix 平臺,封裝了以下幾種版本:

  1) LibGpio;

  2)SysFsDriver,這個就是上面舉例用的方式,以檔案方式操作 /sys/class/gpio 路徑下的檔案。

  3)Raspberry Pi 專版。

另外,還有 HummingBoard 版本。

我們在使用時,其實並不需要去思考使用哪個平臺的型別,在例項化 GpioController 類的時候,會自動選用合適的型別。

 

使用以下命令,在.NET專案中新增 System.Device.gpio 庫的引用。

dotnet add package system.device.gpio

在VS2019 中,你也可以用非常熟悉的 Nuget 包管理器來新增,操作方法省略,老周相信你會用的了。

在程式碼中引入 System.Device.Gpio 名稱空間,然後就可以歡暢地擼程式碼了。

using System;
using static System.Threading.Thread;
using static System.Console;
using System.Device.Gpio;

namespace testA
{
    class Program
    {
        static void Main(string[] args)
        {
            int pin = 17;
            GpioController gpio = new GpioController();
            // 開啟介面
            gpio.OpenPin(pin);
            // 設定通訊方向
            gpio.SetPinMode(pin, PinMode.Output);
            gpio.Write(pin, PinValue.Low); //先置低電平
            // 也可以這樣寫
            //gpio.Write(pin, 0);

            // 傳送訊號
            int x = 20;
            while (x-- > 0)
            {
                WriteLine("開啟鐳射頭");
                gpio.Write(pin, 1);
                Sleep(1000);
                WriteLine("關閉鐳射頭");
                gpio.Write(pin, 0);
                Sleep(1000);
            }

            // 關閉介面
            gpio.ClosePin(pin);
            gpio.Dispose();
            // 退出
            WriteLine("3166");
        }
    }
}

變數 pin 的值是17,前面接線的時候接的是 GPIO 17 引腳。

 

下一步就是釋出程式碼,釋出到本地目錄就行。
dotnet publish -r linux-arm -c release --no-self-contained

-r linux-arm,就是指定目標的執行時為 arm (32)的 Linux 系統。

-c 指定生成方案,有 Debug 和 Release,這個老周就不多解釋了,.NET 程式習慣模式。

--no-self-contained 表示不包含執行時庫,因為老周已在樹莓派的系統上裝了 dotnet 執行時;如果你不想在上面安裝執行時,可以去掉 --on-self-contained 選項,這樣預設會包含執行時庫。上傳到樹莓派上面,執行 chmod u+x xxxx 提升許可權,然後就可以直接執行了。

要在樹莓派上安裝.NET 執行時也很簡單。

1、執行 cd /tmp 轉到臨時目錄。

2、下載時可以選擇 .NET runtime,或 ASP.NET Core Runtime。後者包含執行Web應用的庫。使用 wget 下載壓縮包(選擇 arm32 的 Linux 包)。

wget https://download.visualstudio.microsoft.com/download/pr/7aa18d1a-1c9a-4571-9668-3d76b5cda367/41a75d18282fa815c548be4dbc9dd55f/aspnetcore-runtime-5.0.2-linux-arm.tar.gz

3、在 /usr/local 目錄下建立一個目錄,叫 dotnet。

sudo mkdir /usr/local/dotnet

這個地方要加上 sudo ,不然許可權不夠。/usr/local 這個目錄很適合,它就是讓我們安裝自己需要的第三方軟體用的。

4、解壓剛剛下載的壓縮包,放到 /usr/local/dotnet 目錄下面。

sudo tar -zxf aspnetcore-runtime-5.0.2-linux-arm.tar.gz -C /usr/local/dotnet

-z 參數列示使用 gz 演算法,-x 表示解壓,-f 表示要解壓的檔案,三個引數合起來就是 -zxf。注意 -C 引數是大寫的,表示工作目錄,也就是你要解壓到哪個目錄,此處解壓到 /usr/local/dotnet 目錄下。

5、在 /etc/profile 檔案中加入以下內容。

# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).

if [ "`id -u`" -eq 0 ]; then
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
else
  PATH="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/local/games:/usr/games"
fi

# .NET 的執行路徑
if [ -d /usr/local/dotnet ]; then
  PATH=$PATH:/usr/local/dotnet
fi

export PATH
……

位置是在 PATH 環境變數匯出之前,將 dotnet 執行時的路徑追加上去。即在 export 命令之前。儲存並退出就OK了。

設定 PATH 變數放在 /etc/profile 中比放在 bash 的資原始檔中好一些。放在bash資源中需要你登入終端時才執行,而且只在當前會話期間可用。放在 /etc/profile 中就成了“全域性”了,只要順利登入系統都有效。

在任意路徑下執行 dotnet --info,如果有以下輸出,那就成功了。

【.NET 與樹莓派】使用 GPIO 庫

 

 

好了,現在可以把我們已經發布的程式上傳到樹莓派了。Win 10 自帶 scp 命令,不需要安裝傳輸工具。

在樹莓派上 cd 到 pi 使用者目錄下(如果你改了使用者名稱,可能是其他名字,可以用“~”代替)。

 cd ~

建立一個新目錄,叫 app

mkdir app

回到 Windows  上,開啟命令提示符視窗,cd 到程式釋出的目錄。

cd C:\Users\<使用者名稱>\...\testA\bin\release\net5.0\linux-arm\publish

執行 scp 命令上傳檔案。

scp ** pi@192.168.200.15:/home/pi/app

其中,**(用一個星號也可以,萬用字元)表示把釋出目錄下的所有檔案上傳到樹莓派;冒號後面是樹莓派上的路徑,把檔案放到前面建立的 app 目錄下面,注意要用絕對路徑,不能用“~”。

用終端登入樹莓派,cd 到app下,能看到剛上傳的檔案。

 

 無比緊張的時刻來臨,執行我們寫好的程式。

dotnet testA.dll

 如果沒有出其他問題的話,你會看到鐳射頭一開一關(其間暫停1秒)。

 示例的原始碼可以點這裡下載:拼命點這裡

 這個 System.device.gpio 庫還封裝了 i2c、SPI 等常見的硬體通訊方式,後續文章中老周還會介紹。

 

相關文章