2016年12月29日木曜日

お手軽DTM環境を構築する(VirtualMIDISynthとDomino)

はい、こんにちは。

----今やDTMではMIDIのみで打ち込みなんて下火だと思います。
しかし、曲のスケッチや耳コピをするのであればMIDIで十分すぎると思うのです。----

今回はソフトシンセとシーケンサでMIDI打ち込み環境を構築します。
(普段私はTimidity++使いですが、こっちは難易度が高いので次回)


1. 概要

 ソフトシンセとは、コンピュータの中でシンセサイザーの仕組みをエミュレートして動作するソフトウェアのことを指します。ソフトシンセに任意の音色を導入することで自分好みの音色を発声するシンセにカスタマイズすることが可能です。
 サウンドフォントとは、ソフトシンセに導入できる音色ファイルを指します。様々な楽器の音色が格納されており、ソフトシンセに認識させることでその音色を用いて演奏することが可能です。
 シーケンサとは、音符を並べてコンピュータが読める楽譜を作成し、それをシンセサイザーに送るソフトウェアを指します。この楽譜のことを一般的にMIDIファイルと呼びます。シーケンサには様々な種類がありますが、現在の主流はピアノロールを採用したものです。
 つまり、今回の目標はソフトシンセを起動させ、シーケンサをソフトシンセに接続することです。

2. 用意するもの

各ファイルをダウンロードします。SGM-V2.01は7zで圧縮されているので、お好きな解凍ソフト(ex. Lhaplus)を用いて解凍しましょう。

3. ソフトシンセの導入

 CoolSoft_VirtualMIDISynth_1.17.1.exeを起動し、ウィザードを完了すると次のような画面が現れます。

図1 SoundFont選択画面

右の+ボタンをクリックし、先程解凍したSGM-V2.01.sf2を選択します。OKを押して閉じます。

4. シーケンサの導入

 Domino143.zipを解凍し、Domino.exeを起動します。

図2 Domino初期画面
メニューバーからファイル→環境設定に行きます。左のツリーからMIDI-OUTに行きます。

図3 MIDI-OUT設定画面
ポートAのMIDI OUTデバイスにCoolSoft VirtualMIDISynthを選択し、音源にSC-8850を選択します。

5. お疲れ様でした。

 おめでとうございます。Dominoに適当に音符を置いてみましょう。音がなれば成功です。手持ちのMIDIファイルがあれば開いて再生してみましょう。
 Dominoの使い方についてはネットに豊富にあるのでそちらにお任せします。また、今回導入したサウンドフォントで物足りないと思った人は、「サウンドフォント おすすめ」で検索をかけてみましょう。図1の画面で複数のサウンドフォントを重ねて導入することが可能です。また、レイテンシを気にする人はその他の設定の追加の出力バッファの値を小さくしてみましょう。
 なお、ソフトシンセの設定画面はスタートメニューからConfigure VirtualMIDISynthで開くことが可能です。

図4 Configure VirtualMIDISynth
  何か質問がありましたら、コメント欄かTwitterでコメントください。ではでは。


2016年11月14日月曜日

論理パーティションにWindows OSはインストール可能?

ご無沙汰しています。


 たまたま手元にWindows7のライセンスがあったので、Linux Mint + Win10 + Win7 のトリプルブートを試し、そのときに躓いたある出来事を書きます。

