7
1

More than 1 year has passed since last update.

[Python/Linux/SoC FPGA] プッシュボタンを押すと LINE に通知が飛ぶ Python アプリを、SoC FPGA に実装してみた

Last updated at Posted at 2022-12-02

もくじ

1.はじめに
2.環境
3.構成
4.準備 ~Linux 環境作成~
5.準備 ~Linux 上で GPIO の制御方法の確認~
6.準備 ~LINE の送信~
7.Python コード
8.実行結果
9.おわり

1.はじめに

以前、Intel® Cyclone V SoC のキット(Atlas)と PC を LAN ケーブルで繋ぎ、Python で UDP パケット通信させてみた の記事を作成した際、SoC FPGA を Python で動かすことができれば、色々面白そうと思いました。

センサーで取得したデータや FPGA 側のデータを、Python の豊富なライブラリで扱えると、夢が広がりますよね。
今回はまず手始めとして、プッシュボタンが押されたら、LINE へ通知 & LED の点灯、という Python アプリを作成してみました。
まずは成果物を見たい方は、下記リンクで飛んでみてください。
8.実行結果

ぜひ、最後まで読んでみてください!

2.環境

  • 使用ボード
    Terasic 社 DE0-nano-SoC(Atlas)
    ※Intel® Cyclone V SoC が搭載されています。

  • Linux 環境
    Rootfile System -> Poky
    Linux Kernel version -> 5.15.70

  • Python
    Python version -> 3.10.7

3. 構成 & 動作手順

■構成
HPS 内の CPU(Cortex-A9)に Linux を実装し、こちらの環境で Python プログラムを実行します。

使用するインターフェースは、GPIO、UART、LAN ケーブルです。

  • GPIO: LED とプッシュボタンの制御
  • LAN ケーブル: 携帯へ LINE を送信
  • UART: PC で HPS を制御及びモニタ
    image.png

■動作手順
手順は大まかに図の中に示した ① ~ ③ です。
①. プッシュボタンを押す
②. LED を点灯
③. LINE にプッシュボタンが押されたことを通知

4. 準備 ~Linux 環境作成~

下記資料を参考に Linux が起動するまでの環境を作成しました。
Building Bootloader for Cyclone V and Arria 10

5. 準備 ~Linux 上で GPIO の制御方法の確認~

Atlas に Linux 環境を実装し、下記フローで GPIO は制御できるのを確認しました。

~
a.  /sys/class/gpio/ へ移動
b.  使用したい GPIO の番号を export に書き込み
c.  /sys/class/gpio/ 下に gpio<番号> のディレクトリが作成されていることを確認
d.  /gpio<番号>/direction で、入出力設定
e.  /gpio<番号>/value で、入力なら値を確認、出力なら値を設定
f.  使用し終わったら、GPIO の番号を unexport に書き込み
g.  gpio<番号> ディレクトリが削除されていることを確認
~

実際に GPIO を制御したログを以下に記載します。

GPIO 制御ログ
■LEDの GPIO 動作確認
root@cyclone5:/sys/class/gpio#
root@cyclone5:/sys/class/gpio# ls
export        gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio# echo 2014 > export
root@cyclone5:/sys/class/gpio# ls
export        gpio2014      gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio# echo out > gpio2014/direction
root@cyclone5:/sys/class/gpio# echo 1 > gpio2014/value
root@cyclone5:/sys/class/gpio# echo 0 > gpio2014/value
root@cyclone5:/sys/class/gpio# echo 2014 > unexport
root@cyclone5:/sys/class/gpio# ls
export        gpiochip1963  gpiochip1990  gpiochip2019  unexport


■プッシュボタンの GPIO 動作確認
root@cyclone5:/sys/class/gpio# ls
export        gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio# echo 2015 > export
root@cyclone5:/sys/class/gpio# ls
export        gpio2015      gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio# echo in > gpio2015/direction
root@cyclone5:/sys/class/gpio# cat gpio2015/value
1
root@cyclone5:/sys/class/gpio# cat gpio2015/value
0
root@cyclone5:/sys/class/gpio# echo 2015 > unexport
root@cyclone5:/sys/class/gpio#
root@cyclone5:/sys/class/gpio# ls
export        gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio#

※export に登録する GPIO の番号の補足
使用したい GPIO の番号を export に書き込みますが、
その際、GPIO の番号にオフセットを足す必要があります。

本来、プッシュボタンと LED の GPIO の番号は下記です。
(export に登録するオフセットを足した値は()の中に記載しています)

  • プッシュボタンの GPIO: 54(export に登録する値 -> 2015)
  • LED の GPIO: 53(export に登録する値 -> 2014)

オフセットの求め方を以下に記載していますが、
特に興味が無ければ、6. 準備 ~LINE の送信~ まで読み飛ばして大丈夫です。

