#はじめに
この記事は、Life is Tech ! アドベントカレンダー2017 22日目の記事です.
はじめまして岐阜のiPhoneメンターこと __ぬっきー__です.
普段は岐阜にあるIAMASという学校に住んでいる大学院生です.
そんな私は1年前にiPod20台を通信/制御/連携してみた【Max × Swift × OSC】ということでクラブ空間での新しい演出に繋がらないかと
真面目()に取り組んでいました.
大量に光らせることに満足できず、次は大量に動かしたいなと思い、
この一年は大量にサーボモータをiPodから稼働させていました.
ゴム手袋の中にサーボモータ2つを入れて画面を操作する不気味な…
技術的におもろい点としてはArduinoなどのマイコンを一切使わず
iPod端末からサーボモータ2つを制御することができるGlueMotorです.
そんなことがiOS端末からできちゃうん!?
そんな楽しいワクワクを思う存分今年は紹介したいとおもいます
#本記事について
GlueMotorまわりの基礎をおさえ、ハードを自作&自作アプリから制御できるまでが本記事のゴールです.
回路やらSwiftの基礎についてはあまり触れません、ごめんなさい.
- GlueMotorとは
- GlueMotorを自作
- GlueMotorを制御するアプリを実装
- 実践例
GlueMotorとは、寺崎和久さんによって開発された、端末のイヤホンジャックにプラグを差し込むだけで、サーボモータを制御できてしまう魔法のようなケーブルのことです.
『Arduinoなどのマイコンを一切使わずに老若男女だれでも簡単にモノとモノを糊のようにくっつけることができればいいな』という素敵な想いが込められたんだとか…涙
共立プロダクトさんからはプチロボS2として商品化もされています.
このケーブルとセットでstoreに存在するアプリをインストールすることですぐに使い始めることができます.
GlueMotor2(iOS)
GlueMotor(iOS)(iOS4の場合)
GlueMotor(Android)
またGlueMotorは米国シリコンバレーの Maker Faire Bay Area にて5年連続の受賞や米国版『Make:』magazine では製作記事も掲載されるほど素晴らしいのです.
そして何より素敵なのが…
GlueMotorのハードもアプリも自作できてしまうということ!!
GlueMotor公式サイトでは自作する方法が書かれていて、githubにアプリのコードも記載されています.
Android,JavaScript,iOSの3つが含まれています.
本記事ではその自作手順を、中高生でもハード初心者でも分かるように + 個人的な知見を含みつつ解説していきたいと思います!
ほな
#GlueMotorを自作してみよう【ハードウェア編】
###原理
まずそのGlueMotor原理についてですが、端末のイヤホンジャックから特定の周波数を発生させサーボモータに伝えることで特定角度の制御をしているということです.
これは偶然にもラジコン用サーボモータの制御信号がオーディオの周波数帯域に当てはまるということだからだそうです.しゅごい.
###必要な物
- 3.5mm ステレオミニプラグ 3極
- 電池ボックス
- ケーブル(コネクタ付だと尚良い)
さて以下が電子回路図です.
(サイトより引用)
######(※ここで注意しておきたいのがC1,C2のコンデンサーについてですが、基本的にはiOS端末であれば特に必要ありませんが故障などを防ぐためにつけておくとbetterですね)
さぁこれを作ろう!!
回路図初心者向けにはイメージ図を用意したので参考にしてみてください
これをあとははんだ付けすればOK
###サーボモータについて
サーボモータについてですが、相性がどうやらあるみたいでサイト内ではFutaba S3003標準サーボモーター($10.99)やParallax(Futaba)標準サーボ($12.99)が紹介されています.
個人的に苦学生でありながら大量のサーボが必要だったため、様々なモーターを試した結果一番安く、動作の確認もできたのがVstone 標準サーボモータ(¥648)でした.
webからの購入もできますし、秋葉原での直接購入も可能ですのでご参考までに
###+α 給電方法
特に必須ではないですが、電池ボックスじゃ足りんという方はUSB二股とDCケーブルとDCジャックを用いて端末に給電しながらモーター給電も可能なので、よければ実践して見てください.
- USB-DCケーブル(対応した内径) ¥200
- DCジャック(対応した内径) ¥80
- USB(オス)=USB×2口(メス) ¥250 (変換名人)
#GlueMotorを自作してみよう【アプリ編】
続いてアプリの実装です.
今回はiOS端末からサーボモーターを制御するのでAndroid,JavaScriptはまた別のタイミングorどなたかぜひ書いてみてください.
###導入手順
1.はじめの方に共有したGitHubのページからファイルをまずはダウンロードしてきてください.
2.ファイルの中身を見てもらうとわかる通りObjective-Cのコードのためswiftで使用する場合はbridgingheaderを作ります.
オリジナルのプログラムの中で"GlueMotorCore"というグループを作成してください.
次にそのグループの中に"GlueMotorCore.h"と"GlueMotorCore.m"の2つをdrag & drop しちゃいましょう.(ちゃんとグループの中につっこむことが大事
するとbridgingheaderを作れるようになります.(詳しいことはこちら)
うまくいくと、以下のようにBridging_Header.hが追加されています
出来上がったBridging_Header.hファイルの中に次のように書きましょう
#import "GlueMotorCore.h"
これで導入は完了しました、続いて中身を実装していきます.
###実装
####UIの作成
アプリの見た目をまずは作っていきましょう、サーボモータ2つを制御するのでUISliderを2つ用意するのと、その値を表示するためのUILabelも一緒に
このときに気をつけることはUISliderの設定値です
Value : 0.0015
Minimun : 0.0006
Maximum : 0.0025
続いて中身をごりごり書いていきます.
なるべく細かくコメントを挟んでみました.
import UIKit
class ViewController: UIViewController,GlueMotorCoreDelegate/*GlueMotorのデリゲートまわり*/ {
//UILable,UISliderまわりの宣言
@IBOutlet var servoALabel:UILabel!
@IBOutlet var slideMotorA:UISlider!
@IBOutlet var servoBLabel:UILabel!
@IBOutlet var slideMotorB:UISlider!
//GlueMotorまわり
var glueMotor:GlueMotorCore!
var servoAPulseWidth:TimeInterval!
var servoBPulseWidth:TimeInterval!
//角度調整用値
var angleAmountA = 0.0000001
var angleAmountB = 0.0000001
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
glueMotor = GlueMotorCore.sharedInstance() as! GlueMotorCore
glueMotor.delegate = self
//待機状態の数値をsliderに反映させる 初期値は0.0015
slideMotorA.value = Float(0.0015)
slideMotorB.value = Float(0.0015)
//モータへの周波数にも反映させる
servoAPulseWidth = TimeInterval(slideMotorA.value)
servoBPulseWidth = TimeInterval(slideMotorB.value)
//ラベルにも表示させる
servoALabel.text = "A:"+String(format:"%f", servoAPulseWidth * 1000)
servoBLabel.text = "B:"+String(format:"%f", servoBPulseWidth * 1000)
//周波数をupdate
self.updatePulseWidth()
}
@IBAction func slidercahngedA(_ sender : UISlider){
//Sliderが変更された時に周波数も変更
servoAPulseWidth = TimeInterval(sender.value)
self.updateLabels()
}
@IBAction func slidercahngedB(_ sender : UISlider){
print(sender.value)
servoBPulseWidth = TimeInterval(sender.value)
self.updateLabels()
}
//周波数をupdate
func updatePulseWidth(){
glueMotor.setPulseWidth(servoAPulseWidth, forServo: 1)
glueMotor.setPulseWidth(servoBPulseWidth, forServo: 0)
}
//labelの表示変更
func updateLabels(){
servoALabel.text = "A:"+String(format:"%f", servoAPulseWidth * 1000)
servoBLabel.text = "B:"+String(format:"%f", servoBPulseWidth * 1000)
}
//glueMotorお約束
func glueMotorCoreWillStartPWMCycle(_ glueMotor:GlueMotorCore){
// NOTE: this delegate method will be called in Audio Queue thread, so don't call the UI related API from here.
self.updatePulseWidth()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
これであとは関連付けをしっかりと行ってあげるとしっかりと動くはずです.
おつかれさまでした!!
あとは自動的に角度を制御したり、OSCを受けて無線で動かしたりとか、なんでもできるようになりましたね.
#実践例
一つの手段をお見せしたに過ぎないので、でできることは未知数です
とある方々はサーボモータの動作確認をするために、GlueMotorコードとアプリだけでarduinoなしに確認ができるから便利だとか
あるいはサーボモータを使った制作物の動きの簡単なプロトタイピングにもおすすめです.
私は修士の修士の習作と修士作品で使わせていただきました、よかったら見てみてください〜
###< crawlMob2 (2016) >
はじめてGlueMotorを用いた制作、この時は電池を持たせてOSC通信によって無線で繋がらせ、群れを作ろうとしました.
###<node hands (2017) >
修士作品として制作したnode hands はサーボモータ2つを用いて人の親指の動きを制御する簡易ロボットハンド20台によるインスタレーション作品です.詳しくはタイトルのリンクで飛んでみてみてください.
##最後に
最後まで読んでいただきありがとうございます、
今回の記事を作成するにあたり、寺崎さんに感謝申し上げます.
GlueMotorに出会わなければ作れなかった作品ばかりの自分としては、少しでも多くの方にこの技術が広まれば嬉しい限りです!
明日はデザインもモーショングラフィックもエンジニアリングもなんでもできるフルスタック王子のシオン君です、お楽しみにー!