1. 「Windows OSはプライマリパーティションにのみインストール可能」は本当か?


 もともと、私のPCにはWindows10とLinux Mintが入っていました。Windows10をクリーンインストールすると「システムで予約済み」、「OSパーティション」、「回復パーティション」という3つのパーティションが作成されます。この3つは「プライマリパーティション」と呼ばれる分類に入ります。そして、Linux Mintは拡張パーティション内に作成した論理パーティションにインストールしていました。つまり、この時点でHDDにはプライマリパーティションが4つ存在していました。(※拡張パーティションはプライマリパーティションと同等に扱われる)

 私がパソコンのマニュアルを読み漁っていた小学生の時には、マニュアルに「プライマリパーティションは一つのHDDに最大4つまで作成でき、OSはプライマリパーティションのみにインストールできる」という記述があったと記憶しています。MS-DOSベースのWindows Meのマニュアルだったので、当時はその通りだったのだと思います。(懐かしい)

 BIOS環境下で用いられるMBR(マスターブートレコード)のパーティションテーブルが扱えるパーティションの数は4つであり、現在もプライマリパーティションは4つまでしか作成できません。それ以上のパーティションが必要となった場合は、プライマリパーティションの一つを拡張パーティションとして割り当てて、その中に論理パーティションを作成するという手法で対処できます。ただし、MS-DOSベースが主流だった時代では論理パーティションにはOSをインストールすることはできなかったのです。



図1 Windowsで典型的なBIOSディスクパーティション

私は、「現状4つのプライマリ/拡張パーティションが存在するHDDに、更にWindows OSを入れるのは不可能ではないか。」と思い込んでいました。そこで、何か良い解決策がないかと検索を掛けてみると、驚愕の事実が発覚しました。

「Vista以降のWindowsを拡張パーティションにインストールする事が可能!」

 え?前提が覆りましたね・・・。
 この記述に従えば、最近のOSはプライマリパーティションだけでなく、拡張パーティション(論理パーティション)にもインストールする事が可能になっていたことになります。私の知識は間違いだったのでしょうか???

2. ブートストラップローダとブートローダ


 ここでコンピュータがブートする時のプロセスを勉強しなければなりません。(長いぞ~)

 かつてのBIOSベースのコンピュータでは、最初にMBRに書き込まれた「ブートストラップローダ」と呼ばれる小さなプログラムが読み込まれます。ブートストラップローダはMBRに書き込まれているパーティションテーブルを調べ、アクティブ(起動可能)なパーティションを探し出します。そして、ブートストラップローダがアクティブなパーティションのブートセクタ(PBR:パーティションブートレコード)に書き込まれた、更に大きなプログラム(IPL:イニシャルプログラムローダ)を呼び出すことでブートが続行されます。しかし、この方法ではパーティションテーブルに記述されているパーティションにしか飛ぶことが出来ないため、ブート可能なパーティションはやはりプライマリパーティションに限定されてしまいます。

 そこで天才は考えました。「IPLからもっと高度なブートを可能にするプログラムを呼び出せば良いのでは?」と。素晴らしい。ブートストラップローダから更に高度なブートストラップローダを呼べばいいっていう発想。拍手喝采。

 そのプログラムの名は。君の名は。「ブートローダ」。こっちのほうが馴染みがあるかもしれません。有名なものとしてはGRUB、NTLDR、Windows Boot Manager(以下。WBM)あたりでしょうか。

図2 ブートプロセス

 現在のBIOSベースのコンピュータの殆どがこのプロセスでブートします。ブートストラップローダ→IPL→ブートローダ、というようにどんどんプログラムを呼び出していく方式をチェインロードと言います。
 さて、ブートローダは高度なブートを可能にするプログラムです。ブートストラップローダとは違い、MBR上のパーティションテーブルではなく自前のパーティションテーブルを参照することが出来ます。即ち、パーティションを正しく指定すれば、プライマリパーティションだけでなく、論理パーティションにインストールされたOSも起動できる(!!!)。今回のミラクル(?)はこれが理由だったわけです。

 では、なぜVista以降から可能になったのか。それは採用しているブートローダがNTLDRからWBMに変更されたからだと推測されます。NTLDRでは以前のブートストラップローダと同様にプライマリパーティションからのブートのみに対応していましたが、WBMではよりブートの自由度が広がりました。BCD(Boot Configuration Data)に正しくロードするプログラムを記述すれば、論理パーティションやVHD(Virtual Hard Disk)からでもブートできます。
 ちなみに、Windowsのブートローダに限らずGRUBやLILOをインストールしてある環境では同様に論理パーティションからブートが可能です。

図3 EasyBCDによるBCDストアの編集