■オフセットの求め方
トータル 85 本の GPIO は 3 グループに分かれています。

GPIO Pin Number Address
gpio0 [28:0] 0xFF70_8000
gpio1 [57:29] 0xFF70_9000
gpio2 [84:58] 0xFF70_A000

/sys/class/gpio/ 下の、それぞれの gpiochipXXX 内の label を確認すると、
下記のようになっていました。
gpiochip2019/label: ff708000.gpio
gpiochip1990/label: ff709000.gpio
gpiochip1963/label: ff70a000.gpio

gpiochip2019 は gpio0、gpiochip1990 は gpio1、gpiochip1963 は gpio2 を表しているのかと思います。
gpiochip"xxx" の xxx を各 gpio0~2 のそれぞれのオフセットとします。
gpio0: 1963、gpio1: 1990、gpio2: 2019

例えば、今回の LED の GPIO[53] の場合、
gpio1 に含まれるので、gpio1[24]となります(53-29(gpio0))。
24 に gpio1 のオフセットを足しますので、
24 + 1990 = 2014
となります。

(下記 label の値を確認したときのログ)

label 確認ログ
root@cyclone5:/sys/class/gpio# ls
export gpiochip1963  gpiochip1990  gpiochip2019  unexport
root@cyclone5:/sys/class/gpio# cat gpiochip1963/label
ff70a000.gpio
root@cyclone5:/sys/class/gpio# cat gpiochip1990/label
ff709000.gpio
root@cyclone5:/sys/class/gpio# cat gpiochip2019/label
ff708000.gpio
root@cyclone5:/sys/class/gpio#

6. 準備 ~LINE の送信~

LINE へメッセージを送る際には、LINE notify を使用しています。
LINE notify については、下記記事で紹介されていましたので、こちらを参考にしてみてください。
PythonでLINE Notifyへ通知を送る

下記コードを使用し、LINE へメッセージ(Hello!)が送れることを確認しました。

LINE_send_test.py
import requests

def send_line_notify(notification_message, package_id, sticker_id):
    line_notify_token = <LINE notify のトークン>
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f'{notification_message}', 'stickerPackageId': package_id, 'stickerId': sticker_id}
    requests.post(line_notify_api, headers = headers, data = data)

send_line_notify('Hello!', 4, 303)

7. Python コード

GPIO の制御と LINE へのメッセージ通知を合わせ、最終的なコードは下記のようになりました。

Button_LED_LINE.py
import subprocess
import requests
import datetime

print('=====Start!=====')

print('Open GPIO')
subprocess.run('echo 2015 > /sys/class/gpio/export', shell=True)
subprocess.run('echo in > /sys/class/gpio/gpio2015/direction', shell=True)

subprocess.run('echo 2014 > /sys/class/gpio/export', shell=True)
subprocess.run('echo out > /sys/class/gpio/gpio2014/direction', shell=True)

print('Wait Push the KEY...')
def send_line_notify(notification_message, package_id, sticker_id):
    line_notify_token = <LINE notify のトークン>
    line_notify_api = 'https://notify-api.line.me/api/notify'
    headers = {'Authorization': f'Bearer {line_notify_token}'}
    data = {'message': f'{notification_message}', 'stickerPackageId': package_id, 'stickerId': sticker_id}
    requests.post(line_notify_api, headers = headers, data = data)

while True:
    result=subprocess.run('cat /sys/class/gpio/gpio2015/value', shell=True, capture_output=True)
    if result.stdout == b'0\n':
        print('----------')
        t=datetime.datetime.now()
        print(t)
        print('Pushed the KEY!')
        print('LED ON!')
        subprocess.run('echo out > /sys/class/gpio/gpio2014/direction', shell=True)
        subprocess.run('echo 1 > /sys/class/gpio/gpio2014/value', shell=True)
        print('Send the LINE!')
        send_line_notify('Pushed the KEY!', 3, 222)
        print('----------')
        break;
    elif result.stdout == b'1\n':
        pass
    else:
        print('unknow')

print('Close GPIO')
subprocess.run('echo 2015 > /sys/class/gpio/unexport', shell=True)
subprocess.run('echo 2014 > /sys/class/gpio/unexport', shell=True)

print('=====Finish!=====')

8. 実行結果

実行までの流れは以下のアニメーションをご覧ください。
terminal.gif

届いた LINE メッセージと LED の点灯は以下の通りです。
簡単に LINE にメッセージが送れたり、LED の制御ができると、なんだか楽しいですね!
image.png

9. おわりに

手始めとして作成したプログラムですが、LINE へのメッセージや GPIO の制御など、簡単にできて楽しかったです。
やはり、Python のライブラリを活用し何か物を作成することは、とても夢があると感じます!
今後も、Python を用いて色々なことに挑戦してみたいと思いました。

7
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
1