光源追跡マイクロロボット MR-LST-1406
株式会社アイ・エス・ティさんの「光源追跡マイクロロボット MR-LST-1406」のキットを組み立てました。縦横1インチ(2.54センチ)角、高さ19mm、重量ぴったり10.0gの、小さなロボットです。高さは、部品の足を短く組めば、あと2mmくらい低くできそう。
電源はLR44型ボタン電池2個。車輪を動かす2個のモーターは、1円玉と比べてもかなり小さいのがわかります。それでも、想定外のスピードできびきびと走ります。
回路図はシンプルです。明るさを検知してモーターを動かす回路が、左右それぞれに一系統ずつあります。まず、フォトトランジスタ ST23G で明るさを検知します。明るさの検出は、昔なら CdS が一般的でした。応答速度が数十msと遅く、素子によるバラツキが大きいとのことなので、おそらく今回のような制御には向かないのでしょう。応答速度の遅さがデメリットかというとそんなこともなく、昼夜を識別するセンサーの場合は光の点滅による誤動作が起きにくいため、今でも数多く使われているようです。
さて、光量に応じて出力された電流を、トランジスタ 2SC1815 で増幅します。その増幅した電流でモーターを動かします。光源に向けて進めるためには、右が明るければ左の車輪をより多く回し、左が明るければ右の車輪をより多く回す必要があります。したがって、左のフォトトランジスタは右のモーターを制御し、右はその逆になっています。
こんな素朴なアナログ回路でも、光源の追跡ロボットが作れるのですね。
組み立ては、電子回路部分は特に問題ありませんでした。基盤が小さいので、何か固定する道具があると作業性が上がりそうです。メカ部分に、やや何があります。車輪の外周を、モーターの軸で直接駆動することで、ギア比を下げつつ車輪を回転させています。車輪の中心軸を回すのではなく、外周を回すのです。そのため、車輪の位置、半径、モーターの軸の位置に精度が要求されます。
僕の場合は、最初に動かしたときは右の車輪が空回りして、ライトを当ててもその場をくるくる回るだけでした。車輪をはめる穴を、ほんの少しだけ削ったり、モーター方向に近づくように力をいれつつ取り付けたりして、空回りは回避できましたが、モーターの回転の伝達力が左右で違うことには変わりなく、期待通りには光源を追ってくれませんでした。それでも、だいたいの方へは走ってくれます。
小学校高学年から中学生までの電子工作教室でも使っているとのことなので、車輪とモーターの調整のコツがわかれば、精度良く動くのかもしれません。
購入先:アールティのロボットアイル(秋葉原) 価格:ロボット本体が1,500円。別売りのライントレースユニットが900円。
はじめてのチップ部品半田付け
チップ部品半田付け練習キットと銘打ってLEDをチカチカできるキットがあったので、やってみました。チップ抵抗のサイズは 2012 と呼ばれる、2mm x 1.25mm のもの。アマチュアが手半田をするのは、難易度と部品の入手性により、この 2012 か、1608(1.6mm x 0.8mm)のものが定番のようです。DMM.make Akiba のチップマウンタは、0402 (0.4mm x 0.2mm)まで対応していると、説明会のときにおっしゃっていました。部品の長辺がシャープペンの芯よりも小さいというのは、もう、手作業では無理ですね。
やってみてわかったのは、部品が半田の山の上に浮き上がってしまうことが多いこと。ピンセットで押さえながら再加熱すると、ぴたっと張り付いてくれます。浮き上がるのは、加熱不足でしょうか。あと、大型の電池ホルダ、といっても端子は5mm角ですが、これを表面実装で半田付けするには、ワット数が大きめの半田ごてが必要です。手元にある22Wでは、なかなか半田が溶けてなじんでくれませんでした。
ちなみにこれは、しおりだそうです。本に挟むやつ。
月
初めて月を撮影した。Pentax K-x、標準の望遠レンズキット300mm、ISO 200、F8、1/30秒。 三脚がないので、ベランダの手すり + 適当な厚みの本で固定し斜め上に向けて撮影。 輪郭がぼやけているのはブレだろうか。
Yosemite で libv8 と therubyracer をインストールする
Mac OS X 10.9 Mavericks 以降だと、libv8 と therubyracer の gem がインストールできないじゃないですか。毎回遭遇するけど、毎回苦しんでいます。
キモは、libv8、therubyracer、OS のバージョンの整合性。あとは定番のオプションを付けること。
http://inoao.hatenablog.com/entry/2014/03/27/183523 に、超便利な表がありました。が、Yosemite が載っていないので、最新版はこうなります。Yosemite = darwin-14 の値は、自分で試してうまくいった組み合わせです。
| CPU | OS | OS Version | libv8 | therubyracer |
|---|---|---|---|---|
| amd64 | freebsd | 8 | 3.3.10.4 | 0.10.2 |
| 9 | ||||
| x86 | darwin | 10 | ||
| 11 | ||||
| linux | ||||
| freebsd | 9 | 3.11.8.3 | 0.11.0 | |
| x86_64 | darwin | 10 | ||
| 11 | 3.3.10.4 | 0.10.2 | ||
| 12 | 3.11.8.3 | 0.11.0 | ||
| 13 | 3.16.14.3 | 0.12.1 | ||
| 14 | 3.16.14.7 | |||
| linux | 3.11.8.3 | 0.11.0 | ||
手順としては、まず、自分の OS のバージョンを調べます。
$ ruby -rubygems -e 'puts Gem::Platform.new(RUBY_PLATFORM)'
x86_64-darwin-14
OS X 10.10 Yosemite の場合、darwin-14 になりました。普通に bundle install すると、以下のように失敗します。
$ bundle install --path vendor/bundle
…(略)…
Installing kaminari 0.16.1
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
/Users/takah/.rbenv/versions/2.0.0-p353/bin/ruby extconf.rb --without-system-v8
…(略)…
An error occurred while installing libv8 (3.16.14.3), and Bundler cannot continue. Make sure that `gem install libv8 -v '3.16.14.3'` succeeds before bundling. </code>
なので、上記の表を見て、Gemfile と Gemfile.lock のバージョンが合うように修正します。
さらに、ビルドオプションも付けてやります。gem コマンドでインストールするだけなら、以下のように – で区切ってオプションを渡すことができます。
$ gem install libv8 -v '3.16.14.7' -- --with-system-v8
bundle install でインストールする場合、コマンドラインで直接オプションを指定できないので bundle config コマンドを使います。
$ bundle config build.libv8 --with-system-v8
$ bundle config build.therubyracer --with-v8-dir
このコンフィグオプションは build_info に保存されます。
$ cat vendor/bundle/ruby/2.0.0/build_info/libv8-3.16.14.3.info
--with-system-v8
さて、これで bundle install してみましょう。
$ bundle install
一旦 bundle install –path vendor/bundle すると、オプションが .bundle/config に保存されて、次回以降は –path オプション無しでも同じ動作をしてくれます。
うまく行きました! I’m so happy!
AWS の Route53 でドメインを作成するスクリプト
R53 でドメインを作成するコマンドラインを Ruby で書いた。
使い方
$ ruby create_record -d ドメイン名 [-h ホスト名]
ex) ruby create_record -d google.com -h rarara
-d ドメイン名、だけを指定すると、新規に hosted zone を作成し、
Aレコードと MXレコードを作成する。
-h ホスト名、も付けると、そのドメインの下に Aレコードと
MXレコードを作成する。
コード
require 'rubygems'
require 'aws-sdk'
require 'optparse'
AWS.config( access_key_id: ‘xxxxxxxxxxxxxxxxxxxxx’, secret_access_key: ‘xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx’ ) IP=’xxx.xxx.xxx.xxx’
def create_record domain, host = nil
r53 = AWS::Route53.new zone = r53.hosted_zones.select { |z| z.name == “#{domain}.” }.first
host1 = host ? “#{host}.#{domain}.” : “#{domain}.” host2 = host ? “www.#{host}.#{domain}.” : “www.#{domain}”
r53.client.change_resource_record_sets( hosted_zone_id: zone.id, change_batch: { changes: [ { action: ‘UPSERT’, resource_record_set: { name: host1, type: ‘A’, ttl: 300, resource_records: [ value: IP ] } }, { action: ‘UPSERT’, resource_record_set: { name: host2, type: ‘A’, ttl: 300, resource_records: [ value: IP ] } }, { action: ‘UPSERT’, resource_record_set: { name: host1, type: ‘MX’, ttl: 300, resource_records: [ value: “10 #{host1}” ] } }, ] } ) end
def create_hosted_zone domain r53 = AWS::Route53.new resp = r53.client.create_hosted_zone({ name: “#{domain}.”, caller_reference: domain }) puts “Name servers:” for ns in resp[:delegation_set][:name_servers] puts ns end create_record domain end
options = {}
OptionParser.new do |opts| opts.banner = ‘Usage: create_record [options]’ opts.on(‘-h [HOST]’, ‘–host [HOST]’, ‘hostname’) do |v| options[:host] = v end opts.on(‘-d [DOMAIN]’, ‘–domain [DOMAIN]’, ‘domain’) do |v| options[:domain] = v end end.parse!
if options[:host] create_record options[:domain], options[:host] else create_hosted_zone options[:domain] end </code>