3. WBM万歳!!知識は常に新しいものを仕入れましょう


 今回のまとめをします。

 「MBR環境下でかつブートローダにWBMを採用している場合は、論理パーティションを作成しそこにOSをインストールすることができる!」です。なんだかスッキリしましたね。

図4 現在のパーティション構成


 知識は常に新しいものを取り入れていかないと、時代の流れに置いて行かれてしまいます。(置いてかれんだ~♪)正直、私のコンピュータの知識はWindows XPあたりで止まっていたのでしょう。情けない話ですね。


ということで、皆様もいろんなOSをインストールして楽しいマルチブートをお楽しみ下さい!!

4. 参考文献


「Q&A COLLECTION」

「Windows7が4つのマルチブート環境を作りたいのですが・・・・・」

「Windowsの起動ディスクとパーティション入門」

「OS のブートシーケンス」

「BIOS ベースの推奨ディスク パーティション構成」

「Windows Boot Manager」




2016年9月18日日曜日

電気工学特別講義「三相交流を用いたリニアモーターカーの制御」の回路図とプログラム(VVVFインバータ)

特別講義履修した皆様、発表お疲れ様でした。  夏休み、大変でしたね…

僕はといえば、他の班の発表のポスターの出来が凄くて発表前ちょっと焦りました^^;


 さて、今回は、僕達が制作したリニアモーターカーを駆動する回路、即ち三相インバータの回路図とプログラム(スケッチ)をこちらで紹介しようと思います。なお、語句の説明は記事の最後を参照してください。

 1. 回路図

回路図を下に示します。

図1 三相インバータ回路図

今回、僕が作成した三相インバータは、直流電源からPWM(パルス幅変調)を用いてMOSFETのスイッチングを行うことで三相交流を作り出す、ごく一般的なインバータです。

2つのNch型MOSFETが1つのスイッチを構成しており、それを3つ用意することで1つの直流電圧から3つの独立した出力電圧を発生させることが出来ます。3つのスイッチを適切なタイミングで切り替えていくことで位相差が120度の3つの交流を発生させます。

スイッチングをするための信号はArduino(マイコン)とハーフブリッジドライバによって生成されます。Arduinoの出力ピンから3つの信号線が出ており、それらはMOSFETに接続されているハーフブリッジドライバのV_INに接続されています。ハーフブリッジドライバはV_INからの入力を元にHOとLOから信号を出力し、2つのMOSFETを同時に制御します。

各MOSFETのドレイン・ソース間に接続されているダイオードは還流ダイオードと呼ばれ、モータのような誘導性負荷を出力に接続した場合に発生する逆起電力によるMOSFETの破壊を防止します。誘導性負荷は電流の急激な変化をすることができず、スイッチングをしたときにソースに電流が流れ込んでくる可能性があるため、電流の逃げ道として接続してあります。

3つの出力端子(U/V/W)には三相交流を用いる負荷(ここではリニアモータを指す)を接続します。詳しい話は省略しますが、リニアモータは三相誘導電動機を切り開いた形となっているので配線も切り開いた形で行います。

ちなみに、直流電源に並列に接続してあるコンデンサはバイパスコンデンサの役割を持たせています。電圧の急激な変化を平滑化する働きがあります。

2. プログラム(スケッチ)

Arduinoでは、プログラムのことをスケッチと呼びます。(以下スケッチと呼ぶ)
スケッチを以下に記します。

//使用するピンの指定 13番ピンは内部LEDによるクロック表示用
int Uout=3;
int Vout=9;
int Wout=11;
int Clock=13;
int tsumamiPin = 0;

//各種変数の宣言
int sinw[360];
int InductorU = 0;
int InductorV = 120;
int InductorW = 240;
int ang;
int MODE;
int mag;
double f, d;
double tsumamiHenkan = 1.0;//出力電圧の振幅の大きさの倍率
long t1, i;

