ブログ

ブログです

ただいまシステムの中身③ GPIOを使ったサーボモータ制御

前回までで命令系統が完成したから、いよいよサーボモータ制御についてご紹介。今回使うサーボモータはPWM (Pulse Width Modulation, パルス幅変調)制御のやつ。
f:id:hira-hide:20170429171428p:plain
そもそもPWMってなんだよって人のために軽く説明すると、上の図みたいに一定周期(T_cycle)である幅(T_duty)だけ電圧を高くするようなやつのこと。このT_dutyを短くしたり長くしたりすると、それに応じてサーボモータが動く仕組み。

今回の流れは、まずGPIOコントロール用ソフトのWiring Piってやつをインストールして、その後にサーボ制御用プログラムを書く感じ。

今回使う「GWSサーボ PIC/STD/F」ってやつはいっくら探してもデータシートが見当たらなかったんだけど、ダメ元でSG-90と同じ値使ったらうまく動いたから助かった。

T_cycle T_duty V_high
20ms 0.5 - 2.4ms 4.8 - 5.0V

T_duty=0.5msが-90度、2.4msが90度に対応する感じ。

参考ページ

今回の参考ページはこちら。
hombre-nuevo.com
hombre-nuevo.com
blog.enjel.chips.jp

Wiring Piのセットアップ

まずはI2Cライブラリのインストールをして、その後GitでWiringPiのソースをダウンロードしてインストール、最後にWiringPi2をインストールする流れ。
なんかよく分からんけど、Raspberry Pi3でWiringPiをpythonから呼び出すときはWiringPi2のほうが良いらしい。

I2Cライブラリインストー

Raspberry Pi3のGPIOピンのうち3番、5番、27番、28番はI2Cに使えるピンで、それのセットアップのために必要なライブラリのインストール。

$ sudo apt-get install libi2c-dev

WiringPiのソースダウンロードとインストー

Gitが入ってなかったらまずはGitのインストールから。

$ sudo apt-get install git-core

そしたらGit cloneでソースコードを持ってくる。

$ git clone git://git.drogon.net/wiringPi

wiringPiっていう名前のディレクトリでコピーされるから、そこに移動してビルド。

$ cd wiringPi
$ ./build

これでWiringPi自体はインストール完了なので、WiringPi2のセットアップ。

$ sudo apt-get update
$ sudo apt-get install python3-dev python3-pip
$ sudo pip3 install wiringpi2
$ git clone https://github.com/Gadgetoid/WiringPi2-Python.git
$ cd WiringPi2-Python
$ sudo python3 setup.py install

これでOK。

サーボモータを動かす

Raspberry Piサーボモータを動かすためには最初に書いたようにPWMを出力しなきゃいけないんだけど、Raspberry Pi3でPWM出力にハードウェアで対応してるGPIOピンは下図のPWMxと書かれてるピンのみ。
f:id:hira-hide:20170507123830p:plain
それ以外のピンでPWMをやろうとするとソフトウェア的にやらなきゃいけなくてめんどうだから、PWM対応ピンを使うのが無難(一応WiringPiの機能でSoftware PWMもあるらしい)。

さて、WiringPiでサーボモータを動かす時には pwmWrite っていう関数を使う。

void pwmWrite(int pin, int value);
Writes the value to the PWM register for the given pin. The Raspberry Pi has one on-board PWM pin, pin 1 (BMC_GPIO 18, Phys 12) and the range is 0-1024. Other PWM devices may have other PWM ranges.

引数にピン番号(int pin)と動かしたい角度(int value)を入力するんだけど、動かしたい角度は直接角度を入力するんじゃなくて「T_cycleのうちの何割をT_dutyに充てるか」を用いて指定する。
例えば「90度動かしたいなぁ」ってときは、上で書いた表から計算すると 2.4ms/20ms=12% と計算できる。
さらに、上の関数説明文の中に and the range is 0-1024 って書いてあるように、デフォルトだと 0=0%, 1024=100% を意味するようになってるから、最終的に与える引数は int(12*1024/100) となる。

サーボ制御プログラム

さーてここまで来たらあとはプログラムを書いて動かすだけだ!

#!/usr/bin/python

