Go初心者でもすぐできる!Raspberry Piと組み合わせて素早く目覚ましを作る方法

こんにちは!
Pairsでサーバーサイドの開発を担当している大久保です。
 
突然ですが、皆さんは早起きするのは得意でしょうか?
僕はとても、とてもとてもとてもとてもとても苦手です。
平日も休日も、二度寝どころか、三度寝・四度寝することもしばしば…
 
正直早起きライフにあこがれています。
なので最近、早起きへの意識を高めるために、最近僕が業務で使いはじめたGo言語と、趣味で触り始めたRaspberry Piを使って目覚まし時計を作ってみました。「~はじめた」の言い方から分かるように、僕はGo言語に関しても、Raspberry Piに関しても初心者です。なので目覚まし作成は非常に時間がかかる覚悟をしていたのですが、これが思いの外に素早く作れたのでその際の手順を共有致します。
 

使用機器

・Raspberry Pi TypeB 512MB http://www.amazon.co.jp/dp/B00CBWMXVE
・OS(NOOBS) https://www.raspberrypi.org/downloads/noobs/
・SDカード(8GB) http://www.amazon.co.jp/gp/product/B00Y9OOBQM
・Raspberry Pi工作用パーツセット http://www.amazon.co.jp/dp/B00G86DOP8
 使うのは以下4つなので、これらが入っていれば何でもよいです
 ・タクトスイッチ
 ・ブレッドボード
 ・ジャンパーワイヤー(オスメス * 3)
 ・抵抗(470 ~ 10kΩ)
 

準備

Raspberry Piセットアップ

セットアップ方法については既に多くの書籍やネット記事に書かれているので、この記事では詳細に説明しません。
僕は特に以下の書籍を参考にセットアップしました。(「5章 タクトスイッチによる入力」まで読むだけでも、この記事に書いてある内容は十分に分かるかと思います)
http://www.amazon.co.jp/dp/4062578913/

Goインストール

Go言語で目覚まし処理を書いていくので、前もってGo言語をRaspberry Piにインストールしておきましょう。以下の記事が参考になるので、全く同様の手順でインストールをすすめます。詳細は元記事にありますのでここでは説明致しません。
https://developers.eure.jp/go-language/advent-calender-9/

$ sudo apt-get install -y gcc libc6-dev mercurial
$ cd /usr/local
$ sudo hg clone -u default https://code.google.com/p/go
$ cd go/src
$ sudo ./make.bash
---以下~/.bashrcに追記---
$ export GOROOT=/usr/local/go
$ export GOPATH=$HOME/repos/gohome
$ export PATH=$PATH:$GOROOT/bin:$GOPATH/bin

 

目覚まし実装

目覚ましに必要なのは、以下の2つの機能です。
1.時間になったらアラーム音を流す
2.スイッチを押した時アラーム音を止める

これらを実装していきます。

実装1 時間になったらアラーム音を流す

①アラーム音を鳴らす

mpg321というMP3再生用のアプリケーションを使います。

$ sudo apt-get install mpg321

インストールできたら、以下の形でMP3を再生できます。

$ mpg321 ***.mp3

MP3ファイルは何でもよいですが、今回僕は以下のサイトからアラーム音をダウンロードしました。 利用の前には必ず一度「利用規約」をお読みください。
http://soundeffect-lab.info/

mpg321コマンドの主なオプションとしては以下のものもありますので、用途に合わせて使いわけると良いと思います。

-l : リピート回数。0を指定すると永続的にリピートします。 ex. mpg321 -l 3 ***.mp3
-k : 先頭部分をスキップさせて再生できます。数値はフレーム単位で秒数ではないので注意  ex. mpg321 -k 2300 ***.mp3
  1150フレームで約30秒
  2300フレームで約1分

 

②ソースコード

アラーム音を鳴らすコードは以下です。
main.go

package main

import (
        "fmt"
        "os"
        "os/exec"
)

// アラーム音鳴らす
func start() {
        out, err := exec.Command("sh", "-c", "mpg321 -l 0 /path/to/***.mp3 > /dev/null &").Output() --- ①
        if err != nil {                  --- ②
                fmt.Println(err)
                os.Exit(1)
        }
        fmt.Println(string(out))
}

func main() {
        start()
}

 

③ソースコード解説

①mpg321コマンドで***.mp3をリピート再生します。「&」を末尾につけないとリピート再生中に次の処理にうつらないので必須です。

②mpg321コマンド実行が失敗した時のためエラー表示を出力します。エラーを意図的に出力しないこともできますが、要所の処理なので出力させます。
 

④クーロン設定

9時に起きたい場合、crontab -eで以下のように設定しましょう。

0 9 * * * /usr/local/go/bin/go run /path/to/main.go 1>>/tmp/cron.log 2>>/tmp/cron-err.log