//初期化
void setup()  {
  t1=millis();
  Serial.begin(9600);

  //1度単位のsinのテーブルを作成
  mag = 96;//0~127の範囲で設定
  for(ang=0;ang<360;ang=ang+1){
    sinw[ang]=mag*(sin(ang * 3.14/180)+1);
    }
   
  //各出力ピンのモードを出力に設定
  pinMode(3, OUTPUT);//インダクタ接続
  pinMode(9, OUTPUT);//
  pinMode(11, OUTPUT);// 
  pinMode(13, OUTPUT);//内部LED接続
}

//メインプログラム
void loop()  {
  //6周期(2160/360=6)ごとに方向を転換する
  if(i % 4320 == 2160){
  InductorU=0;
  InductorV=120;
  InductorW=240;
  Serial.println("GO");
  Serial.print(f);
  Serial.println("Hz");
  }
  else if(i % 4320 == 0){
  InductorU=0;
  InductorV=240;
  InductorW=120;
  Serial.println("BACK");
  Serial.print(tsumamiHenkan*12*mag/127);
  Serial.println("V");
  }
 
  f = (double)analogRead(tsumamiPin) * 0.007595308;//可変抵抗の値から周波数を計算する
  //f = (double)analogRead(tsumamiPin) * 0.01;
  if(f >= 0.001){
    d = 1.0/(f * 360.0);
  }
  else if(f < 0.001){
    d = 0.01;
  }

  //v/f制御 周波数に比例して電圧を変化させる
  if(analogRead(tsumamiPin) > 256){
    tsumamiHenkan = analogRead(tsumamiPin)/1023.0;
  }
  else{
    tsumamiHenkan = 0.25;
  }
  //PWMで出力ピンから電圧を出力する
  analogWrite(Uout, sinw[InductorU] * tsumamiHenkan);
  analogWrite(Vout, sinw[InductorV] * tsumamiHenkan);
  analogWrite(Wout, sinw[InductorW] * tsumamiHenkan);
 
  //1周期ごとに内部LEDを点灯させる
  if(InductorW  == 0){
    digitalWrite(Clock, HIGH);
  }
  else{
    digitalWrite(Clock, LOW);
  }
 
 
  //U,V,Wの角度を進める
  InductorW = update_phase(InductorW);
  InductorV = update_phase(InductorV);
  InductorU = update_phase(InductorU);
 
  //設定した周波数に応じて遅延させる 遅延関数の仕様により使い分ける
  if(d * 1000000.0 > 16383.0){
    delay(d * 1000.0);                   
  }
  else{
    delayMicroseconds(d * 1000000.0);
  }
  //delay(d);
  i++;//角度をカウントアップする                 
}


//角度を進める
int update_phase(int Inductor){
  Inductor = Inductor+1;
  if(Inductor>=360) Inductor=0;
  return Inductor;
}

コメントに沿ってスケッチを見ていきましょう。


最初に、ピンの指定を行います。使用するピンは出力3,9,11,13番、入力0番ピンです。
インバータ駆動用の信号線は3,9,11番ピンです。これらのピンはPWM出力が可能で、周波数は約490Hzです。
13番ピンは交流電圧が一周期変化した時にArduino内部のLEDを点灯させるためのものです。
入力0番ピンは可変抵抗の値を読み取る為に用います。(後述)

続いて変数を幾つか宣言していますが、後ほど正体がわかりますので割愛します。

初期化のブロックでは、PCとのシリアル通信の開始、正弦波の値の計算、出力ピンのモード設定を行います。
PCとの通信は主にデバッグ用で、車両の向き、交流の周波数、出力電圧をPCに表示させます。
正弦波の値を1度刻みで360度まで計算し、配列に代入します。Arduinoの性能的にリアルタイムで値を計算させると処理落ちする可能性があるため、それを回避するためにここで事前に計算させます。
出力ピンのモード設定はお忘れなく。

