できること

Arduino LeonardoでつくるUSB周辺機器で音量調整に挑戦!

Arduinoは、USBのインターフェースを持っているので、キーボードやマウスなどのパソコンの周辺機器も自作できます。

もちろん、キーボードそのものを作ることもできますが、いきなり作るのは大変です。そこで本記事では、一部のキーボードに付いている音量を調整する部分をArduinoで作ってみます。

Arduinoと可変抵抗器(ポテンショメーター)があれば簡単です。早速、始めましょう。

translated-usb-volume-control-with-arduino-01

Arduino Leaonardoの外観

 

目次

  1. 準備
  2. USBを使った通信でパソコンをコントロール
  3. エンコーダーにも使用される可変抵抗器
  4. スケッチ全体
  5. プログラムを詳細に見てみよう
  6. Arduinoと可変抵抗器をつなげよう
  7. まとめ

 

1. 準備

本記事では次のものを使用します。

Arduino Leonardo

translated-usb-volume-control-with-arduino-02

可変抵抗器

translated-usb-volume-control-with-arduino-03

Arduino IDE

 

今回はArduino Unoではなく、Arduino Leonardoを使用します。
Arduino Leonardoは、キーボードやマウスなど、USBに接続する周辺機器を作成できるHID機能が備わっているので、任意の文字列のPC入力や、マウスのスクロール操作のようなUSBインターフェースデバイスとして使うことが可能です。

可変抵抗器は、後ほど解説します。

上記に加えて、micro USB(マイクロUSB)ケーブルを用意してください。

本記事は、スケッチの操作、動作確認にWindowsを使用しています。ほかのOSでは、動作が異なる場合もあるので注意が必要です。

 

2. USBを使った通信でパソコンをコントロール

Arduinoは、接続しているパソコンとUSBで通信する機能を搭載しています。
Arduino Unoなど、ほとんどのArduinoボードは、USBの通信とスケッチを実行するマイコンが別々に搭載されています。このようなArduinoボードでは、パソコンのUSBに接続する周辺機器を作るには大変な作業です。

技術的にはArduino UnoでもHoodloader2ライブラリを組み合わせれば、USB機器として動作できますが、この方法は難易度が高いので、最初からUSBのインターフェースを内蔵しているマイコンを搭載したArduinoボードを使用するのがおすすめです。

 

本記事では、Arduino Unoから派生した、Leonardoを使用。
Arduino Leonardoスケッチを実行するマイコンに、ATmega32u4が搭載されています。
ATmega32u4はUSB通信機能を内蔵しているマイコンなので、その機能をうまく応用することでマウスやキーボードのような、USB接続の周辺機器を簡単に制作できます。

標準ライブラリだけでもマウスやキーボードののような入力デバイスを簡単に作成できますが、今回は一歩進んで、音量調整やPLAY・PAUSE・STOPボタンなどの機能を持つマルチメディアキーを作ってみましょう。

マルチメディアキーに対応するには、Arduino IDEにライブラリを追加する作業が必要です。

ライブラリには、特殊な処理を実行するためのソースコードがまとめられています。
サーボモーターの制御や、キーボード・マウスの自作をサポートするものなど、数多くのライブラリが、Arduino IDEに組み込まれています。
あらかじめ用意されているライブラリだけでなく、サードパーティーが提供するものや、自作のライブラリの追加もできるので、Arduinoを使った電子工作の可能性は無限に広がります。

 

今回は、サードパーティー製のHID-Projectと呼ばれるライブラリを使用。

[スケッチ]メニューから[ライブラリをインクルード]>[ライブラリを管理…]を選択してください。
次に[検索をフィルタ]に「hoodloader」と入力してください。
すると、「HID-Project by NicoHood」が見つかるはずなので、最新のバージョンを選択して、[インストール]をクリックします。
これで、HID-projectライブラリが、使用できるようになりました。

 

3. エンコーダーにも使用される可変抵抗器

可変抵抗器は、英語で「potentiometer: ポテンショメーター」と呼ばれています。本来、ポテンショメーターは、回転角や移動量を調整するデバイスの総称ですが、内部に可変抵抗器が使用されていることから、英語では「可変抵抗器=ポテンショメーター」と呼ばれるようになったようです。

日本でも、回転角や移動量を調整する目的で使用する場合には、「ポテンショメーター」と呼ぶ場合もあります。
本記事では、混乱を避けるために「可変抵抗器」と呼び方を統一します。

また、「可変抵抗器」に似たデバイスに「半固定抵抗器」がありますが、基本的に両者の機能は同じと考えていいでしょう。筐体からシャフトと、1番・2番・3番の3本の端子が出ています。シャフトを回すことで「1番」と「2番」、「2番」と「3番」の端子間の抵抗値が変わります。
ただし、端子名は製品によって異なる場合があるので、使用前に、データーシートで確認してください。

 

可変抵抗器と半固定抵抗器の違い

