2013年9月28日土曜日

100円ショップのUSBマイクロケーブル

100円ショップでケーブル長が5cm程度のかなり短いUSBマイクロケーブルがあったのでつい買ってしまった。




100円ショップ商品はケーブルの金属に不純物が多くて危険な場合があることに注意せねばならんらしい。

実際スマホの爆発炎上は大概100円ショップケーブルだとか。

というわけでスマホやタブレットなどのリチウムイオンバッテリー搭載物は純正ケーブルを使うようにしている。

それ以外のモノならまあ多分大丈夫だろうということで使ってみる。

Google音声認識APIを利用した音声認識コマンド入力

前記事「Ruby + Google音声認識APIによるRaspberryPIでの音声認識」でGoogle音声認識が使えることがわかったので音声認識コマンド入力のプロトタイプを作ってみた。

動作概要

  • コマンド入力スクリプトはリモコンから起動
  • ピッという発信音の後5秒間録音してGoogle音声認識APIにかける
  • Google音声認識APIの結果からコマンドかどうか判断
ソース

----

# coding:utf-8
require 'pp'
require 'uri'
require 'json'
require 'net/http'
require 'fileutils'
WAVFILE="/tmp/voice.wav"
FLACFILE="/tmp/voice.flac"
def start_alarm
`/home/pi/aquestalkpi/AquesTalkPi -b -g 100 "ピッ" | aplay`
end
Net::HTTP.version_1_2
def voicerecog
start_alarm
`arecord -D plughw:1,0 -d 5 -f cd #{WAVFILE}`
FileUtils.rm_f(FLACFILE)
`ffmpeg -i /tmp/voice.wav -vn -ac 1 -ar 16000 -acodec flac #{FLACFILE}`
uri = URI.parse("https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ja&maxresults=6&pfilter=2")
req = Net::HTTP::Post.new(uri.request_uri)
req.body = File.read(FLACFILE)
req.content_type = "audio/x-flac; rate=16000"
req.content_length = req.body.size
req['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11"
#req['Accept-Encoding'] = "gzip,deflate,sdch"
req['Accept-Language'] = "ja,en-US;q=0.8,en;q=0.6"
req['Accept-Charset'] = "utf-8;q=0.7,*;q=0.3"
http = Net::HTTP.new(uri.host,uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
http.start do |h|
res = h.request(req)
result = JSON.parse(res.body)
command = result["hypotheses"][0]["utterance"]
return command
end
end
# main
command = voicerecog
case command
when "天気予報","てんきよほう"
`/home/pi/aquestalkpi/AquesTalkPi -b -g 100 "天気予報" | aplay`
when "タイムライン","timeline"
`/home/pi/aquestalkpi/AquesTalkPi -b -g 100 "タイムライン" | aplay`
when "ツイート"
`/home/pi/aquestalkpi/AquesTalkPi -b -g 100 "ツイート" | aplay`
end
view raw voicecommand.rb hosted with ❤ by GitHub
----

プロトタイプなので「天気予報」などのコマンドの中身は実装していない。

状態遷移で複雑な入力もできるし、対話型にしてもいいかも知んない。

色々できそうではあるんだがいかんせんヤル気が・・・


2013年9月24日火曜日

RaspberryPI + I2C 3軸デジタルコンパスHMC5883L(4) xively.comのグラフ 気温連動

HMC5883Lのグラフを眺めていて緩やかに上下することに気付いた。

どうも気温と連動しているようだ。

チップ内部で電圧かなんかを測ってるに違いないから温度変化で抵抗値が変わって出力が変わってんだろうなぁ。という当たり前だのクラッカーを確認しただけにすぎんのですが。


2013年9月19日木曜日

Ruby + google音声認識APIによるRaspberryPIでの音声認識

「googleの日本語音声認識を自由に呼び出して使う方法」を参考にRubyからgoogle音声認識APIを叩いてみた。

まず事前準備として

RaspberryPIにUSBマイクで音声入力を参考に、録音
$ arecord -D plughw:1,0 -d 10 -f cd test.wav
ffmpegパッケージでtest.wavをtest.flacに変換
$ ffmpeg -i test.wav -vn -ac 1 -ar 16000 -acodec flac test.flac
あとは以下のスクリプトを実行。

----
# coding:utf-8
require 'pp'
require 'uri'
require 'net/http'
Net::HTTP.version_1_2
uri = URI.parse("https://www.google.com/speech-api/v1/recognize?xjerr=1&client=chromium&lang=ja&maxresults=6&pfilter=2")
req = Net::HTTP::Post.new(uri.request_uri)
req.body = File.read("test.flac")
req.content_type = "audio/x-flac; rate=16000"
req.content_length = req.body.size
req['User-Agent'] = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.47 Safari/536.11"
#req['Accept-Encoding'] = "gzip,deflate,sdch"
req['Accept-Language'] = "ja,en-US;q=0.8,en;q=0.6"
req['Accept-Charset'] = "utf-8;q=0.7,*;q=0.3"
http = Net::HTTP.new(uri.host,uri.port)
http.use_ssl = true
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
#http.set_debug_output STDERR
http.start do |h|
res = h.request(req)
p res
puts res.body
end
view raw gvoicerecog.rb hosted with ❤ by GitHub
----

実行結果
$ ruby gvoicerecog.rb
#<Net::HTTPOK 200 OK readbody=true>
{"status":0,"id":"1b69aa31b6bfac4059d6409566f4950e-1","hypotheses":[{"utterance":"あいうえお","confidence":0.5210862},{"utterance":"あ い う え お"},{"utterance":"アイウエオ"},{"utterance":"あいうえお aa"},{"utterance":"あいうえお うー"}]}

juliusと違ってかなりの認識精度

それにRaspberryPIの負荷もほとんどない・・・

便利すぎる。

ただ家電コントローラ的にはリモコン操作に慣れてしまったのでもはや使い所がない。
うーむ。ちょっと利用方法を考える。

  • 人口無脳的チャット
  • 自由記述による検索
  • 天気予報とかwikipediaとか(出力が音声だと使いにくくない?)
ぬぬー。求むアイディア。

2013年9月16日月曜日

RaspberryPI + I2C 3軸デジタルコンパスHMC5883L(3) xively.comのグラフ

xively.comに3軸デジタルコンパスHMC5883Lの値を5分間隔でアップロードしてみたわけだが、

以下のように若干ガタガタしたものになった。


といっても原因は自分自身のせいなのだけど。

RaspberryPIとHMC5883Lをキャスター付きパソコンデスクに載せているのだが、

このパソコンデスク足元にプリンタ用の棚がドデンとあるタイプなので構造上蹴らずにはいられない。

そして蹴った時の衝撃に反応してか、実際に若干動くのか値が変化してしまうようだ。

衝撃のない安定した場所に据え付けたいけどなかなかそのような場所はない。

部屋の隅の壁に神棚みたいなもの作って置こうかなぁ。

2013年9月15日日曜日

RaspberryPI + 赤外線リモコン基盤 + mplayerでラジオサーバ(2)

ボタン7と8({7,8}-rimokon.sh)にボリュームアップ、ダウンを追加。

amixer sset PCM 10%{+,-}で相対的に音量増減できるはずなのだが、

上手く動作しないようなので

amixer sget PCMから現在のボリュームを取得して+-5するようにしてみた。

#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "らじお、ていし" | aplay
killall mplayer
view raw 0-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、いち、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129931/live/reflector:46032.asx
view raw 1-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、に、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129932/live/reflector:46056.asx
view raw 2-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、えふえむ、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129933/live/reflector:46051.asx
view raw 3-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "だらずえふえむ、かいし" | aplay
killall mplayer
mplayer -playlist http://www.darazfm.com/streaming.asx
view raw 4-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "びーびーしー、いち、かいし" | aplay
killall mplayer
mplayer -playlist http://www.bbc.co.uk/radio/listen/live/r1.asx
view raw 5-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "ろく" | aplay
view raw 6-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "ぼりゅーむ" | aplay`
vo=`amixer sget PCM | awk 'match($0,/([[:digit:]]+)%/,data){ print data[1]}'`
vo=`expr $vo + 5`
if [ $vo -gt 100 ]
then
vo=100
fi
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "$voぱあせんと" | aplay`
amixer sset PCM "$vo%"
view raw 7-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "ぼりゅーむ" | aplay`
vo=`amixer sget PCM | awk 'match($0,/([[:digit:]]+)%/,data){ print data[1]}'`
vo=`expr $vo - 5`
if [ $vo -lt 75 ]
then
vo=75
fi
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "$voぱあせんと" | aplay`
amixer sset PCM "$vo%"
view raw 8-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "きゅう" | aplay
view raw 9-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "でんとう" | aplay
irsend SEND_ONCE light power
view raw a-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "ちょうこう" | aplay
irsend SEND_ONCE light choukou
view raw b-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "じょうやとう" | aplay
irsend SEND_ONCE light jouyatou
view raw c-rimokon.sh hosted with ❤ by GitHub
# coding:utf-8
class Locked < StandardError
end
def lock(lock_file_path='/tmp/rirc')
File.open(lock_file_path, 'w') do |lock_file|
if lock_file.flock(File::LOCK_EX|File::LOCK_NB)
yield
else
raise Locked
end
end
end
def exec_script(cmd)
dir = File.expand_path(File.dirname(__FILE__))
script = File.join(dir,"#{cmd}.sh")
if File.exist?(script)
Process.spawn(script)
end
end
INTERVAL_SEC = 1.0
begin
lock do
IO.popen("irw","r") do |io|
st = Time.now
loop do
# 0000555af1484a8b 00 1 rimokon
line = io.gets.chomp
int = Time.now - st
if int > INTERVAL_SEC
cmd = line.split(" ")[-2..-1].join("-") # => 1-remokon
exec_script(cmd)
st = Time.now
end
end
end
end
rescue Locked
exit 0
end
view raw rirc.rb hosted with ❤ by GitHub

2013年9月14日土曜日

RaspberryPI + I2C 3軸デジタルコンパスHMC5883L(2) 5分間隔で計測してxively.comにデータ登録

前回はi2cget、i2csetコマンドでHMC5883Lのモード設定、コンパス値の取得が使用できることを確認した。

i2cget、i2csetコマンドをRubyやシェルスクリプトから叩くつもりだったが、1回の測定について1000回ぐらい繰り返し、平均値を使ったほうが良い気がしてきた。

1000回の測定となると毎回i2cgetコマンドを叩くのは非効率なので、C言語でプログラムを書くことにした。

hmc5883l.c
  • HMC5883Lの測定周期、磁界強度設定などの設定はデフォルト、測定モードは連続モード
  • 10ms間隔で1000回測定した平均値を出力
で、そのCのプログラムの実行結果をログファイルに書いてxively.comに転送するRubyスクリプト(hmc5883l.rb)も作成。

そしてそのhmc5883l.rbをcronで5分間隔で実行するようにしてみた。

で、その結果が以下である。


スクリーンショット

当たり前なのだが、センサーを固定しているのでほぼ変動がない。

このグラフに意味があるかないかはよくわからないけどしばらく続けてみる予定である。

最後に作成したプログラムを公開しておく。

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <linux/i2c-dev.h>
#include <fcntl.h>
#include <sys/ioctl.h>
static void
HMC5883L_write(
unsigned char address,
unsigned char data,
int fd)
{
unsigned char buf[2];
buf[0] = address;
buf[1] = data;
if((write(fd,buf,2))!=2) {
printf("Error writing to i2c slave\n");
exit(1);
}
return;
}
static unsigned char
HMC5883L_read(
unsigned char address,
int fd)
{
unsigned char buf[1];
buf[0] = address;
if((write(fd,buf,1))!= 1){
printf("Error writing to i2c slave\n");
exit(1);
}
if(read(fd,buf,1)!=1){
printf("Error reading from i2c slave\n");
exit(1);
}
return buf[0];
}
static void
HMC5883L_readData(
int *idata,
int fd)
{
unsigned char i,addr,data[6];
for(i=0; i<6; i++){
addr = 0x03 + i;
data[i]=HMC5883L_read(addr,fd);
}
idata[0]=((int)data[0]<<24|(int)data[1]<<16)>>16;
idata[1]=((int)data[2]<<24|(int)data[3]<<16)>>16;
idata[2]=((int)data[4]<<24|(int)data[5]<<16)>>16;
return;
}
static void
HMC5883L_init(int fd)
{
unsigned char data;
data = HMC5883L_read(0x0a,fd);
if (data != 0x48) {
printf("Identification Register 0x0a check failure [%02x]",data);
exit(1);
}
data = HMC5883L_read(0x0b,fd);
if (data != 0x34) {
printf("Identification Register 0x0b check failure [%02x]",data);
exit(1);
}
data = HMC5883L_read(0x0c,fd);
if (data != 0x33) {
printf("Identification Register 0x0c check failure [%02x]",data);
exit(1);
}
HMC5883L_write(0x00,0xe0,fd); /* set default val to Config Reg A */
HMC5883L_write(0x02,0x00,fd); /* set continuous mode to Mode Reg */
return;
}
int
main(
int argc,
char **argv)
{
int i,j,fd,data[3];
char *i2cfile = "/dev/i2c-1";
unsigned char i2caddr,status;
double x,y,z;
i2caddr = 0x1e;
if ((fd = open(i2cfile, O_RDWR)) < 0) {
printf("Faild to open i2c port\n");
exit(1);
}
if (ioctl(fd, I2C_SLAVE, i2caddr) < 0) {
printf("Unable to get bus access to talk to slave\n");
exit(1);
}
HMC5883L_init(fd);
x = y = z = 0;
for(i=0,j=0; i<1000; i++) {
status = HMC5883L_read(0x09,fd);
if (status | 0x1) {
HMC5883L_readData(data,fd);
x += (double)data[0];
z += (double)data[1];
y += (double)data[2];
#if 0
printf("x[%05d] z[%05d] y[%05d]\n",
data[0],data[1],data[2]);
#endif
j++;
}
usleep(1000*10);
}
printf("%5.1lf %5.1lf %5.1lf\n",x/j,y/j,z/j);
return;
}
view raw hmc5883l.c hosted with ❤ by GitHub
# coding:utf-8
require "pp"
require "net/https"
require "fileutils"
def xively(x,y,z)
uri = URI.parse('https://api.xively.com/v2/feeds/1679002984.xml')
https = Net::HTTP.new(uri.host,uri.port)
https.use_ssl = true
headers = {
'X-ApiKey' => 'XXXXXXXXXXXXXXXXXXXXXXXXXXXX',
'Content-Type' => 'application/xml'
}
data =<<-EOS
<?xml version="1.0" encoding="UTF-8"?>
<eeml>
<environment>
<data id="HMC5883L_X">
<current_value>#{x}</current_value>
</data>
<data id="HMC5883L_Y">
<current_value>#{y}</current_value>
</data>
<data id="HMC5883L_Z">
<current_value>#{z}</current_value>
</data>
</environment>
</eeml>
EOS
res = https.send_request('PUT',uri.request_uri,data,headers)
end
now = Time.now
dir = File.expand_path(File.dirname(__FILE__))
command = File.join(dir,"hmc5883l")
x,y,z = `#{command}`.split(" ")
exit 0 unless x && y && z
dir = File.join(ENV["HOME"],"hmc588l",now.strftime("%Y"),now.strftime("%m"))
file = File.join(dir,now.strftime("%d")+".txt")
FileUtils.mkdir_p(dir)
mode = File.exists?(file) ? "a" : "w"
File.open(file,mode) do |io|
out = "#{now.strftime("%Y%m%d%H%M%S")}\t#{x}\t#{y}\t#{z}"
io.puts out
end
begin
xively(x,y,z)
rescue Exception => ex
puts ex
end
view raw hmc5883l.rb hosted with ❤ by GitHub


2013年9月13日金曜日

RaspberryPI + 赤外線リモコン基盤 + mplayerでラジオサーバ

先日作成したリモコン基盤マウンタとRaspberryPIをPower Mac G4 cubeにつっこむ。

基盤下に耐震ジェルパッドを敷いてユルーク固定してるつもりだけどあまり意味なし。

USBスピーカーも繋げてバージョン1完成とする。

PIneApple(・・・PI in Apple)と命名する。




ただ肝心のソフトがまだだったので作成。

ざっくりとした仕様は以下。
  • 赤外線リモコンで操作
  • ボタンに応じてmplayerの起動、フロアライトのリモコン操作を行う
  • 赤外線受信のハンドリングはirwコマンドで行う
でできたのが↓のRubyスクリプト(rirc.rb)。
  • IO.popenでirwの標準出力を拾って解析
  • ボタンとリモコン名からスクリプト名を決定し、スクリプトファイルがあれば実行
  • どうもリモコンボタンを普通に押しただけで2回連続で赤外線とぶみたいなので、実行後1秒間の受信は無視
  • cronで定時起動するようにしてロックファイルで重複実行しないように
  • ボタン対応スクリプト内でAquesTalkで軽くしゃべらせる

#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "らじお、ていし" | aplay
killall mplayer
view raw 0-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、いち、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129931/live/reflector:46032.asx
view raw 1-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、に、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129932/live/reflector:46056.asx
view raw 2-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "えぬえいちけい、えふえむ、かいし" | aplay
killall mplayer
mplayer -playlist http://mfile.akamai.com/129933/live/reflector:46051.asx
view raw 3-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "だらずえふえむ、かいし" | aplay
killall mplayer
mplayer -playlist http://www.darazfm.com/streaming.asx
view raw 4-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "びーびーしー、いち、かいし" | aplay
killall mplayer
mplayer -playlist http://www.bbc.co.uk/radio/listen/live/r1.asx
view raw 5-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "ろく" | aplay
view raw 6-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "ぼりゅーむ" | aplay`
vo=`amixer sget PCM | awk 'match($0,/([[:digit:]]+)%/,data){ print data[1]}'`
vo=`expr $vo + 5`
if [ $vo -gt 100 ]
then
vo=100
fi
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "$voぱあせんと" | aplay`
amixer sset PCM "$vo%"
view raw 7-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "ぼりゅーむ" | aplay`
vo=`amixer sget PCM | awk 'match($0,/([[:digit:]]+)%/,data){ print data[1]}'`
vo=`expr $vo - 5`
if [ $vo -lt 75 ]
then
vo=75
fi
`/home/pi/aquestalkpi/AquesTalkPi -g 100 "$voぱあせんと" | aplay`
amixer sset PCM "$vo%"
view raw 8-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "きゅう" | aplay
view raw 9-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "でんとう" | aplay
irsend SEND_ONCE light power
view raw a-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "ちょうこう" | aplay
irsend SEND_ONCE light choukou
view raw b-rimokon.sh hosted with ❤ by GitHub
#!/bin/bash
/home/pi/aquestalkpi/AquesTalkPi -g 100 "じょうやとう" | aplay
irsend SEND_ONCE light jouyatou
view raw c-rimokon.sh hosted with ❤ by GitHub
# coding:utf-8
class Locked < StandardError
end
def lock(lock_file_path='/tmp/rirc')
File.open(lock_file_path, 'w') do |lock_file|
if lock_file.flock(File::LOCK_EX|File::LOCK_NB)
yield
else
raise Locked
end
end
end
def exec_script(cmd)
dir = File.expand_path(File.dirname(__FILE__))
script = File.join(dir,"#{cmd}.sh")
if File.exist?(script)
Process.spawn(script)
end
end
INTERVAL_SEC = 1.0
begin
lock do
IO.popen("irw","r") do |io|
st = Time.now
loop do
# 0000555af1484a8b 00 1 rimokon
line = io.gets.chomp
int = Time.now - st
if int > INTERVAL_SEC
cmd = line.split(" ")[-2..-1].join("-") # => 1-remokon
exec_script(cmd)
st = Time.now
end
end
end
end
rescue Locked
exit 0
end
view raw rirc.rb hosted with ❤ by GitHub



動作風景


見た目が若干アレなので配線の始末とか前面パネルとか作るかも知れない。

あとはLCDとかマトリックスLEDでなにか表示させるとかやってもよいかも。

2013年9月11日水曜日

ダイソーのMDF材で赤外線リモコンマウンタ作成

Power Mac G4 cubeアクリルケースにRaspberryPI + 赤外線リモコン基盤を設置するにあたり、

赤外線リモコン基盤を露出穴付近まで嵩上げするマウンタが必要になった。

↑はバランスとって穴の縁にのっけてるだけ

そこでダイソーで売っている100x100x7 5枚入りMDF材でマウンタを作成してみた。



MDF材は安くて加工しやすくて、強度もそこそこあって、木工用ボンドで接着できるのでチョロッとしたものを作るのにとても便利。
(ただし湿気に弱くカビやすいという弱点もあるらしいケド)

というわけで適当に切って、ボンドでくっつけて、穴あけてネジ止めしただけのマウンタがわずか30分で完成(乾燥時間を除く)。



ついでにRaspberryPI1号 + GC-10の取り付けラック?もMDF材で作成。

ボンドでくっつけただけの逸品です。


ダイソーのMDF材オススメですw

RaspberryPI + I2C 3軸デジタルコンパスHMC5883L


RaspberryPIにはi2cインターフェースがついていて、i2c経由で色々できるらしい。ということでi2cの面白いセンサーがないかなぁと探していたところ
というのをみつけた。

ロボットにつけて向きを測定したりするのが正しい用途なんだろうけど、センサー固定して地磁気のログをとってみるのも興味深いかもってことでポチリ。

で、少し前に届いてたのを今回触ってみる。

チップにピンヘッダをハンダ付けしてブレッドボードオーン。
GPIOにジャンパーピーン。

ロボット制御のように連続計測するわけじゃないのでDRDYは使用しない。でいいよね。たぶん。



例によって
あたりを参考にRaspberryPIにi2cを設定。

HMC5883Lの仕様の詳細についてはStrawberry Linuxの「3軸ディジタルコンパスモジュール HMC5883L 」のマニュアルを参照。

i2cdetectでチップ認識、アドレス確認
  => 0x1e

動作確認用のIdentification Register読み出しも問題なし
  => 0xa=0x48, 0xb=0x34, 0xc=0x33

pi@raspi2:~$ sudo i2cdetect 1
WARNING! This program can confuse your I2C bus, cause data loss and worse!
I will probe file /dev/i2c-1.
I will probe address range 0x03-0x77.
Continue? [Y/n] 
     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- -- 
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- 1e -- 
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 
70: -- -- -- -- -- -- -- --                         
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x0a b
0x48
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x0b b
0x34
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x0c b
0x33

Mode Register(0x02)に0x00を書き込むと連続計測モードになって、
値がData Output Register(0x03〜0x08)に書き込まれる。
データは下記のようにX,Y,Zの16bitずつである。

0x03 X方向MSB

0x04 X方向LSB

0x05 Z方向MSB

0x06 Z方向LSB

0x07 Y方向MSB

0x08 Y方向LSB


Status Register(0x09)の下位1bitが1だと読み込み可能。

デフォルトだと15Hzで更新されるのでコマンドポチポチ打つ分には常に読み込み可能状態。


下位2bit目はLOCKbitで0x03-0x08で読み込んでないRegisterがあると1になる。
全部読むとクリアされる。

LOCK中はRegisterが更新されない(全部Data Register読まないと更新されない)。

pi@raspi2:~$ sudo i2cset -y 1 0x1e 0x00 0xe0 # Configuration A Registerをデフォルトにセット
pi@raspi2:~$ sudo i2cset -y 1 0x1e 0x02 0x00 # Mode Register Continuous modeにセット
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x09 b    # Status Register 
0x11                                         # => Ready
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x03 b    # X MSB Register
0x02
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x04 b    # X LSB Register
0x7d
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x05 b    # Z MSB Register
0xff
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x06 b    # Z LSB Register
0x15
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x07 b    # Y MSB Register
0x00
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x08 b    # Y LSB Register
0x58
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x09 b    # Status Register
0x11                                         # => Ready

... ここでブレッドボードを90度動かしてみる ...

pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x03 b    # X MSB Register
0x00
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x04 b    # X LSB Register
0xba
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x05 b    # Z MSB Register
0xff
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x06 b    # Z LSB Register
0x43
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x07 b    # Y MSB Register
0x01
pi@raspi2:~$ sudo i2cget -y 1 0x1e 0x08 b    # Y LSB Register
0x9d

ブレッドボードを動かすと値が変わったのを確認できた。

ちなみに値はsigned int 16で-2048から2047の範囲。

設定でpositive bias、negative biasかけられるとあるが、uint 16になるという意味なのか、値域はそのままで値にbiasするのか不明。まーデフォルトで。

日本語マニュアルには磁石を近づけるとすぐオーバーフロー(0xff)するとあったけど、近づけると大きく値が変化するもののオーバーフローまでには至らない。

ということでお試し的に十分堪能したので次はログ取りスクリプトを作成しよう。

C言語で作成しようかと思ったけどなんか面倒になったのでRubyでいいや。

リアルタイムじゃなくていいし。

2013年9月9日月曜日

RaspberryPI in Power Mac G4 cubeアクリルケース

Power Mac G4 cubeのアクリルケースを入手したので、

これにRaspberryPIを入れてはどうかと妄想してみた。






なにやらシュールな感じだがホコリよけには十分でしょう。



リモコン基盤を支えるマウンタみたいなものを作らんといかんな。

2013年9月8日日曜日

RaspberryPIで赤外線リモコン(3)

ブレッドボードでの動作を確認したのでユニバーサル基板で回路作成してみた。

なにぶん初めてのユニバーサル基板なのでパーツの配置と配線に頭を使った。

とくにRaspberryPIのGPIOに合わせて13x2pinにしたのだが2列だとどうしても立体交差が生じてしまう。

結局、ジャンパーピンを使いまくって回避。

で、完成したのがコレ








装着図


しかし改めて見ると無駄に細かいジャンパーピン繋ぎまくってるな・・・

長めのやつをカクカク折り曲げて使えばよかったかも・・・

次回への教訓ですかな。

で、動作確認すると受信できるもののLED発光せず、ヤベー配線ミスったかと焦ったが、トランジスタのベース入力のGPIO17のハンダ付けが不十分なだけだった。

ハンダ付けなおしたらキチンと動いた。ヤレヤレ

最終的な回路図をグニャグニャつけとく。


2013年9月7日土曜日

RaspberryPIでJuliusによる音声認識(3) canna変換辞書から認識辞書作成

前回、自前で文法を作成してコマンドだけ認識させるようにしてみたが、

false positive(=無効な単語を有効コマンドに誤認識)が多すぎて使えないことがわかった。

しばらく考えて無意味な単語は無意味なものとして認識させれば良いのではないかと思い立った。

そこでcannaの変換辞書から単語を取り出して辞書に追加してみた。

辞書はスクリプトで作成

  • 長音とヴが入った単語は変換が面倒なので削除
  • 残った単語をローマ字音節に変換

単語数は12000程度。




・・・で、試してみた。

結論から言えばfalse negative(=有効なコマンドを他の単語に誤認識)が多すぎて使えない。

「エアコンオン」が「オヤブンヤク」になったり、文字数はあっていて音の感触が近いものがあがってくるが、使えないことには変わりない。

やっぱり音の認識そのものの性能がイマイチな気がする。

調整すれば使えるかも知れないけど面倒なので、juliusによるコマンド入力は一旦諦めようと思う。



機材追加(はんだ台、ハッコースッポン、ピンセット)

ユニバーサル基板に回路作ることを考えてはんだ台、ハッコースッポン、ピンセットを購入した。


GC-10作成のときにハッコースッポンさえあれば液晶表示も付け直すことができたかもしんない。




ちなみに今まで使ってたはんだ台(ジャムのビンに水にひたしたメラミンスポンジいれただけ)w


2013年9月6日金曜日

RaspberryPIで赤外線リモコン(2)

5Ωと1KΩ買ってきて早速付け替えてみた・・・



うむ。

付かん。

LEDを5V直結すると(デジカメでは)眩しく光るし、

トランジスタを使わずにGPIO17を直接LEDのアノードに接続すると微弱ながら点灯するので

Raspbian及びlircは動作している模様。

やはりトランジスタ2SC1815が上手く動いてないようなのだが理由がわからん。

エミッタ、コレクタ、ベースの確認は何度もしたし、2SC1815も2回変えてみたがダメ。

わからん。困った。

・・・

他のサイトの回路の写真みてたらやっぱりトランジスタのピンを間違えているっぽい気がしてきた。

トランジスタの説明書の以下の図からして凹んだというか平になってる側を上にして左から、エミッタ、コレクタ、ベースだと考えていたけど、凹んだ側を下にして左からエミッタ、コレクタ、ベースではないかと。




赤外線を使ってRaspberry Piから家電を制御しよう(予告編)」の以下の写真でついに確信に至る。


てことでトランジスタ反対にして挿し直したらあっさりLEDがついた。

しかしデジカメでみると随分光が弱い気が・・・

と思ったのだが4,5m離れたTVの電源を操作することができたのでまあよしとする。

どうしても出力が弱ければ第14回「テレビのリモコンでロウソクを点ける実験」にあるコンデンサを使う方法を試すのも良いかも。

にしても説明書の図わかりにくすぎるだろ

「なめやがってェ!エェ!初心者だと思ってなめてんのか!チクショー!ドカッ!!バキッ!!」
ギアッチョ並みにブチ切れたい。

2013年9月5日木曜日

RaspberryPIで赤外線リモコン(1)

秋月電子で頼んでた赤外線リモコンのパーツが届いた。


キモのパーツは赤外線受光モジュールのPL-IRM0101-3と赤外線発光ダイオードOSI5FU511C-40。

例によってhttp://homebrew.jp/show?page=1480のサイトを参考にした。

早速ブレッドボードで回路作って接続。



最初に間違えてhomebrew.jpで赤外線受光モジュールにCRVP1738を利用しているのを忘れてそのままPL-IRM0101-3で置き換えて回路作ってしまった。

CRVP1738とPL-IRM0101-3ではピン配置が異なっていたためショートさせてしまい異臭発生

RaspberryPIも起動せず。

確認してないけどPL-IRM0101-3たぶん壊れたと思う。(*ノω・*)テヘ

で、ピン配置を正しく置き換えてlircdの設定をしたところキチンとリモコンの信号がとれた。

lircdの学習方法がはじめよくわからなかったが、


を参考に学習。

ようは2回ランダム押しした後にひとつひとつ名前をつけながら入力していく感じ。

学習も終わったのでいよいよ出力。

なのだが赤外線でない。

受光モジュールのショートのときに他の部品も壊したのかと抵抗やトランジスタを変えてみても出ない。

テスタで調べてみたところGPIO17から信号は出てるっぽい。

GNDと各部の電流を調べてみたけどよくわからん。
※コレクタ、エミッタ間とか調べればよかったかも・・・

と、ここで気づいたがベースの2k2の抵抗がデカすぎるんでないかと。

2つ目の参考サイトでは1kの抵抗を使ってる。

というわけで抵抗を変えてみたいが2k2と100しか買ってないのでまた後日。

近所のパーツ屋で調達してからリトライ。

いくら品ぞろえ悪い無線関係中心のパーツ屋でも抵抗くらいはあるだろう。



2013年9月1日日曜日

RaspberryPIでJuliusによる音声認識(2)

前回の確認でデフォルトの辞書では使い物にならないことがわかったので

Julius の記述文法を用いて音声認識精度をあげてみた

を参考にコマンドの文法を作成してみた。

詳細は参考サイトを参照してもらうとして、以下の設定ファイルを作成して試してみた。

cmd.grammar
S       :  NS_B CMD NS_E
CMD     :  RADIO CH
CMD     :  RADIO OFF
CMD     :  DENKI
CMD     :  CHOUKOU
CMD     :  JOUYATOU
CMD     :  EAKON ON
CMD     :  EAKON OFF
CMD     :  TENKIYOHOU


cmd.voca
% RADIO
ラジオ  r a j i o
% CH
イチ  i ch i 
ニ  n i 
サン  s a N
ヨン  y o N
ゴ  g o
ロク  r o k u
ナナ  n a n a
ハチ  h a ch i
キュウ  ky u:
ジュウ  j u:
% OFF
オフ  o h u
% ON
オン  o N
% DENKI
デンキ  d e N k i
% CHOUKOU
チョウコウ ch o: k o:
% JOUYATOU
ジョウヤトウ j o: y a t o:
% EAKON
エアコン e a k o N
% TENKIYOHOU
テンキヨホウ t e N k i y o h o:
% NS_B
<s>  silB
% NS_E
<s>  silE

julius.conf
-input mic
-h hmmdefs_ptm_gid.binhmm 
-hlist logicalTri

-n 5
-output 1

-rejectshort 800
-demo
-debug
-lv 5000


コマンド
$ ../dist/bin/julius -C julius.conf  -gram cmd


出力結果は以下のようにほぼ間違いなく認識できるようになった。

pass1_best: <s> デンキ <s>        
WARNING: 00 _default: hypothesis stack exhausted, terminate search now
STAT: 00 _default: 2 sentences have been found
sentence1: <s> デンキ <s>
pass1_best: <s> ラジオ イチ <s>        
WARNING: 00 _default: hypothesis stack exhausted, terminate search now
STAT: 00 _default: 2 sentences have been found
sentence1: <s> ラジオ イチ <s>
pass1_best: <s> エアコン オン <s>        
WARNING: 00 _default: hypothesis stack exhausted, terminate search now
STAT: 00 _default: 2 sentences have been found
sentence1: <s> エアコン オン <s>
pass1_best: <s> エアコン オン <s>        
WARNING: 00 _default: hypothesis stack exhausted, terminate search now
STAT: 00 _default: 2 sentences have been found
sentence1: <s> エアコン オン <s>
pass1_best: <s> テンキヨホウ <s>          
WARNING: 00 _default: hypothesis stack exhausted, terminate search now
STAT: 00 _default: 1 sentences have been found
sentence1: <s> テンキヨホウ <s>
pass1_best: <s> チョウコウ <s>            
sentence1: <s> チョウコウ <s>
pass1_best: <s><input rejected by short input>
pass1_best: <s><input rejected by short input>

しかし、記述文法方式だと無意味な発音も無理やり認識してしまう。
「こんにちは」と発音しても「デンキ」となってしまう。

勿論スコアがあるのだけどコマンド毎に数値の基準が違ったり、全く別の発音でも高スコアだったりして判定できない。

結局、false positiveが多すぎて使えない・・・うーむ。

amazonアソシエイト