import wiringpi2 as wp
import sys

servo_pin = 12    # 12番ピンを指定
param = sys.argv
set_degree = int(param[1])
print(set_degree)

wp.wiringPiSetupGpio()    # 上図 pin(BOARD) の番号でピン指定するモード
wp.pinMode(servo_pin, 2)  # 出力ピンとして指定
wp.pwmSetMode(0)          # 0Vに指定
wp.pwmSetRange(1024)      # レンジを0~1024に指定
wp.pwmSetClock(375)       # 後述

move_deg = int((4.75*set_degree/90 + 7.25)*(1024/100)) # 後述
wp.pwmWrite(servo_pin, move_deg)

実行時の引数に角度を指定してこのプログラムを実行すると、指定した角度だけちゃんとサーボが動いてくれる。

さて、上で後述とした二点について。wp.pwmSetClock() はWiring PiのPWM制御のための基準周波数を決める関数で、以下の条件式が成立するらしい。

PWM周波数=Raspberry PiのPWMが持つベースクロックの周波数/(clock×レンジ)

いま、サーボのPWM周波数が50Hz、Raspberry PiのPWMが持つベースクロックの周波数が19.2MHz、レンジが1024だから、clock=18750/50=375 になる。
move_deg = int( (4.75*set_degree/90 + 7.25)*(1024/100) ) ではサーボ動作の引数を計算してるんだけど、ここでは「0度を中心として何度動かすか?」を計算している。
0度のときが7.25%、90度のときが12%、-90度のときが2.5%だから、その間を線形に計算するような式を突っ込んでるだけ。

これで音声認識、サーボ動作、2つのコアとなる機能ができたから、あとはこいつらをまとめ上げればただいまシステムは完成だ!

ただいまシステムの中身② Socketを介した認識結果のXMLパース

前回までで音声認識をする部分は完成したから、今回は認識結果を出力して渡す部分について。
まずはJuliusをモジュールモードで起動して、その後にpythonでsocketつないでxmlをもらう、といった流れ。
f:id:hira-hide:20170423165131p:plain
前回の最後にサーボ制御についても説明するとか書いてたけど、それはさらに次回。

参考ページ

今回のはほぼこちらのページを参考にさせてもらった。
blog.livedoor.jp

Juliusのモジュールモード起動

Julius起動時のオプションに -module を付けるとモジュールモードでの起動になって、クライアントからの TCP/IP 接続待ち状態になる。その状態でクライアントからの接続を受けると音声認識可能な状態になって、クライアントに認識結果をXMLで送信するようになる。
より詳細については公式ドキュメントを参照してね。
第10章 モジュールモード

ちなみに、いちいちオプションに -module つけんのめんどくせぇよってときは、前回作った設定ファイル(word.jconf)に -module を書いとけば勝手にモジュールモードにしてくれる。

Julius出力XML

JuliusのXMLは以下のような構成になってるらしい。公式ページから引用。改行コードは "\n"で、クライアントがパーズしやすくするために、メッセージ送信ごとにデータの終端として"." のみの行が送信される。

<STARTPROC/>
<INPUT STATUS="LISTEN" TIME="994675053"/>
<INPUT STATUS="STARTREC" TIME="994675055"/>
<STARTRECOG/>
<INPUT STATUS="ENDREC" TIME="994675059"/>
<GMM RESULT="adult" CMSCORE="1.000000"/>
<ENDRECOG/>
<INPUTPARAM FRAMES="382" MSEC="3820"/>
<RECOGOUT>
  <SHYPO RANK="1" SCORE="-6888.637695" GRAM="0">
    <WHYPO WORD="silB" CLASSID="39" PHONE="silB" CM="1.000"/>
    <WHYPO WORD="上着" CLASSID="0" PHONE="u w a g i" CM="1.000"/>
    <WHYPO WORD="を" CLASSID="35" PHONE="o" CM="1.000"/>
    <WHYPO WORD="白" CLASSID="2" PHONE="sh i r o" CM="0.988"/>
    <WHYPO WORD="に" CLASSID="37" PHONE="n i" CM="1.000"/>
    <WHYPO WORD="して" CLASSID="27" PHONE="sh i t e" CM="1.000"/>
    <WHYPO WORD="下さい" CLASSID="28" PHONE="k u d a s a i" CM="1.000"/>
    <WHYPO WORD="silE" CLASSID="40" PHONE="silE" CM="1.000"/>
  </SHYPO>