可変抵抗器と半固定抵抗器の違いは、その強度にあります。
可変抵抗器は、機器の目立つ場所に取り付けられ、音量の調整など、頻繁に動かされることを想定した、丈夫な作りになっています。一方、半固定抵抗器は、基板上などに実装され、電子回路の調整に使われることが多いです。頻繁に操作する部分ではないので、強度より小型化が重視されています。

 

可変抵抗器は、人間がシャフトを回転することによって、端子から出力される信号(電圧)が変わります。

その電圧を、マイコンボードが読み取ることで、シャフトの位置を検出。このとき、電圧は0Vから5V(電源電圧)まで、アナログ的に変化します。製品によって違いはありますが、出力される電圧が2.5Vの時は、シャフトの位置が中間となります。
マイコンボードで、このアナログ的な変化を読み取るには、「A/D変換」という機能を使用します。
A/D変換は、アナログ入力ピンの現在の電圧を、そのまま数値で表現できるのです。

可変抵抗器は、必ずしも人間が回転する必要はありません。シャフトの部分を、モーターに取り付ければ、「モーターが何度回転したのか」を読み取ることが可能です。この機能を「エンコーダー」と呼びます。
ホビー用のサーボモーターは、この仕組みを利用して、正確な位置決めを実現しています。

 

4. スケッチ全体

Arduino Unoに転送するスケッチは以下の通りです。

#include <HID-Project.h>

int potpin = 0; // Assign analog pin to potentiometer
int val = 0; // Variable to read value from potentiometer, starts at 0
int oldVolume = 0; // Used to compare volume levels
int currentVolume = 0; // Used to compare volume levels

void setup() {
    Serial.begin(9600); // This will allow you to read the current value of the dial
}

void loop() {
    val = analogRead(potpin); // Reads potentiometer value (between 0 and 1023)
    val = map(val, 0, 1023, 0, 50); // Scale value to volume (value between 0 and 50)
    Serial.print(val); // Print dial/volume position
    Serial.println(); //

    if (val != oldVolume) {
        if(val > oldVolume) {
            //delay(100);
            Consumer.write(MEDIA_VOLUME_UP);
            currentVolume = currentVolume + 1;
            if (currentVolume > 50) {
                currentVolume = 50;
            }
            oldVolume = currentVolume;
        }
        else {
            //delay(100);
            Consumer.write(MEDIA_VOLUME_DOWN);
            currentVolume = currentVolume - 1;
            if (currentVolume < 0) {
                currentVolume = 0;
            }
            oldVolume = currentVolume;
        }
    }
}

上記のソースコードをArduino IDEにコピー&ペーストしてください。

 

5. プログラムを詳細に見てみよう

可変抵抗器の読み取りや、その値をパソコンに送る方法など、スケッチの重要な部分を解説します。
Arduinoボードに転送する前に確認しましょう。

 

①インクルードファイルの読み込み

最初の行は、インクルードファイルの読み込みです。

#include <HID-Project.h>

マルチメディアキーの処理を提供するHID-projectライブラリを、先ほど読み込みましたが、それだけではスケッチで利用できません。忘れずにインクルードファイルの読み込みをしてください。

 

②グローバル変数の定義と初期化

次に、グローバル変数の定義と初期化が続きます。

int potpin = 0; // Assign analog pin to potentiometer
int val = 0; // Variable to read value from potentiometer, starts at 0
int oldVolume = 0; // Used to compare volume levels
int currentVolume = 0; // Used to compare volume levels

最初の行は、可変抵抗器からの入力を受け取るアナログ入力ピンの番号を指定。ここでは「A0(0番)」を指定しています。
可変抵抗器の現在の位置情報は、2行目の変数valに格納されます。最初に0で初期化しておきましょう。

 

USBのインターフェースでは、直接、パソコンに音量の値を指定できないことになっています。
そのため、スケッチからパソコンには、「少し大きく」や「少し小さく」のように指示します。
Windowsで設定できる音量の範囲は、0から100なので、その範囲を超えるまで、パソコンは指示を受け付けます。
Arduinoからの「少し大きく」や「少し小さく」の指示で、パソコンは2段階ずつ音量が変わるようです。

また、Arduinoから、パソコンの現在の値を取得することもできません。スケッチの中では「今、何回指示を出したか」を数えることで、パソコンの音量を0から100の範囲に収めます。
残りのoldVolumeとcurrentVolumeは、その「何回指示を出したか」を記憶する現在の音量をカウントする変数です。どちらの変数も、最初に0で初期化しておきます。

 

looop()関数内のコードを解説

val = analogRead(potpin); // Reads potentiometer value (between 0 and 1023)
val = map(val, 0, 1023, 0, 50); // Scale value to volume (value between 0 and 50)

この2行は、可変抵抗器の現在の位置を読み取っています。

analogRead()関数は、指定されたアナログ入力ピンの状態を取得。変数potpinには0が格納されているので、ここではアナログ入力ピン「A0(0番)」の電圧を読み込みます。

