SML with マイコンボード
この記事はML Advent Calendar 2014 14日目の記事です。
最近は、お仕事でマイコンボードプログラミングを書いています。
現在はBeagle Bone Black(以下BBB)をいじっています。
ところでこのマイコンボードはArmでフルのLinuxを動かすことができます。
さらにこんなコメントが。
mltonってARM対応してましたよね…
もちろんBBBは各種GPIOやLEDをLinuxのファイルシステムとして提供してくれています。
つまりファイルの読み書きさえできて、Arm対応の言語なら何でもマイコン操作ができるはずです。
そこで今回はMltonによるマイコンボードプログラミングを紹介します。
環境
- Beagle Bone Black (Rev C)
- Ubuntu 14.10 utopicをインストール済み
- apt-getでMltonのインストール済み
Beagle Bone BlackのGPIOの操作方法
- 以下のサイトを参考にしました
- shellからの操作がとても参考になる。
- ピン番号についての一覧エクセル/PDFも便利。
http://www.si-linux.co.jp/techinfo/index.php?BeagleBoneBlack
# echo 60 > /sys/class/gpio/export # 60番GPIOを使用 # 新しいディレクトリgpio60ができる # echo out > /sys/class/gpio/gpio60/direction # outputに指定 # echo 0 > /sys/class/gpio/gpio60/value # HIGH出力 # echo 1 > /sys/class/gpio/gpio60/value # LOW出力
SMLによるGPIOモジュールの例(Arduino風)
上記シェルコマンドの動作をそのまま落とし込むだけです。
100行以下の小さなお試しプログラムです。
(* DIGITAL_GPIO.sig *) signature DIGITAL_GPIO = sig type pin = int datatype mode = OUTPUT | INPUT (* | INPUT_PULLUP *) datatype value = HIGH | LOW val pinMode : pin * mode -> unit val digitalWrite : pin * value -> unit (* 省略 val digitalRead : pin -> value *) end
(* DigitalGPIO.sml *) structure DigitalGPIO : DIGITAL_GPIO = struct type pin = int datatype mode = OUTPUT | INPUT datatype value = HIGH | LOW val path = "/sys/class/gpio" fun startPin pin = let val path = path ^ "/export" val outs = TextIO.openOut path val () = TextIO.output (outs, Int.toString pin) val () = TextIO.closeOut outs in () end fun setMode (pin, mode) = let val path = path ^ "/gpio" ^ Int.toString pin ^ "/direction" val modeString = case mode of OUTPUT => "out" | INPUT => "in" val outs = TextIO.openOut path val () = TextIO.output (outs, modeString) val () = TextIO.closeOut outs in () end handle IO.Io error => () fun pinMode (pin, mode) = let val () = startPin pin val () = setMode (pin, mode) in () end fun digitalWrite (pin, value) = let val path = path ^ "/gpio" ^ Int.toString pin ^ "/value" val v = case value of HIGH => "1" | LOW => "0" val outs = TextIO.openOut path val () = TextIO.output (outs, v) val () = TextIO.closeOut outs in () end end
(* Main.sml *) structure Main : sig val main : unit -> unit end = struct fun init () = DigitalGPIO.pinMode (60, DigitalGPIO.OUTPUT) fun loop () = let val () = DigitalGPIO.digitalWrite (60, DigitalGPIO.HIGH) val () = OS.Process.sleep (Time.fromReal 0.5) val () = DigitalGPIO.digitalWrite (60, DigitalGPIO.LOW) val () = OS.Process.sleep (Time.fromReal 0.5) in loop () end fun main () = (init (); loop ()) end val () = Main.main ()
できたプログラムをBBB上で実行すると、P9-12番ピン - GND間に繋いだLEDが1秒周期でチカチカします。
やったね!
setMode関数でIo例外を握りつぶしています。
実行初回だけdirectionファイルがビジー状態のエラーがでるためです。
もしかするとexport設定後のdirectionファイルへのアクセスが早過ぎる?
この辺はまだ調査中です。