TokyuRuby会議12で抽選してきた(mruby/cによる抽選マシーン制作)

TechEmbedded, ESP32, Japanese, mruby, mruby/c, Tokyu.rb

TokyuRubyKaigi12
TokyuRubyKaigi12

2018/7/29、台風が接近して開催が危ぶまれましたが、なんとか無事TokyuRuby会議12を開催することができました。参加していただいた皆さんありがとうございます!おかげさまでとても楽しい会になったと思います。

自分は抽選担当として、例によって抽選LT1の抽選を行ってきました。
当日その場でも簡単に何をしているか説明したかったところですが、準備に手間取ってほとんど説明できなかったので、ここに説明を残しておきたいと思います。

過去の抽選方法

過去にもあれこれ抽選の方法を考案してきました。

今回は、何をしたのか

今回は、最近趣味でよく遊んでいるESP32というマイコン上でmruby/cを動かしつつ、抽選してみました。
mruby/cとはmrubyのバイトコードを実行するVMの一種で、mrubyの機能を制限することで、よりリソースが制限されたマイコンでも動くようにしているものです。
詳しくは、こちらなど参照。
http://www.s-itoc.jp/activity/research/mrubyc/mrubyc_about/
パーサーはmrubyのものをそのまま用いています。

せっかく物理的なものを使うわけなので、抽選にはサイコロを用いていました。
サイコロを振る機械はちょうどよいのがAmazonにあったので、それを少しだけ改造して用いています。
具体的にはモーターにつながっている電源スイッチの線を穴を開けて外に端子として出しています。

それをマイコンのGPIOにつながったリレーでON/OFF制御するというものです。
マイコン(ESP32)上では、mruby/cを動かしており、そこでボタンの監視とGPIOの制御を行っています。

mruby/cの実行には、自分でポーティングしたArduinoライブラリを用いています。
https://github.com/kishima/mrubyc_for_ESP32_Arduino

単にスクリプトを動かすだけだと面白くないので、mruby/cのインタプリタが処理中の命令を逐次LCDに表示するようにしています。
普通に処理させると早すぎて何が起きているのわからないので、ボタンを押すことでインタプリタの実行スピードを切り替えられるようにもしています。

Shaking Dice Machine
Shaking Dice Machine

ブロック図と材料

こんな構成でした。

Block diagram of shaking dice machine
Block diagram of shaking dice machine

サイコロ関連以外は、手持ちの在庫の部品を組合わせています。
– ESP32-Devkitc
https://www.amazon.co.jp/dp/B0718T232Z/ref=cm_sw_r_tw_dp_U_x_i1jyBbD3B3A04
– LCD
https://www.switch-science.com/catalog/1629/
– リレー
千石電商で買ったキット
– 10面ダイス
https://www.amazon.co.jp/dp/B00A1AS08S/ref=cm_sw_r_tw_dp_U_x_A0jyBbA1ED154
– 電動ダイス
https://www.amazon.co.jp/dp/B004V2KDCI/ref=cm_sw_r_tw_dp_U_x_B0jyBb8870A54

Rubyのコード

button = 27
chusen = 26
puts "set pin mode"
Arduino.pin_mode(button,:INPUT_PULLUP)
Arduino.pin_mode(chusen,:OUTPUT)
Arduino.delay 100
while true
  val = Arduino.digital_read(button)
  if val==0
    Arduino.digital_write(chusen,:HIGH)
  else
    Arduino.digital_write(chusen,:LOW)
  end

  Arduino.delay 300
end

コンパイルしたあとのバイトコード

irep 0x6000814d0 nregs=8 nlocals=4 pools=1 syms=11 reps=0
file: chusen.rb
    2 000 OP_LOADI      R1      27              ; R1:button
    3 001 OP_LOADI      R2      26              ; R2:chusen
    4 002 OP_LOADSELF   R4
    4 003 OP_STRING     R5      L(0)    ; "set pin mode"
    4 004 OP_SEND       R4      :puts   1
    5 005 OP_GETCONST   R4      :Arduino
    5 006 OP_MOVE       R5      R1              ; R1:button
    5 007 OP_LOADSYM    R6      :INPUT_PULLUP
    5 008 OP_SEND       R4      :pin_mode       2
    6 009 OP_GETCONST   R4      :Arduino
    6 010 OP_MOVE       R5      R2              ; R2:chusen
    6 011 OP_LOADSYM    R6      :OUTPUT
    6 012 OP_SEND       R4      :pin_mode       2
    7 013 OP_GETCONST   R4      :Arduino
    7 014 OP_LOADI      R5      100
    7 015 OP_SEND       R4      :delay  1
    8 016 OP_JMP        036
    9 017 OP_GETCONST   R4      :Arduino
    9 018 OP_MOVE       R5      R1              ; R1:button
    9 019 OP_SEND       R4      :digital_read   1
    9 020 OP_MOVE       R3      R4              ; R3:val
   10 021 OP_LOADI      R5      0
   10 022 OP_EQ         R4      :==     1
   10 023 OP_JMPNOT     R4      029
   11 024 OP_GETCONST   R4      :Arduino
   11 025 OP_MOVE       R5      R2              ; R2:chusen
   11 026 OP_LOADSYM    R6      :HIGH
   11 027 OP_SEND       R4      :digital_write  2
   11 028 OP_JMP        033
   13 029 OP_GETCONST   R4      :Arduino
   13 030 OP_MOVE       R5      R2              ; R2:chusen
   13 031 OP_LOADSYM    R6      :LOW
   13 032 OP_SEND       R4      :digital_write  2
   16 033 OP_GETCONST   R4      :Arduino
   16 034 OP_LOADI      R5      300
   16 035 OP_SEND       R4      :delay  1
    8 036 OP_LOADT      R4
    8 037 OP_JMPIF      R4      017
    8 038 OP_LOADNIL    R4
    8 039 OP_STOP

動かしてみた様子

実は・・・

できれば、先日試したArduinoのNTSC出力と組み合わせてバイトコード実行状態表示したり、とかまでやりたかった…

もしくは、rmirbと組み合わせてみるのもよいかと思ってけれど、本番酔った状態で上手くコード打てる自信がなかったのでこれは見送りました…

最後に

いずれにせよとても楽しかったー。いつも思いますが、とても体一つでは楽しみきれいないくらいです。


  1. 参加者全てを対象としてランダムで抽選を行って、当選した方にもLT発表者として登壇していただくしきたり