さて、メインプログラムに入ります。が、ここで三相交流について軽く触れましょう。
三相交流において、U相、V相、W相から出力される電圧は位相差が120度です。位相の正負を変えることで回転磁界の方向(≒モータの回転方向)を変えることが出来ます。ちなみに普通の交流でもモータを動作させることが出来ますが、回転方向は起動時の方向に固定されてしまいます。
さて、各相の角度は先程の変数の宣言のブロックで初期化を行っていました。初期値は0度、120度、240度にしてありますので、この角度から1度ずつ進めていきます。角度が2160度(6周期)進んだときに、各相の角度は0度、-120度、-240度で初期化され、車両の走行方向が逆転します。これを繰り返すことで周期的な往復走行を実現します。

周波数の設定は入力ピンに接続された可変抵抗の値から計算します。適切なレンジに設定しましょう。なお、f=0のときに周期が∞にならないように適当な値を代入しています。

今回のミソである、V/f制御のブロックです。ここでは周波数に応じて出力電圧の倍率を変化させます。
V/f制御とは、出力電圧と周波数を1次関数的に変化させることで低速から高速までトルクを一定に保ったままモータを動作させることを可能にする制御方式です。今回は比較的滑らかに走行する電圧と周波数のデータを取り、それを元に関数を決定しました。なお、低速時には大きなトルクが必要となる(トルクブースト)ので、電圧を固定するようにしてあります。

そして、PWMで出力ピンから電圧を出力します。初期化ブロックで計算した正弦波の値と先程の倍率を掛け合わせることでリアルタイムで出力電圧を変化させます。(まぁこっちの方がマイコンの負荷も軽いでしょう^^;)

これまでの動作が終了したところで角度を一度進め、遅延させます。
遅延させるというのはArduinoではよく使われる手法ですが、○秒電圧を出力するというときに使います。周波数の設定でお気づきの方もいるとは思いますが、周波数から周期を計算し、それを360で割った値を変数dに代入しています。dは”角度が1度進むときに電圧を出力する時間”というわけです。まぁあれですよね。連続関数もコンピュータで離散的に処理する必要があるってわけです。
遅延関数は仕様の関係で使い分けています。


ざっと説明しましたが、いかがでしょうか。何か意見がありましたらコメントをよろしくお願いします。


※PWM(パルス幅変調)・・・電圧のオンオフの時間の比率(デューティ比)を変化させ、平均的に任意の電圧を出力する手法
※MOSFET・・・金属酸化物半導体を用いた電界効果トランジスタ。ソース、ゲート、ドレイン端子を持ち、ゲートに電圧をかけることでソースからドレインに電流の通り道が生成され、導通する。
※インバータ・・・直流を交流に変換する回路。対して交流を直流に変換する回路はコンバータと呼ばれる。なお、NOT回路のことではない。

2016年8月29日月曜日

3年夏休み(長いです)

夏休みも半分終わり、秋の雰囲気さえ感じさせる雰囲気ですが、皆様いかがお過ごしでしょうか。

僕にとってはこの夏休みが実質最後の長期休暇です。悲しいです。来年は院試の勉強か、就活のラストスパートでヒィヒィ言っていることでしょう(笑)

時に、自分がこの大学に入り、この学科で勉強してきたことが自分にとって幸せだったかどうかを考えることがあります。大学生になって3年目の今、何を思うのか。今回は今までの道のりを振り返りつつ、将来のことについて少し書きます。忙しい人は中略してもらって構いません。

***

僕は幼い頃からコンピュータが好きでした。
小学一年生のとき、父親からお下がりのノートパソコンを貰ったのが始まりです。付属のマニュアルを何度も熟読し、色々試しては色々失敗し、パソコンの使い方を体得しました。マニュアルで覚えた漢字も少なくなかったと思います(笑)。

パソコンは僕にとってまさに魔法の道具でした。インターネットで知りたい情報を簡単にかつ迅速に入手できるし、自分のアイデアをデータという形にすることもできました。
幼心にも、パソコンの持つ様々な可能性に気づいていたのかもしれません。

