CommonLispでGPIO実験 ~BCM2835ライブラリ編~


CommonLispでGPIO実験 ~BCM2835ライブラリ編~

本章では、タクトスイッチを使ってGPIO入力をやってみます。

【目次】
1.GPIO入力プログラムの作成
2.使用した電子部品
3.回路図
4.実行
5.Lチカと組み合わせる

1.GPIO入力プログラムの作成

Lチカ実験の際にGitHubからダウンロードした「bcm2835.lisp」にはGPIO入力に必要な関数がありません。
なので、それを自分で追加することにしました。

以下に、追加した箇所を記します。

まずは利用できるパッケージを用意。
ここで指定した名前がプログラムで使用できます。

[bcm2835.lisp]
(defpackage :BCM2835 
	(:use :FFI)
	(:export :init
		:close
		:gpio-fsel
		:gpio-write
		:gpio-lev
		:gpio-set
		:gpio-clr
		;; ここから追加
		:gpio-set-pud		; 指定されたピンのプルアップ/ダウン・モードを設定する。
		:gpio-len			; 指定されたピンを有効にし、LOW検出できるようにする。
		:gpio-eds			; ステータスを検出する。
		:gpio-set-eds		; フラグをクリアする。
		;; ここまで追加
		:delay
		:delay-microseconds))
使用するライブラリ関数を定義。
ファイルの最後に以下を追加。

[bcm2835.lisp]
;; 指定されたピンのプルアップ/ダウン・モードを設定する。
(ffi:def-call-out gpio-set-pud
		  (:name "bcm2835_gpio_set_pud")
		  (:arguments (pin ffi:uint8) (pud ffi:uint8))
		  (:language :stdc)
		  (:library "libbcm2835.so"))

;; 指定されたピンを有効にし、LOW検出できるようにする。
;; LOWレベルがピンで検出されると、イベント内の適切なピンが検出状態を設定する。
(ffi:def-call-out gpio-len
		  (:name "bcm2835_gpio_len")
		  (:arguments (pin ffi:uint8))
		  (:language :stdc)
		  (:library "libbcm2835.so"))

;; bcm2835_gpio_ren(), bcm2835_gpio_hen(), bcm2835_gpio_len()など
;; からの要求に応じて、指定のピンがレベルまたはエッジを検出する。
;; bcm2835_gpio_set_eds(pin)を呼び出すことによって、与えられたピンのためのフラグをクリアする。
(ffi:def-call-out gpio-eds
		  (:name "bcm2835_gpio_eds")
		  (:arguments (pin ffi:uint8))
		  (:return-type ffi:uint8)
		  (:language :stdc)
		  (:library "libbcm2835.so"))

;; フラグをクリアする効果があるピンに対して、イベント検出ステータスレジスタに1を設定する。
;; ピンのイベント検出ステータスを見た後に使用すること。
(ffi:def-call-out gpio-set-eds
		  (:name "bcm2835_gpio_set_eds")
		  (:arguments (pin ffi:uint8))
		  (:language :stdc)
		  (:library "libbcm2835.so"))
次に、タクトスイッチが押されたらそれを検出してコンソール画面に出力するプログラムを記します。
今回は入力にGPIO15を使用します。

[input.lisp]
;; bcm2835.lispをロード
(load "bcm2835.lisp")

;; メイン処理
(defun main ()
  (bcm2835:init)
  
  ; P1の15ピンを入力に設定
  (bcm2835:gpio-fsel 15 0)

  ; プルアップする
  (bcm2835:gpio-set-pud 15 2)

  ; LOW検出ができるようにする
  (bcm2835:gpio-len 15)
  
  (loop
    (if (equal (bcm2835:gpio-eds 15) 1)
      (progn
	; 次のイベントを待つためにフラグをセットし直す
	(bcm2835:gpio-set-eds 15)
	(print "押されてるよ!"))
      (print "押されてないよ!"))

    ; 待機
    (bcm2835:delay 500))
  
  (bcm2835:close))

▲上へ

2.使用した電子部品

GPIO入力するにあたって、以下のものを準備しました。

・ タクトスイッチ 1個


・ 10kΩ抵抗(茶黒橙金) 1個


・ オスメスジャンパー線 2本


・ ブレッドボード 1個

▲上へ

3.回路図

回路図は以下のようになります。


▲上へ

4.実行

プログラムを実行して実際に動かしてみます。

GNU CLISPを起動します。
sudo clisp
※ 出力では大丈夫だったのですが、入力では管理者権限が必要なようです。
  なので、「sudo」を付けてCLISPを実行します。

「blink.lisp」をロードします。
(load "input.lisp")
ロードが成功したら、以下のコマンドで実行します。
(main)
※ 終了するときは「Ctrl + c」を入力してください。

以下に、実行した様子を示します。



これにて、GPIO入力成功です。
▲上へ

5.Lチカと組み合わせる

以下にLチカと組み合わせたプログラムを記載します。
タクトスイッチを押したらLEDが点灯、離したら消灯するプログラム

[input_led.lisp]
;; bcm2835.lispをロード
(load "bcm2835.lisp")

;; メイン処理
(defun main ()
  (bcm2835:init)
 
  ; P1の11ピンを出力に設定
  (bcm2835:gpio-fsel 11 1)
  ; P1の15ピンを入力に設定
  (bcm2835:gpio-fsel 15 0)

  ; プルアップする
  (bcm2835:gpio-set-pud 15 2)

  ; LOW検出ができるようにする
  (bcm2835:gpio-len 15)
  
  (loop
    (if (equal (bcm2835:gpio-eds 15) 1)
      (progn
	    ; 次のイベントを待つためにフラグをセットし直す
	    (bcm2835:gpio-set-eds 15)
	    (bcm2835:gpio-write 11 1)	; LED点灯
	    (print "押されてるよ!"))
      (progn
	    (bcm2835:gpio-write 11 0)	; LED消灯
	    (print "押されてないよ!")))
    ; 待機
    (bcm2835:delay 500))
  
  (bcm2835:close))

回路図を以下に示します。


プログラムを実行して実際に動かしてみます。

GNU CLISPを起動します。
sudo clisp
「blink_led.lisp」をロードします。
(load "input_led.lisp")
ロードが成功したら、以下のコマンドで実行します。
(main)
※ 終了するときは「Ctrl + c」を入力してください。

以下に、実行した様子を示します。


Lチカと組み合わせての動作も確認することができました。
今回はこれで終わりです。
お疲れ様でした。
▲上へ