RaspberryPiとArduinoでミニ四駆ラップタイマー製作

# はじめに

ミニ四駆のコースである「[ジャパンカップ ジュニアサーキット](http://www.tamiya.com/japan/products/69506/index.html)」を会社に設置してもらったが、私しか熱中していないため競争相手がいない
結果、自分のマシンが早くなったのかを確認する手段がなくモチベーションが保てないので、ラップタイムを測定し過去の自分と向き合うこにした

タミヤ公式から「[タミヤ グレードアップ No.184 GP.184 ミニ四駆ラップタイマー 15184](https://www.amazon.co.jp/%E3%82%BF%E3%83%9F%E3%83%A4-%E3%82%B0%E3%83%AC%E3%83%BC%E3%83%89%E3%82%A2%E3%83%83%E3%83%97-No-184-GP-184-%E3%83%9F%E3%83%8B%E5%9B%9B%E9%A7%86%E3%83%A9%E3%83%83%E3%83%97%E3%82%BF%E3%82%A4%E3%83%9E%E3%83%BC/dp/B00061GZ48)」が発売さていたが廃盤となっており、現在手に入れようと思うと高騰した中古を探すこととなるので諦めた

スマホアプリで無料で測定できるものがあるが、せっかくなので自作しようと考えた

「やらなきゃ意味ないよ」

# 失敗事例

過去に作った[人感センサー](https://qiita.com/inaBowBow/items/dca01622d086f113db00)を改造すれば楽勝と考えていたが、人感センサーが検知してから復帰するまでの時間が５秒以上かかるようで、１ラップ５秒以下だと正常に計測できないことがわかった
また、[この記事](http://nao-bamboo.hatenablog.com/entry/2015/08/29/002912)でArduinoと測距センサーを使ってラップタイマーを作っていたので、RaspberryPiでもできるかと考えたが、測定間隔が長すぎてうまく測定できなかった（[参考記事](https://umiushizn.blogspot.com/2017/10/hc-sr04raspberry-pi.html)）
これは工夫次第でできる気がするが、私の力では無理だった

# 実現したい機能

* ミニ四駆のラップタイム計測
* Webページでの操作（計測開始、停止）
* Webページでのタイム表示

# 使うもの

* セットアップ済RaspberryPi（LAN接続とIP固定）
* Arduino互換機（[What's Next Yellow](https://www.switch-science.com/catalog/3521/)を使用）
* 測距センサー（[HC-SR04](https://www.amazon.co.jp/dp/B004U8TOE6/ref=asc_df_B004U8TOE62454653/?tag=jpgo-22&creative=9315&creativeASIN=B004U8TOE6&linkCode=df0&hvadid=204274148874&hvpos=1o1&hvnetw=g&hvrand=9849005429857000036&hvpone=&hvptwo=&hvqmt=&hvdev=c&hvdvcmdl=&hvlocint=&hvlocphy=1009343&hvtargid=pla-459285090715)）
* ジャンパピン（オス-メス）４本
* USBケーブル（A-B）
* パソコン（ArduinoIDEが動くやつならMacでもWinでもLinuxでも）

# Arduino設定

Arduinoにプログラム（スケッチ）を送る？入れる？には、Arduino IDEが必要
Arduinoに触るのは初めてで、以下の記事を参考に環境設定した
[Arduinoの最初の一歩](http://n.mtng.org/ele/arduino/tutorial001.html)

センサー接続、ソースについては、以下記事をそのまま使用させていただいた
[nao-bambooの日記：ミニ四駆ラップタイマーを作った](http://nao-bamboo.hatenablog.com/entry/2015/08/29/002912)
本当にありがたいです助かりました

あと、Arduinoと接続するUSBケーブルは「A-B」
今時見かける機会がほとんどないので、これを勘違いして電気屋さんに走るのは悲しい

# RaspberryPi設定（Arduinoからタイム取得）

Arduinoからシリアル経由で出力される文字列をPythonで取得する
調べたところ「pyserial」を使えば簡単にできる
[参考記事1](https://qiita.com/kosystem/items/0023cfee941fdf099087) [参考記事2](v)

```
pip install pyserial
```

``` python:lap.py
import serial
import time

def run():
    s = serial.Serial('/dev/ttyACM0', 9600)
    time.sleep(2)

    outStr = []
    while True:
        outVal = s.readline().rstrip("\n")
        outStr.append(outVal)
        if '[Lap5]' in outVal:
            outStr.append('Goal')
            return outStr

if __name__ == '__main__':
    run()
```

４行目は環境によって変わる可能性あり
また、Arduinoから５lap目のタイムが来たら画面表示するようにした
本当は1lap毎に画面表示したかったが、パッとはできなかった

# RaspberryPi設定（Webアプリ）

WebアプリはFlaskを使って作成した
index.htmlはボタンをつけただけなので、後々オシャレにする

```
pip install flask
```

``` python:application.py
# coding: utf-8

from lap import run
from flask import Flask, render_template, request
app = Flask(__name__)

@app.route("/", methods=['GET', 'POST'])
def index():
     print request.method
    ret = []
    if request.method == 'POST':
        ret = run()
    return render_template('index.html', message=ret)

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=3000)
```

``` html:templates/index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset='UTF-8'>
    <title>lap time</title>
</head>
<body>
    <p>
    <form action="/" method="post">
        <button type="submit">ボタン</button>
    </form>
    </p>
    {% for lap in message %}
        <p>{{lap}}</p>
    {% endfor %}
</body>
</html>
```

起動は以下コマンド実施
```
python application.py
```

ブラウザからRaspberrPiの固定IP:3000にアクセスすればOK

# コースに設置

適当な道具でセンサーをコースに設置
高さ調整しないと反応しないことがあるため、実際にミニ四駆を走らせて調整する

<img src="https://qiita-image-store.s3.amazonaws.com/0/59636/4d74310d-2a49-b078-f0bd-b4d6562f0863.jpeg" width=９0%>

# 所感

Arduinoはこれまでなぜか敬遠していて、今回RaspberryPiでどうしてもできなかったので
しぶしぶ使ってみたが、とても便利でサイコー、もう手放せない

肝心のラップタイマーだが、Webアプリが全然思い通りにできなかった
とりあえず、１lap毎に画面更新されるようには絶対にしたい
あと見た目オシャレにする