久々の工作日記。
しばらく前からリモートワークやWEB会議が多くなり、ヘッドホンやイヤホンをつけたまま仕事をすることも多くなりました。
会議中に唐突にマイク音の大きい人がしゃべることにより、聞きたくもないおっさんの吐息が耳の中へ流れ込みます・・・( ゚Д゚)
急いでボリュームを絞ろうとして、別のアイコンをクリックしてしまったりするので、単独でPCのボリュームをグリグリ調整できるコントローラが欲しくなりました。
キーボードのショートカットでも操作できますが、両手を使わないといけないので、とっさには操作しづらい・・・
市販品もありますが、カッコいい市販品は無駄に高い・・・
中華品の製品を見てみたらと、質素な基盤とツマミだけで数千円するので、これなら自分で作れるぞ!っと調査開始。
Arduinoを使ってコントローラを作っている人がいるようなので、自分も真似してみました。
完成です。
素材はジャンクパーツから外してあった部品で作成。
可変抵抗の電圧値をArduinoで読み取ってやり、PCへボリューム変更の信号を送ります。
素材
・100均の缶カラ
・可変抵抗
・なんか良さげなノブ
・ケーブル
・ピンソケット
・Arduino UNO (ここが失敗・・・)
こういうものは触った時の重さが質感を出すので・・・
中華風ナットでずっしり作戦!
デットニング材を張り付けることで、触った時の”カラカラ”いう安っぽい軽い音も防止。
Arduino Leonardo(互換機)を使用。
ArduinoはUnoではなく、Leonardoを使用しました。
こいつが何かっていうと、PCとつなげることでマウスやキーボードなどのUSBデバイスとして認識させることができます。
つまり、マウス操作などをプログラムすることで、誰も操作していないのに定期的にマウスが動き、リモートワーク中に「退席中」にならないデバイスが作れるわけです。
当初、手持ちのArduino Unoのファームウェアを書き換えて、USBデバイスとして認識させようと思いましたが、自分のはバージョンが古いR2であったためうまくできませんでした。(海外フォーラムだと成功例あり??)
Arduino UNO R3であれば、ATmega16U2のファームウェアを書き換えれば、HIDキーボードデバイスとして認識させることができるようです。
ArduinoUno作戦がうまくいかなかったため、急遽Arduino Leonardoの互換機(600円)を追加購入しました。
んで出来たのが上の写真。
Arduino Leonardoがキーボードとして認識され、可変抵抗から出た電圧を読み取り、その値の変化に応じてPCへ音量Up/Downの信号を送ります。
ここで何も考えず作業を始めてしまったことで、失敗に気づく・・・
当初、可変抵抗を動かすことで、PCへ送る信号として「PCの音量を20%にしろ」、「PCの音量を50%にしろ」という信号を送れると考えていました。
でも良く調べてみると「PCの音量を1上げろ」、「PCの音量を1下げろ」しか指令できないことに気づく・・・
可変抵抗は回転範囲が限られているため、上で書いたような指令の出し方では相性が悪い。
回転の絶対位置でボリュームが規定できるわけではなく、現在の音量設定からの相対位置で指示を送ることになるので、PC側で音量を変更した場合、可変抵抗の角度と差が生まれてしまいます。
たとえば、
理想: 最小0 ⇔ 最大100
可変抵抗の最小点を音量0、最大点を音量100にするのが理想。
でもPC側の音量をマウスで変更してしまうことで、PC音量100、でもノブの位置は最小地点で、これ以上下げられない!って状況が生まれてしまいます。
音量を下げる側に動かせない・・・
素直に初めからロータリーエンコーダを使用するべきでした。エンコーダなら今の位置からの角度変化を検出して指示が送れるので、こんなことはおきません。
そこで、音量を最小にしたときに、「音量を1下げる」信号を送り続けて、初期位置補正をするようにしました。
扱いになれれば、とても便利なデバイスになりました(/・ω・)/
これで唐突な音量変化にも対応できるぞ!
安いエンコーダも買ってあるので、気が向いたときに組み替えたいと思います。
キーボード操作部分のヘッダーファイルは
この記事を参考にさせていただきました。
#include "ConsumerControl.h"
int val_old;
int cnt = 0; // 音量最小時のカウント 音量が一番小さいときにカウントを開始。
// 最小時に25カウント以上すると通信を終了する。
void setup() {
Serial.begin(9600);
}
void loop() {
int val = analogRead(0);
int valm = map(val, 0, 1023, 0, 100);
Serial.println(valm);
// ボリュームを最小にしたとき ⇒ 音量小ボタンを押し続ける。
if (valm <= 1 & cnt < 25) { // 25カウント以上ループした場合、機能を無効化する。
Serial.println("Volume DOWN");
ConsumerControl.press(VOLUME_DOWN); // 音量小ボタンを押す
ConsumerControl.release(); // ボタンを離す
val_old = valm;
cnt = cnt + 1;
}
// ボリュームを大きくする
if (valm > val_old + 2) {
Serial.println("Volume UP");
ConsumerControl.press(VOLUME_UP); // 音量大ボタンを押す
ConsumerControl.press(VOLUME_UP); // 音量大ボタンを押す
ConsumerControl.press(VOLUME_UP); // 音量大ボタンを押す
ConsumerControl.release(); // ボタンを離す
val_old = valm;
cnt = 0;
}
// ボリュームを小さくする
if (valm < val_old - 2) {
Serial.println("Volume DOWN");
ConsumerControl.press(VOLUME_DOWN); // 音量小ボタンを押す
ConsumerControl.press(VOLUME_DOWN); // 音量小ボタンを押す
ConsumerControl.press(VOLUME_DOWN); // 音量小ボタンを押す
ConsumerControl.release(); // ボタンを離す
val_old = valm;
cnt = 0;
}
// 変化がない場合
if (valm == val_old) {
Serial.println("-------");
}
delay(20);
}