その中の一つに、小学校低学年の頃に作成した新聞があります。これはその当時NHKで放送されていた「趣味悠々とっても楽しい中高年のパソコン教室」という番組で紹介されていた新聞を作ってみようという内容の真似事で、自分や家族の近況を写真をつけて書きました。
ある日、作成した新聞を小学校に持っていったところ担任の先生に評価され、それが校長先生にも伝わり校長先生にも褒められました。これはとても嬉しかったことを覚えています。

この頃から、パソコンで何かを作り、人々を楽しませることが自分にとっても楽しいことであると気づいたのだと思います。他にもボイスレコーダーで自分の声を録音してみたり、カメラで動画を撮って編集することもやってみました。

いつもパソコンばかり弄っていた僕は、ついに父親よりもパソコンに詳しくなってしまいました。そして、小学校高学年の時には家のパソコン周りのメンテナンスはほぼ自分が受け持つようになりました。この時、ネットワークに接続されている複数のパソコンを管理することの難しさと面白さに気づいた(いわゆるインフラ整備の類ですね)のだと思います。

中学生になった頃、動画投稿サイトの勢いが隆盛し、僕のパソコンへの興味は加速的に増加しました。前述のとおりパソコンを用いることで自分のアイデアを形にできると僕は考えていましたが、動画投稿サイトのように比較的容易に作品を公開できる場所が誕生したことで、多くの人々が作品を製作し公開すると共に多くの人々がそれらを鑑賞することが可能になりました


以前はサーバーが配信するコンテンツをクライアントが受信し楽しむという一対一なコミュニケーションが主流でした(もちろん掲示板などはこれに限りません)が、ここでサーバーはクライアント同士の双方向的なコミュニケーションの中継地点としての役割を担うことになりました。中央集権的なサービスから分散型サービスへの転換と言ってもいいでしょう。分散型サービスは現在もホットなトレンドになっていることは皆様もご存知かと思います。(TwitterやFacebookなどのSNSに代表されますね)


閑話休題。中学三年生になり動画投稿サイトの投稿に影響を受けた僕は、吹奏楽部で培った音楽的センスを使って耳コピ、作曲に手を出し始めました。自分も頑張ればネットで評価されるような作品を制作することができるのではないか、という淡い期待もあったかもしれません。

何曲か拙作を作りましたが、結局大々的に公開することはありませんでした。しかし、あーでもないこーでもないと悩みつつも夢中で作曲に取り組んでいる時はとても楽しいものでした。真っ白なキャンバスに何かを描きはじめることは非常に難しいですが、自分の思い通りの作品ができた時の喜びは他に代え難いものであると考えています。

ところが高校生になると特進クラスに入り、受験勉強へのシフトを余儀なくされました。いや、最後は自分でこの選択肢を選びとったわけですが。今まで続けてきた創作活動はほとんど休むことになりました。自分のやりたいことを考える前に、とりあえずは大学に受からないことには始まらないと思ったからです。

***

このような軌跡を描き、現在に至ります。

大学生になってから、正直なところ自分は一ミリも成長していないんじゃないかと思います。ただ課題やレポートに追われ、長い通学時間は睡眠に当て、本当に自分がしたいことをゆっくり考える時間がなかった。言い訳でしょうか、多分そうでしょうね。でもこれが現実でした。

しかし大学3年生になった今、将来自分がなにをしたいのかをじっくり考えなければならない時期がやって来ました。最後の裁判の時が訪れたのです。

もはや大学受験の時のような、なんとなくの動機で将来を選択することは出来ません。なんとなくの動機で選択したところで、おおよそ後悔する結果が待ち受けていることでしょう。

自己分析という言葉がありますが、こうやって自分の過去を思い出し分析することで自分はどういう人間であるかというマニュアルを作る作業であると表現されることがあります。だからこうやって連々と文章を書いているわけです。あわよくば自分の本当の気持ちに気づくことが出来るのではないかと。

