arduinoで遊ぶのになるべく高級言語を使いたい。
Haskellでarduinoを扱うためのライブラリはHaskell Wikiにまとまっている。
arduinoを扱うのに好きな言語を使うにはFirmata protocolがよく利用されてるようです。
arduinoにFirmataでおしゃべりできるようになるにファームウェアをいれてシリアルポートでFirmataでおしゃべりしてarduino操作します。
このfirmata用のHaskellライブラリにはhArduinoがあります。
また、firmataから派生したものとして独自に進化したのがhaskinoっぽいです。
そして、Haskellでファームウェアを生成できるライブラリのfrp-arduinoがあります。
名前の通り、arduinoでFunctinal Reactive Programming可能にするようです。
Firmataを利用するとMacなり、ラズパイなりなにかとシリアル通信していないといけないし、かといってC言語っぽい言語も書きたくないので、frp-arduinoで遊んで見ることにしました。
公開されてる 0.1.0.3 のfrp-arduinoはghc 7.10.3だとうまくビルドできませんでした。githubのmasterは対処がしてあったので、stack.yamlのpackagesにgitリポジトリを指定して利用しました。
packages:
- '.'
- location:
git: git@github.com:frp-arduino/frp-arduino
commit: cf463a0f9a1f9a36d1d760994adccd74c4e82123
Lチカのサンプルコードはこんな風になっています。
import Arduino.Uno
main = compileProgram $ do
digitalOutput pin13 =: clock ~> toggle
このプログラムを実行するとpin13がチカチカするmain.c
が生成されます。C言語ファイルが生成されます。
あとはこのmain.c
をコンパイルして、arduinoにアップロードします。
OS Xでのアップロード手順
arduino用の実行ファイルをつくるためにコンパイラなどなどをインストールします。
$ brew tap osx-cross/avr
$ brew install avr-libc
arudinoと通信するmakeファイルが簡単につくれるarduino-mk
をインストールします。
$ brew tap sudar/arduino-mk
$ brew install arduino-mk
このarduino-mkがpyserialを使うようなので好みの方法でいれます。
$ easy_install -U pyserial
あとは適当にMakefileをかきます。
NO_CORE = Yes
BOARD_TAG = uno
MCU = atmega328p
F_CPU = 16000000L
AVRDUDE_ARD_PROGRAMMER = arduino
AVRDUDE_ARD_BAUDRATE = 115200
include /usr/local/opt/arduino-mk/Arduino.mk
make upload
を実行すればarduinoにインストールできます。
遊んだコードなど
pinを指定すればLチカできる関数は以下の感じです。
blickBasic pin = digitalOutput pin =: clock ~> toggle
チカチカ速度を調整するにはclock = every 10000
となってるので
blinkSpeed pin speed = digitalOutput pin =: every speed ~> toggle
で変えることができました
点灯しっぱなしにしたいなら
eternalHigh pin = digitalOutput pin =: clock ~> mapS (const bitHigh)
なのでできました。clockが来るたびにbitHighになるようにしてるだけです。
uart
を使うとシリアルポートからアウトプットができました。
接続するとカウントアップする処理とかかいてみました。
import Arduino.Uno
main = do
compileProgram $ do
uart =: clock ~> foldpS (\_ state -> state + 1) 0
~> mapSMany formatDelta
~> flattenS
formatDelta :: Expression Word -> [Expression [Byte]]
formatDelta delta = [ formatString "delta: "
, formatNumber delta
, formatString "\r\n"
]
感想
ハードウェアとFPRって相性いいと思います。
グローバルな変数をつくる方法がわからない。