ラズパイ2試食レポ[8]: 目覚まし時計をつくってみた [Raspberry Pi]
目覚まし時計を作ってみました。
仕様は以下です。
- 時刻をAquesTalkPiでしゃべらせる。
- cronを使って、定時に時刻をしゃべる。
- cronだけでは起きない場合、任意にしゃべらせる。
◆ntpの設定
その前に、時刻は正確でなくては、ということでntpを設定します。ntpdはインストール済みで動作もしていますが、正しいサーバに設定しなおします。
pi@raspberrypi ~ $ sudo vi /etc/ntp.conf
「server」で始まる行をコメントアウトして、以下を追加します。
pool ntp.nict.jp iburst
ntpdを再起動します。
pi@raspberrypi ~ $ sudo service ntp restart
サーバとの同期状態を確認します。
pi@raspberrypi ~ $ ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
+ntp-b2.nict.go. .NICT. 1 u 97 128 377 7.093 0.824 0.144
*ntp-a2.nict.go. .NICT. 1 u 46 128 377 7.125 0.556 0.324
+ntp-a3.nict.go. .NICT. 1 u 97 128 377 6.607 0.820 0.316
-ntp-b3.nict.go. .NICT. 1 u 120 128 377 7.110 0.326 0.479
一番左に「*」が付いているサーバと同期していることを示しています。
◆cronで動かす
cronで起動するスクリプトcron_time.shは以下のようにしました。
#!/bin/sh
# cron_time.sh
daytime=`date "+%-B %-d日 %-A %-H時 %-M分"`
/usr/local/bin/atalk "おはようございます。${daytime}です。"
/usr/local/bin/atalk "天気予報です。`/usr/local/sh/tenki.py`"
/usr/local/bin/atalk "${daytime}です。"
時刻の後に天気もしゃべります。
これを、以下のようにcrontabで設定しました。
30,35,45 06 * * 1-5 /usr/local/sh/cron_time.sh
月-金の 6:30~6:45まで5分毎3回実行します。しつこいですね。
◆好きな時に好きな言葉をしゃべらせる
これでも起きないときのために、任意の言葉を好きなタイミングでしゃべらせるようにします。
ここでは、UDP通信を待ち受けるプログラムを常駐させて、スマホなどからしゃべる文字列を送りつけることで実現しました。
常駐プログラムは以下です。
//
// udp_talk
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#define BUF_SIZE 1024
#define PORT_NUM 12345
void run_comm(char *buf, int len){
char str[BUF_SIZE];
strcpy(str, "/usr/local/bin/atalk ");
strncat(str, buf, len);
//printf("%s\n", str);
system(str);
}
int main(){
int sock = 0;
int len = 0;
int loop = 1; // 1=forever
struct sockaddr_in addr;
socklen_t addrlen;
char buf[BUF_SIZE];
// create socket
sock = socket(AF_INET, SOCK_DGRAM, 0);
if ( sock < 0 ) {
exit(-1);
}
// set address and port
addr.sin_family = AF_INET;
addr.sin_port = htons(PORT_NUM);
addr.sin_addr.s_addr = INADDR_ANY;
// bind
if ( bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0 ) {
perror("bind");
fprintf(stderr, "port %d is already used.\n", PORT_NUM);
return(-1);
}
// clear buf
memset(buf, 0, sizeof(buf));
// recv
while ( loop ) {
addrlen = sizeof(struct sockaddr_in);
len = recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *)&addr, &addrlen);
if ( len < 0 ) {
perror("recv");
break;
}
//printf("%s\n", buf);
run_comm(buf, len);
if( strncmp(buf, "quit\n", 5) == 0 ) {
loop = 0;
}
memset(buf, 0, len);
}
close(sock);
return 0;
}
UDP通信では特にパケットなど規定せず、送られてきたデータを単純にAquesTalkPiに渡すだけです。処理時間もそれほど掛かりませんし、不特定多数のクライアントを想定しなくても良いのでforkはしていません。
送る側はUDPで送れれば何でも良いので、スマホアプリの「UDP Tester」などが利用できます。いくつかの文字列をプリセットしておいて選択できるようなアプリを自分で作ってもいいですね。
準備OKです。が、スピーカーがない…。
【2015/05/19追記】 100均のスピーカーを繋げてみました。「音は大きくなりません」と明記してあるものです。ラズパイ本体のボリュームを最大にすると、近くに置いてあれば部屋の中なら普通に聞こえるレベルです。でも目覚ましにするにはあきらかに力不足でした。
【2015/05/25追記】 同じく100均のアンプを買ってみました。ちょっとボリュームを上げるだけで十分な音量になります。このままでも実用可能ですが、別途電池が必要なのがちょっと癪に障ります。中のICは1.8~15Vくらいで動作可能なようなので、たとえばラズパイのGPIO出力を電源とすれば、鳴らすときだけ3.3V供給とかできそうです。電流足りないかな?
コメント 0