就職するのか、院に進学するのか。少なくとも、僕は生粋の研究者というものとは対極の位置にいる人間であると思っています。僕は自分達の力で何かしらのコンテンツもしくはインフラを作り、維持することで、他の人々に喜びを与えるという役割を果たしたいと思っています。パソコンを使うことに慣れ親しんだ身としては、パソコンを一から作ることよりもパソコンを用いて何かをすること(アプリケーション)に興味が有るのです。

他の人々に喜びを与えるという役割を果たす、それを具体的にはどのような形で実現するのか。そこの考えを詰めることが出来れば将来ももう少し見通しの良いものになるのでしょう。非常に難しいですが、本当の幸せを見つけるための大事な一歩として、残された時間を有意義に使おうと思います。こんなことを考える夏休みでした。


最後まで読んでくださり、ありがとうございました。

2016年8月18日木曜日

Windows起動時にbatファイルを管理者権限で実行する方法

僕のPC、どうもおかしい。


DellのLatitude E6220というPCを使っているのですが、このPCにはSDカードスロットが装備されています。

ところが、Windows10の環境下において起動時に何故か毎回SDカードスロットが無効化されてしまいます。正確に言えば、SDカードスロットがぶら下がっているPCI Express Root Portが無効化されてしまいます。

有効化してみると普通に使えるのでデバイスに致命的な問題があるとは思えないのですが、未だに原因は分からずじまい。

さあ、どうするか。それなら、起動時に毎回SDカードスロット(Root Port)を有効化するバッチファイルを実行すればいいじゃない!





というわけで、実際にやってみましょう。

1. バッチファイルの作成

デバイスの有効化を行うプログラムはdevcon.exeというもので、バッチファイルはこれに引数を渡して特定のデバイス(ここではRoot Port)を有効化するために用います。devcon.exeは予めダウンロードしておき、Windowsフォルダとかに入れましょう。バッチファイルは以下のように作成します。

----sd_on.bat----

devcon enable "PCI\VEN_8086"

たったこれだけです。簡単でしょう?第二引数はハードウェアIDで、デバイスマネージャーから参照することが可能です。作成したバッチファイルはCドライブ直下に置いておきましょう。

2. タスクスケジューラにタスクを登録

コンピュータの管理からタスクスケジューラ→タスクスケジューラライブラリを開きましょう。
画面右のメニューの基本タスクの作成をクリックします。



全般タブで、一番下の「最上位の特権で実行する」にチェックを入れてください。devcon.exeは管理者権限でなければ実行できません。



トリガータブに移り、新規よりトリガーを作成します。この時、ログオン時に設定し、任意のユーザーのラジオボタンにチェックを入れてください。





操作タブに移り、新規より操作を作成します。操作はプログラムの開始、プログラムのパスは先程のバッチファイルを指定してください。


これで完了です。次回ログオン時にバッチファイルが実行されることを確認してください。

natsuki_botの関数解説①

皆様に好評(?)を頂いているnatsuki_bot(@natsukitus)。

元々は知り合いのnatsukiの迷言集を呟くだけのbotだったのですが、返信機能がつき、スケジュール機能がつき、終いには天気予報がついた意味不明なbotとなってしまいました。笑

そろそろ開発を終了するつもりなので、このシリーズでは私が独自に追加した関数について、自分なりの解釈を含めつつ解説していきます。


今回は、natsuki_botの主要機能となったメモ機能です。