もしmain.go自体は動作するのにcronがうまく動かない場合は、標準出力ファイル/tmp/cron.logと標準エラー出力ファイル/tmp/cron-err.logの内容を確認してみましょう。
 

実装2 スイッチを押した時アラーム音を止める

①入出力端子と接続

回路は以下のようにしました。
s_kairo_real
 
3.3vのピンから電流が流れ、タクトスイッチ押下時のみ、GPIO22番ピンに電流が流れるようになっています。
回路図は以下です。
kairo
 

②Gobotのインストール

今回素早く目覚ましを作りたかったので、Go言語製ロボティクスフレームワークのGobotを使ってGPIO制御が簡単にできるようにしました。
インストール方法は以下です。

$ go get github.com/hybridgroup/gobot

http://gobot.io/
 

③ソースコード

②でインストールしたGobotを利用して、「実装1 時間になったらアラーム音を流す」で作成したmain.goに以下を追記します。フルのソースコードは本記事の末尾にあります。※1

main.go

〜〜〜
import (

〜〜〜
        "time"
        "github.com/hybridgroup/gobot"
        "github.com/hybridgroup/gobot/platforms/raspi"
)

〜〜〜
// アラーム音鳴り始めて1分経ったら停止 or スイッチ押下で停止
func stop() {
    gbot := gobot.NewGobot()
    r := raspi.NewRaspiAdaptor("raspi")

    work := func() {
        waitMillisecond := 100
        i := 0;
        gobot.Every(time.Duration(waitMillisecond)*time.Millisecond, func() { --- ①
                v, _ := r.DigitalRead("15") --- ②
                if v == 1 || waitMillisecond*i > 60000 {
                        out, err := exec.Command("killall", "mpg321").Output() --- ③
                        if err != nil {
                                fmt.Println(err)
                                os.Exit(1)
                        }
                        fmt.Println(string(out))
                        os.Exit(0)
                }
                i++
        })
    }

    robot := gobot.NewRobot("blinkBot",
        []gobot.Connection{r},
        nil,
        work,
    )
    gbot.AddRobot(robot)
    gbot.Start()
}

func main() {
        start()
        stop() // 追記
}

 

④ソースコード解説

今回追記分のソースコードは、インストールしたgithub.com/hybridgroup/gobot/examples/以下にあるサンプルコード「raspi_blink.go」を参考に書いています。
https://github.com/hybridgroup/gobot/blob/dev/examples/raspi_blink.go

このソースコードはLEDを点滅させるためのものですが、GPIO制御の部分はほぼそのまま流用できます。
ですので今回の目覚まし実装のために変更したのは、gbot.Start()時に呼び出されるコールバック関数work内のみです。その上でコールバック関数内の処理について解説していきます。

①音楽再生中は、0.1秒置きにスイッチの押下を感知できるようにしています。

②GPIO22ポートに電流が流れていれば「1(int)」を、そうでなければ「0(int)」を取得します。GPIO22ポートは、左上のピンから右下のピンに向かって数えた時に15番目に位置するため「15」を指定しています。

③GPIO22ポートに電流が流れる or 音楽を流し始めて60秒以上立った時、mpg321のプロセスをkillし音楽を止めます。
 

⑤スピーカーと接続

アラームを室内に響かせるためにスピーカーと接続します。
s_speaker
 

使ってみた

普通に目覚ましとして使えます。アラーム音を選べたり、サビから流すことができるのは自作目覚ましの利点といえそうです。(iPhoneでもできる?ナンノコトヤラ)
タクトスイッチが弱々しいので、押下する時は慎重にした方がいいかもしれませんね(笑)
 

終わりに

今回はGo言語を使って、Raspberry Piで目覚ましを作ってみました。
コード量もすくなかったので、意外にすぐに作れました。(配線とかでつまづくと時間かかるかもしれませんが)

今後の展望としては、今回作ったシンプル目覚ましをベースに、色々な機能追加などを目論んでいます。(朝起きたら色々な情報を教えてくれたりするなど)

ではまた!
 

その他の参考記事)第19回「ラズベリーパイで手作り目覚まし時計!ストップボタン編」
http://deviceplus.jp/hobby/raspberrypi_entry_019/
 

※1. 以下本記事で書いたソースコード全文です。
https://gist.github.com/orkShinnosuke/c3091c1ca792bce81e7c

  • このエントリーをはてなブックマークに追加

エウレカでは、一緒に働いていただける方を絶賛募集中です。募集中の職種はこちらからご確認ください!皆様のエントリーをお待ちしております!

Recommend

Camp Match 2016 @Dallas に参戦してきました!

GOPATH を build.Default.GOPATH で適切に扱う