</RECOGOUT>
.

これをXMLパーサで受け取って解析すれば、認識結果の信頼度命令を抽出できるから、音声制御が可能になる。

Python処理

今回プログラムはすべてPythonで書いた。理由は特になくて、みんなRaspberry Pi動かすときはPython使ってるっぽいからそうしただけ。サンプルコード多いと助かるしね。
まずはとりあえずプログラム全体の掲載。

#!/usr/bin/python
# -*- coding: utf-8 -*-
import socket
import xml.etree.ElementTree as ET

def main():
    host = 'localhost'
    port = 10500

    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    client.connect((host, port))

    try:
        data = ''
        while 1:
            if '</RECOGOUT>\n.' in data:
                root = ET.fromstring('<?xml version="1.0"?>\n' + data[data.find('<RECOGOUT>'):].replace('\n.', ''))
                for whypo in root.findall('./SHYPO/WHYPO'):
                    command = whypo.get('WORD')
                    score = float(whypo.get('CM'))
                    
                    if command == u'ただいま' and score >= 0.9:
                        # ここにただいま処理
                    elif command == u'パキン' and score >= 0.996:
                        # ここにパキン処理
                    elif command == u'おやすみ' and score >= 0.93:
                        # ここにおやすみ処理
                    elif command == u'いってきます' and score >= 0.93:
                        # ここにいってきます処理
                    elif command == u'部屋つけて' and score >= 0.93:
                        # ここに部屋つけて処理
                    elif command == u'おはよう' and score >= 0.9:
                        # ここにおはよう処理
                    elif command == u'部屋消して' and score >= 0.9:
                        # ここに部屋消して処理
                    elif command == u'廊下つけて' and score >= 0.93:
                        # ここに廊下つけて処理
                    elif command == u'廊下消して' and score >= 0.9:
                        # ここに廊下消して処理
                data = ''
            else:
                data = data + client.recv(1024)
    except KeyboardInterrupt:
        client.close()

if __name__ == "__main__":
    main()

個々の処理は次回以降また説明するとして、今回はsocketとXML解析についてだけ。

Socket接続部分

host = 'localhost'
port = 10500

client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client.connect((host, port))

Socketについてはこれだけ。あ、もちろん最初に import socket は忘れないように。
今回は Host も Client も自分自身だから、IPアドレスlocalhost として、ポートはデフォルトの10500番
この宣言で socket が接続されるから、音声認識待ち状態になって認識結果をXMLで投げるようになる。

XML解析部分

try:
    data = ''
    while 1:
        if '</RECOGOUT>\n.' in data:
            root = ET.fromstring('<?xml version="1.0"?>\n' + data[data.find('<RECOGOUT>'):].replace('\n.', ''))
            for whypo in root.findall('./SHYPO/WHYPO'):
                command = whypo.get('WORD')
                score = float(whypo.get('CM'))
                
                if command == u'ただいま' and score >= 0.9:
                    # ここにただいま処理
                elif command == u'パキン' and score >= 0.996:
                    # ここにパキン処理
                elif command == u'おやすみ' and score >= 0.93:
                    # ここにおやすみ処理
                elif command == u'いってきます' and score >= 0.93:
                    # ここにいってきます処理
                elif command == u'部屋つけて' and score >= 0.93:
                    # ここに部屋つけて処理
                elif command == u'おはよう' and score >= 0.9:
                    # ここにおはよう処理
                elif command == u'部屋消して' and score >= 0.9:
                    # ここに部屋消して処理
                elif command == u'廊下つけて' and score >= 0.93:
                    # ここに廊下つけて処理
                elif command == u'廊下消して' and score >= 0.9:
                    # ここに廊下消して処理
            data = ''
        else:
            data = data + client.recv(1024)
except KeyboardInterrupt:
    client.close()