Arduinoのアナログ入力は、ピンにかかる電圧(0Vから5V)を、0から1023の1024段階(1段階は4.9mV)で読み取ります。変数valには、読み取った値が格納されます。

ただし、0から1023は、パソコンに対する指示としては細かすぎるので、map()関数を使用して、0から50までの範囲に丸めてください。map()関数は整数を出力するので、丸める際に小数部分は切り捨てられます。
ここで、最大値を50にするのは、Arduinoからの指示によって、パソコンの音量が2段階ずつ変化するためです。音量が0の状態から100になるまでに、50回「少し大きく」と指示を出します。

 

③音量の指示出し

以下のコードは、可変抵抗器の現在の値に応じて、パソコンに音量を「少し大きく」や「少し小さく」と指示を出す部分です。

 

if (val != oldVolume) {
    if(val > oldVolume) {
        //delay(100);
        Consumer.write(MEDIA_VOLUME_UP);
        currentVolume = currentVolume + 1;
        if (currentVolume > 50) {
            currentVolume = 50;
        }
        oldVolume = currentVolume;
    }
    else {
        //delay(100);
        Consumer.write(MEDIA_VOLUME_DOWN);
        currentVolume = currentVolume - 1;
        if (currentVolume < 0) {
            currentVolume = 0;
        }
        oldVolume = currentVolume;
    }
}

 

④読み取った可変抵抗器の値と、音量をカウントする変数の値を比較

読み取った可変抵抗器の値と、スケッチ内部の現在の音量をカウントする変数の値を比較します。
変化がなければ、外側のif文は実行されず、プログラムは何もしません。可変抵抗器が少しでも変化すると、if文の中が実行されます。

可変抵抗器が「少し大きく」の方向に回転した場合は、Consumer.write()関数を呼び出して、パソコンにMEDIA_VOLUME_UPを送信してください。
これによって、「パソコンの音量が上がった」はずなので、現在の音量をカウントする変数の値は増加します。

この動作は、loop()関数が呼び出されるごとに、可変抵抗器の値と、現在の音量をカウントする変数の値が一致するまで実行されます。

 

反対に、可変抵抗器の値が「少し小さく」の方向に回転した場合は、パソコンにMEDIA_VOLUME_DOWNを送信し、現在の音量をカウントする変数の値を減少します。
この動作も、可変抵抗器の値と、現在の音量をカウントの値が一致するまで繰り返します。

 

6. Arduinoと可変抵抗器をつなげよう

ソースコードの実装が終わり、スケッチが完成したらArduinoボードに転送しましょう。
その後、一旦、パソコンにつながっているUSBケーブルを取り外して、可変抵抗器を次の手順で配線してください。

  • 可変抵抗器の「1番」端子をArduinoボードの「GND」と接続します。
  • 可変抵抗器の「2番」端子をアナログ入力ピンの「A0(0番)」と接続します。
  • 可変抵抗器の「3番」端子をArduinoボードの「5V」と接続します。

translated-usb-volume-control-with-arduino-05

Arduinoに接続された可変抵抗器(イメージ)

 

配線が終わったら、Arduinoボードを再びパソコンに接続します。
通常の電子工作であれば、Arduinoを常にパソコンに接続しておく必要はありませんが、今回は、USB接続で動く周辺機器を作ったので、USBケーブルでパソコンに接続する必要があります。

 

いよいよ本番です。
可変抵抗器の値とパソコンの音量が最小の状態で、Arduinoボードをパソコンに接続して可変抵抗器を動かすと、音量が大きくなり上手く動作するはずです。
可変抵抗器を操作しても、意図したように音量が動かない場合は、配線の確認や、可変抵抗器の端子の位置をデーターシートで確認してください。

スケッチの中にdelay()関数を呼び出している行があります。可変抵抗器の動作に合わせて、スムーズに音量が変化しない場合は、ここを調整してください。
サンプルのスケッチはコメント状態(//から行末まで)になっているので、Arduinoボードの動作には影響を与えません。このコメント記号(//)を取り除くことで有効化できます。

 

7. まとめ

Arduinoボードには、さまざまな種類があり、Leonardoのように、標準でキーボードやマウスの作成をサポートするライブラリが用意されているものがあります。
さらに、サードパーティー製のライブラリを使えば、音消・PLAY・PAUSE・STOPボタンなどのマルチメディアキーも実装できます。

今回の記事では、ライブラリを利用することで、USB接続で動作する周辺機器もArduinoを使えば簡単に制作できることを紹介するため、シンプルな構成にしました。
USBの周辺機器の製作は、一見すると難しく感じます。一つ一つ、ゆっくりと進めていけば、単純な制御の組み合わせなので、怖がらず、ぜひ、挑戦してください。

アバター画像

エレクトロニクスやメカトロニクスを愛するみなさんに、深く愛されるサイトを目指してDevice Plusを運営中。

https://deviceplus.jp

高専ロボコン2016 出場ロボット解剖計画