11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Haskellでarduino(主にfrp-arduino)

Last updated at Posted at 2016-05-25

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リポジトリを指定して利用しました。

stack.yaml
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って相性いいと思います。

グローバルな変数をつくる方法がわからない。

試した時のコード

eiel/frp-arduino-sample

LTしたときの資料

参考

11
8
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
11
8

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?