まず data という空の変数を作って、whileでずっとループを回して受け取ったデータをこの変数に格納できるようにする。
上に書いたように Julius の XML は \n. で終端されるから、それを判定基準として if を入れている。
PythonXML パーサでちゃんと処理できるように、まず xml ヘッダと改行コード(\n)を付け足して、RECOGOUT 要素以下を XML としてパースする。

実際の認識結果は タグとして渡されるから、whypo に格納して、value を見て判定を行っていく。ここでは WORD(認識した単語)と CM(信頼度)を抽出して命令実行のための判定に使っている。
f:id:hira-hide:20170423181632j:plain
print命令で WORD と CM を出力した結果はこんな感じ。あとは処理部分を記述すればだいたいおわり。

次回はサーボモータ制御について書く予定。

ただいまシステムの中身① Raspberry Piで音声認識

まず前回のおさらい。↓みたいなシステムを作った。
f:id:hira-hide:20170416211614p:plain
外観写真で説明すると、USBマイクで音声命令を拾って、それをRaspberry Piで認識して、しかるべき制御をサーボモータに送るっていう流れになる。
f:id:hira-hide:20170422162903j:plain
今回は最初の音声認識部分について書いていくゾ。手順としては、まず音声入力デバイスの優先度を変更して、Juliusっていう音声認識ソフトのセットアップをするだけ。

参考ページ

音声認識を行う上で以下のWebページを参考にさせてもらった。
qiita.com
blog.livedoor.jp
blog.livedoor.jp

USBマイクのセットアップ

事前準備

USBマイクを使えるようにするために、まずはパッケージのアップデートと各種ドライバ・ソフトウェアのインストール、マイクの動作設定とかをやってくよ。

とりあえずパッケージのアップデートから

パッケージアップデート
$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo rpi-update

アップデートが終わったらライブラリのインストール

ライブラリインストール
$ sudo apt-get install alsa-utils sox libsox-fmt-all

ちなみに、ALSA (Advanced Linux Sound Architecture)はLinux用音声ドライバ、soxは音声ファイル形式変換ソフトらしい(上記リンク先のコマンドそのまま打っただけ)

さて、ここまでやったらとりあえずUSBポートにマイクを差して、まずはちゃんとハードウェアが認識されているかのチェック。

ハードウェア認識チェック
$ lsusb
Bus 001 Device 004: ID 0d8c:0016 C-Media Electronics, Inc.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. SMSC9512/9514 Fast Ethernet Adapter
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp.
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub

C-Media Electronics, Inc.がUSBマイクらしいから、これが表示されてれば認識はOK

オーディオモジュールの優先順位変更

おそらく初期設定だと内蔵オーディオモジュールの優先順位のほうが高いはずなので、/proc/asound/modules を見て確認。

モジュール優先度チェック
$ cat /proc/asound/modules
 0 snd_bcm2835
 1 snd_usb_audio

↑みたいに snd_bcm2835(内蔵オーディオモジュール)が0番だったら、/etc/modprobe.d/alsa-base.conf を変更してUSBマイクの優先順位を変えよう。
この設定ファイルが生成されていないこともあるから、そのときは新規作成

alsa-base.conf の変更(or新規作成)
options snd slots=snd_usb_audio,snd_bcm2835
options snd_usb_audio index=0
options snd_bcm2835 index=1

これでRebootすれば優先順位が入れ替わってるはず。

マイク感度設定

音声入力するにあたって、マイク感度を適当に調節しとかないといけないから、それの設定。と、その前にサウンドカードの番号をチェック!

サウンドカード番号チェック
$ arecord -l
**** List of CAPTURE Hardware Devices ****
card 0: Micophone [USB Micophone], device 0: USB Audio [USB Audio]
  Subdevices: 0/1
  Subdevice #0: subdevice #0

card 0 と書いてあればサウンドカード番号は0番だから、感度設定の引数で0を設定

マイク感度設定
$ amixer sset Mic 62 -c 0
Simple mixer control 'Mic',0
  Capabilities: cvolume cvolume-joined cswitch cswitch-joined penum
  Capture channels: Mono
  Limits: Capture 0 - 62
  Mono: Capture 62 [100%] [22.50dB] [on]