ソースコードを下に示します。簡単のため、一部を省略してあります。


 //タイムラインへの反応を作る
 function makeReplyTimelineTweets($timeline, $replyPatternFile){
 if(empty($this->_replyPatternData[$replyPatternFile])){ $this->_replyPatternData[$replyPatternFile] = $this->readPatternFile($replyPatternFile); }
        $replyTweets = array();
        foreach($timeline as $tweet){
            $status = "";

   if(preg_match ('/(.*)#(.*(メモ|めも))(.*)/s',$tweet["text"], $matches) === 1){
    $status = $this->MEMORANDUM ($tweet, $matches);
   }

            //リプライパターンと照合
            foreach($this->_replyPatternData[$replyPatternFile] as $pattern => $res){
                if(preg_match("@".$pattern."@u",$tweet["text"], $matches) === 1 && !preg_match("/\@/i",$tweet["text"])){                                        
                    $status = $res[array_rand($res)];
                    for($i=1;$i convertText($status, $tweet);
            //フッターを追加
            $status .= $this->_footer;

            //リプライ相手、リプライ元を付与
            $rep = array();
            
  switch(true){
  //リプライ反応をTLに発言
  case stristr($status, "[[TLH]]"):
  $status = str_replace("[[TLH]]","",$status);
  $rep["status"] = $status;
  $rpid = (string)$reply->id;
  file_put_contents($this->_logDataFile,$rpid);
  break; 
  //その他
  default:
  $rep["status"] = "@".$tweet["user"]["screen_name"]." ".$status;
  } 


            $rep["in_reply_to_status_id"] = $tweet["id_str"];      
            //応急処置
            if(!stristr($status,"[[END]]")){
                $replyTweets[] = $rep;
            }
        }                        
        return $replyTweets;    
    }          




 function MEMORANDUM ($tweet, $matches){
   //var_dump($matches);
   $filename = "memo/{$matches[2]}.txt"; 
   if (!file_exists($filename)){
     touch($filename);
     chmod($filename,0666);
   }
   $date = date ("Y-m-d H:i");
   $filename = "memorandum.txt";
   $matches[0] = str_replace("#.*","",$status);
   $matches[0] = htmlspecialchars_decode($matches[0]);
   $nakami = preg_replace("/#(.*(メモ|めも))/", "", $matches[0]);
   $matches[0] = preg_replace('/\n/', '{kaigyou}', $matches[0]);

   $txt = $date."\t".$matches[0]."\r\n";
   if(file_put_contents ($filename, $txt, FILE_APPEND | LOCK_EX)){
    echo "メモ登録成功。
"; }else{ echo "メモ登録失敗。
"; } $status = NULL; return $status; }


僕が作成したMEMORANDUM関数は引数が$matches、返り値が$statusです。
$matchesはpreg_match関数を用いてツイートを分解し、要素を配列に入れたものです。
$statusは最終的にツイートされる文章です。すなわち、メモ完了ツイートです。


さて、誰かが「テストです #ミズヒトメモ」と呟きます。すると、この関数にはまず次のような配列$matchesが渡されます。

[0] => "テストです #ミズヒトメモ"
[1] => "テストです"
[2] => "ミズヒトメモ"
[3] => ""

これはpreg_match関数の動作の特徴になります。preg_match関数では、()で囲われた正規表現による文字列を検索パターンとし、検索対象の文字列の中でそのパターンに合致したものを順番に配列に入れていきます。ただし、0番目の要素は検索対象の文字列そのものが入っています。

配列が渡されると、最初にメモを記録する用のtxtファイルを参照します。
ここで、txtファイルが存在しない場合は新たにtxtファイルを作成します。touch関数でファイルを作成し、chmod関数で「自分もグループメンバも他人も、読み込みと書き込みができる」パーミッション(666)設定を行います。

次に、txtファイルに書き込むデータを作成します。date関数でツイートの日時を作成し、htmlspecialchars_decode関数を用いて特殊記号をデコードした$matches[0]と組み合わせて$txtに整えて入れます。

そして、最後にfile_put_contents関数で用意したtxtファイルに書き込みをします。FILE_APPENDはファイルの後ろに追記するオプション、LOCK_EXは排他アクセス(他のプログラムに書き込みをさせない)オプションです。

ところで、途中で出てきた$nakamiはpreg_replace関数を用いて$matches[0]からタグを取り去ったものです。最後の$statusで用いられているのが分かると思います。そして、return $status;によってメモ完了ツイートが戻り値として呼び出したところへ戻っていきます。

このようにしてnatsuki_botは皆様のツイートを収集してファイルに保存しています。



いかがでしたか?それほど難しいプログラムではありませんが、やはり正規表現によるマッチングでつまずく可能性が高いでしょう。何かわからないことがあったらコメントくださいね。