マイク感度は0 - 62の63段階で選ぶようになってるけど、まーたぶん最大値で設定して問題ないと思う(ぼくは今のところ問題ない)。

これでUSBマイクは使える状態になったから、こっから音声認識ソフトの設定をやってくよ。

Juliusのインストールと設定

そもそもこのJuliusっていうソフトは何なのかっつーことだけど、公式サイトからまんま引用した以下の文章を読んでくれ。

Julius は,音声認識システムの開発・研究のためのオープンソースの高性能な汎用大語彙連続音声認識エンジンです. 数万語彙の連続音声認識を一般のPCやスマートフォン上でほぼ実時間で実行できる軽量さとコンパクトさを持っています.

言語モデルとして単語N-gram,記述文法,ならびに単語辞書を用いることができます.また音響モデルとしてトライフォンのGMM-HMMおよびDNN-HMMを用いたリアルタイム認識を行うことができます.DNN-HMMの出力計算にnumpyを用いた外部モジュールを利用することも可能です.複数のモデルや複数の文法を並列で用いた同時認識も行うことができます.

Juliusの最大の特徴はその可搬性にあります.単語辞書や言語モデル・音響モデルなどの音声認識の各モジュールを組み替えることで,小語彙の音声対話システムからディクテーションまで様々な幅広い用途に応用できます.

Julius はオープンソースソフトウェアです.プログラムはC言語で書かれており、さまざまなプラットフォームへの移植や改造が容易です.ライセンスはオープンライセンスで,商用利用への制限もありません.

http://julius.osdn.jp/

細かい話は専門家じゃないからよく分からんけど、動きは下の画像のような感じ。
f:id:hira-hide:20170422204747p:plain
音声入力を文字データにして、あらかじめ用意してある辞書データと比較して合致するものを探すみたい。
wgetJulius本体ディクテーションキット文法認識キットの3つをインストール。バージョンは適宜変えてくれ。あとディクテーションキットは容量がデカイから時間かかるかも。

Julius本体、ディクテーションキット、文法認識キットのダウンロードとインストール
sudo wget -O julius-4.4.2.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F60273%2Fjulius-4.3.1.tar.gz'
sudo wget -O dictation-kit-v4.3.1-linux.tgz 'http://sourceforge.jp/frs/redir.php?m=jaist&f=%2Fjulius%2F60416%2Fdictation-kit-v4.3.1-linux.tgz'
sudo wget -O grammar-kit-v4.1.tar.gz 'http://sourceforge.jp/frs/redir.php?m=osdn&f=%2Fjulius%2F51159%2Fgrammar-kit-v4.1.tar.gz'

tar zxvf julius-4.4.2.tar.gz
cd julius-4.4.2/
./configure
make
sudo make install

cd ..
tar zxvf dictation-kit-v4.3.1-linux.tgz
tar zxvf grammar-kit-v4.1.tar.gz

これでとりあえず使えるようにはなってるから、テストしてみよう。

話しかけてみよう!

あらかじめ用意されてるグラマーキット testmic.jconf を使ってきちんと認識するかどうかのテスト。julius -C ./grammar-kit-v4.1/testmic.jconf -charconv EUC-JP UTF-8 を実行すると音声認識スタンバイ状態になるから、話しかけると「あんたが今言ったのこれやな!」って返してくれるよ。
ちなみに、このテスト設定だと「みかん・りんご・ぶどう」の3つの果物について反応するから、適当に「みかん!」とか「りんご!」とか言ってみてね。

Julius動作テスト
julius -C ./grammar-kit-v4.1/testmic.jconf -charconv EUC-JP UTF-8

Notice for feature extraction (01),
        *************************************************************
        * Cepstral mean normalization for real-time decoding:       *
        * NOTICE: The first input may not be recognized, since      *
        *         no initial mean is available on startup.          *
        *************************************************************
 
Stat: adin_oss: device name = /dev/dsp (application default)
Stat: adin_oss: sampling rate = 16000Hz
Stat: adin_oss: going to set latency to 50 msec
Stat: adin_oss: audio I/O Latency = 32 msec (fragment size = 512 samples)
STAT: AD-in thread created

この状態の時に話しかければOK。ちゃんと結果が返ってきたら設定とかは問題なし。

辞書データ作成

ここまで来たらあとは自分の用途に合わせて辞書データを作成してあげればOK。認識結果はsocketを介してxmlで渡せるから、それを使って後段のサーボモータ制御をやっていく流れ。
辞書ファイルは
(単語)(タブ区切り)(読み)
の形で記述して、拡張子は.yomiとして保存すること。今回の目的は「ただいま」に反応して動作してくれればいいから基本的には「ただいま」だけ辞書登録しとけば良いんだけど、どうせならいろいろやりたいな、と思って以下のような辞書データを作った。

ただいま    ただいま
おやすみ    おやすみ
部屋つけて   へやつけて
部屋消して   へやけして
廊下つけて   ろうかつけて
廊下消して   ろうかけして
おはよう    おはよう
いってきます  いってきます
パキン     ぱきん

機能としては、

ただいま   → 部屋も廊下もつく
おやすみ   → 部屋も廊下も消える
部屋つけて  → 部屋の電気がつく
部屋消して  → 部屋の電気が消える
廊下つけて  → 廊下の電気がつく
廊下消して  → 廊下の電気が消える
おはよう   → 部屋の電気がつく
いってきます → 部屋も廊下も消える
パキン    → 部屋も廊下もつく

ってなってる。パキンってなんだよパキンってと思うかもしれないけど、これは指パッチンで部屋の電気ついたらクソおもしれぇなと思ってあとから追加した辞書データ。ちなみに動きはこんな感じ。


超おもしろかった。その代わり判定しきい値をかなり高くしてるからめったに動作しない。隠しコマンド的立ち位置。

それはさておき、辞書データを作ったらJulius用の辞書形式ファイルに変換する。
あ、ルートディレクトリは基本的に home を考えて書いてるから、適宜読み替えてください。

辞書データ変換
cd julius-4.4.2/gramtools/yomi2voca
iconv -f utf8 -t eucjp ~/word.yomi | yomi2voca.pl > ~/dictation-kit-v4.3.1-linux/word.dic

そしたら最後に設定データを作成すれば音声認識基盤の完成!

$ vi ./dictation-kit-v4.3.1-linux/word.jconf

-w word.dic       #単語辞書ファイル
-v model/lang_m/bccwj.60k.htkdic  #N-gram、または文法用の単語辞書ファイルを指定
-h model/phone_m/jnas-tri-3k16-gid.binhmm #使用するHMM定義ファイル
-hlist model/phone_m/logicalTri   #HMMlistファイルを指定する
-n 5        #n個の文仮説数が見つかるまで検索を行う
-output 1     #見つかったN-best候補のうち、結果として出力する個数
-input mic      #マイク使用
-input oss      #オープンサウンドシステム使用
-rejectshort 600  #検出された入力が閾値以下なら棄却
-charconv euc-jp utf8 #入出力エンコード指定(内部euc-jp, 出力utf-8)
-lv 1000    #入力の振幅レベルの閾値(0~32767)

これで julius -C ./dictation-kit-v4.3.1-linux/word.jconf を実行すれば上で作った辞書データを元に音声認識してくれる。

認識結果の受け渡しとそれを利用したサーボ制御については次回。

ただいまシステム

ただいまシステムと言うものをつくったお話です。

ことの発端

これまでずっと実家にいたけど、ついに家を出て一人暮らしをすることになった。一人暮らしすることはまあ別にいいんだけど、しばらく暮らしていてどうも何か物足りないな、ということに気づいてきた。

【これまで】
ぼく「ただいまー」
家族「おかえりー」
【いま】
ぼく「はぁ~~……よいしょっと(部屋の電気をつける)」

そう、ただいまがないのだ!

ほしいなぁ~~~ただいま・おかえりプロトコル

せや!ただいまに反応するなんか作ったろ!

ということで秋葉原に走った。

とりあえずこのラズベリーパイっていうの買えばいいんだろ?

たぶんラズベリーパイ買えばなんとかなるだろ!と思って秋葉原でいろいろ買った。

f:id:hira-hide:20170416205111j:plain

  • Raspberry Pi 3 model B
    WiFiは標準でついててほしかったからこれ
  • PiShow 2.8
    SPIで表示させるタッチパネル
  • GWSサーボ PIC/STD/F
    ちっちゃいサーボモーター。2個。
  • USBマイク MM-MCU02BK
    写真には載ってないけどサンワサプライのUSBマイク
  • あとこまごまとしたもの

やりたいことは↓みたいなこと。

f:id:hira-hide:20170416211614p:plain

本当はPhilips Hueとか使ってもっと賢くやりたかったんだけど、家の電気が全部蛍光灯だったから仕方なく電気のスイッチをサーボモータで物理的に動かすことにした。

出来上がったシステム

外観はこんな感じ。本当はラズベリーパイのGPIOに直接サーボつなぐのはよろしくないけど、ちっちゃいサーボだし大丈夫でしょ!

f:id:hira-hide:20170416212147j:plain

ただいまっていうとちゃんと電気つくよ!

次回以降セットアップとかプログラムとか紹介する予定。

ちょっとした一工夫で生活は遥かに豊かになる

社会人になってしまってから生活の大部分が会社で過ごす時間になって、日々の面白エピソードが必然的に社内話になっちゃってブログにはかけずヤキモキしていたけれど、「フィギュアレビュー書いてよ」って言われたから今日はそんなようなことを書くね。

ただ、フィギュアレビューに関してはぼくなんかよりずっと巧みな言葉遣いお金の掛かった撮影機材とんでもなく歓迎意欲の湧く記事を書いてくださる方々がいらっしゃるので、普通のレビューはそういう方々におまかせしてここでは撮影が楽しくなる一工夫を紹介。

被写体にはこの子を使います。ジャジャーン!

f:id:hira-hide:20161120101505j:plain

ToHeart2 AnotherDays  菜々子 ~ネコ耳スクール水着ver.~黒ネコ版」です。なんど見てもハチャメチャにかわいい。お迎えしてよかった。まだamazonでも取り扱いはあるみたいだけど定価の倍くらいの値段になってる。

 さてさてこの菜々子フィギュア、原型がとても良いからスマートフォンで適当にパシャリとしても常に性的に切り出されるとってもすばらしいフィギュアです。

f:id:hira-hide:20161120102222j:plainこんなのとか。

f:id:hira-hide:20161120102248j:plainもうちょっと胸側に寄ったのとか。

でもでも、ちょ~~っとだけ工夫を加えるだけでこの写真がさらにアトラクティングエキサイティングエレクチオンになっちゃうんだな。

手順①:適当な紙と穴あけパンチを用意!

f:id:hira-hide:20161120102559j:plain

手順②:適当に一つ穴を開ける!

f:id:hira-hide:20161120102721j:plain

手順③:穴越しに撮影!

f:id:hira-hide:20161120102806j:plain

すごい!すごい背徳感をかんじる!

f:id:hira-hide:20161120102933j:plain

みんなもやってみてね!

四の五の言わずプリペイドSIMを買え

学生の頃に(晴れて修了したのでやっとこの言葉が使える)何度も海外出張したけど、行く国行く国で現地のプリペイドSIMを買うのがぼくの楽しみの一つでもあったわけだけど、今回はミュンヘンに行った時に大変困った事になったのでそのことでも書きますね。

続きを読む

Office製品はかゆいところに手が届かないなぁ

「余計なお世話みたいな機能ばっかり付け足してどうにかして欲しいところはほったらかし」でお馴染みのOffice製品。Word、ExcelPowerpointあたりはまぁ仕方ない、目をつぶって使いましょうか、となることが多いと思うんだけど、Outlook、お前だけは看過できん。

Skype for Business (旧Microsoft Lync)との予定表連携とかは業務で使うのにはすごく良い機能だと思うんだけど、お前の本分はメーラーだぞ。なんで肝心要のその部分が使いづらいんだ。

一番致命的だと思うところは「自分自身をBCCに入れる」機能がデフォルトで搭載されていないってところだと個人的には思ってる。

と、いうわけで今回はOutlookにこの機能を追加する方法について。やり方はVBAで書いた自作マクロを登録するしかない」というなんともユーザフレンドリーな設計です。

続きを読む