ゆるく楽しむプログラミング

スイッチの状態を読み取る

Arduinoを操作するために入力機能を使ってスイッチの状態を読み取ります。
Arduinoではデジタル入力とアナログ入力が利用できます。

デジタル入力

単純に考えると▼ですが

これだと、スイッチが押されていない状態では
Arduinoのピンは何処にもつながっていない宙ぶらりんになり
入力値がHIGHでもLOWでもない不安定な値になるため
誤動作を起しやすくなります。

一般的にはこのような回路を使います


プダウン抵抗/プルアップ抵抗は電流が流れすぎないようにするために付けます。
10KΩ位の抵抗を使うのが通常のようです。

プルダウン抵抗を付けたスイッチは押すとHIGH、放すとLOWになります。
プルアップ抵抗を付けたスイッチは押すとLOW、放すとHIGHになります。



ボタン入力のスケッチ例はArduinoIDEの[スケッチ例]-[02.Digital]-[Button] にあります。
 関連する関数は次の二つです
 ピンのモード設定 pinMode(ピン番号 , INPUT)
 ピンの値読み取り digitalRead(ピン番号) 結果はHIGHまたはLOWになります。

-- Button --

// constants won't change. They're used here to set pin numbers:
const int buttonPinPD = 10;  // the number of the pushbutton (PullDown) pin
const int buttonPinPU = 11;  // the number of the pushbutton (PullUp) pin
const int ledPin =  13;      // the number of the LED pin

// variables will change:
int buttonStatePD = 0;         // variable for reading the pushbutton(PullDown) status
int buttonStatePU = 0;         // variable for reading the pushbutton(PullUp) status

void setup() {
  // initialize the LED pin as an output:
  pinMode(ledPin, OUTPUT);
  // initialize the pushbutton pin as an input:
  pinMode(buttonPinPD, INPUT);  // ★ ピンモードを入力に設定
  pinMode(buttonPinPU, INPUT);  // ★ ピンモードを入力に設定
}

void loop() {
  // read the state of the pushbutton value:
  buttonStatePD = digitalRead(buttonPinPD); // ★ ピンの値を読み取り
  buttonStatePU = digitalRead(buttonPinPU); // ★ ピンの値を読み取り

  // check if the pushbutton is pressed.
  // If it is, the buttonStateUD is HIGH or the buttonStateUU is LOW:
  if (buttonStatePD == HIGH || buttonStatePU == LOW) {
    // turn LED on:
    digitalWrite(ledPin, HIGH);
  } else {
    // turn LED off:
    digitalWrite(ledPin, LOW);
  }
}

-- 内蔵プルアップ抵抗--
Arduinoはチップ内部にプルアップ抵抗が付いています。
内部のプルアップ抵抗を有効にすることで外部のプルアップ抵抗を省略して回路を簡素化する事ができます。


この方法のスケッチ例はArduinoIDEの[スケッチ例]-[02.Digital]-[DigitalPullup] にあります。
 関連する関数は次の二つです
 ピンのモード設定 pinMode(ピン番号 , INPUT_PULLUP) Arduino内部のプルアップ抵抗を有効にします
 ピンの値読み取り digitalRead(ピン番号) 結果はHIGHまたはLOWになります。

-- DigitalPullup --

void setup() {
  //configure pin 10 as an input and enable the internal pull-up resistor
  pinMode(10, INPUT_PULLUP); // ★ 2番ピンのプルアップ抵抗を有効にして入力モードにする
  pinMode(13, OUTPUT);

}

void loop() {
  //read the pushbutton value into a variable
  int pushbutton = digitalRead(2); // ★ 2番ピンの値を読み取る

  // Keep in mind the pull-up means the pushbutton's logic is inverted. It goes
  // HIGH when it's open, and LOW when it's pressed. Turn on pin 13 when the
  // button's pressed, and off when it's not:
  if (pushbutton == HIGH) {
    digitalWrite(13, LOW);
  } else {
    digitalWrite(13, HIGH);
  }
}

アナログ入力

Arduinoのアナログ入力ピン(A0~A5)を使用して、入力電圧を0~1023の値で読み取ることができます。
通常はセンサー等のデータを読み取るのに使用します。

アナログ入力のスケッチ例はArduinoIDEの[スケッチ例]-[03.Analog]-[AnalogInpout] にあります。
 Arduinoのアナログピンは入力用なのでピンモードの宣言は不要です。
 ピンの値読み取り AnalogRead(ピン番号) 結果は0~1023の数値になります。

スケッチ例の回路
 コードにはsensorPin となっているので何らかのセンサーを想定しているようですが、ここでは可変抵抗をつないでみます。
 抵抗値に応じてLEDの点滅間隔が変わります。


ArduinoIDEの[スケッチ例]-[03.Analog]-[AnalogInput]を 変更なしで そのまま使用します。

アナログアナログ入力を利用したボタン読み取り

ATTinyなどピン数の少ないマイコンを使用する場合に、アナログ入力でボタンを読み取れ一つのピンに複数のボタンをつなげる事ができます。
S1を押した場合、S2を押した場合、S1とS2を同時に押した場合で入力値が変わるので、ボタンの状態を判別できます。



frozringのライブラリに30Kと20Kの抵抗がなかったので回路図では33Kと22Kになっていますが、実験では30Kと20Kを使っています。
A0の入力値は計算上は▼になる筈です。
  抵抗値 電圧 入力値(理論値) 入力値(実測値) プログラムでの認識範囲 
S1 20KΩ 3.33V 681  681~683  640~720
S2 30KΩ 3.75V 767  768~770  730~810
S1+S2 12KΩ 2.76V 564  557~559  520~600
※実測にはArduinoIDEの[スケッチ例]-[03.Analog]-[AnalogOutSerial]を使用しました。
あまりシビアにすると配線抵抗や温度などの条件の変化で動かなくなってしまうので、幅を持たせてプログラムでの認識範囲を決めます。

-- Analog Switch Input --
※回路では省略しましたが、12番ピンと13番ピンにLEDを接続する事を想定しています。

int sensorPin = A0;    // アナログ入力ピン
int ledS1Pin = 12;     // S1が押された時に光るLED
int ledS2Pin = 13;     // S2が押された時に光るLED
int analogValue = 0;   // アナログピン入力値

void setup() {
  // declare the ledPin as an OUTPUT:
  pinMode(ledS1Pin, OUTPUT);
  pinMode(ledS2Pin, OUTPUT);
}

void loop() {
  // read the value from the sensor:
  analogValue = analogRead(sensorPin);

  int s1 = LOW ;
  int s2 = LOW ;
  if (640 <= analogValue && analogValue <= 720) {
    // S1 ON
    s1 = HIGH ;
  }
  if (730 <= analogValue && analogValue <= 810) {
    // S2 ON
    s2 = HIGH ;
  }
  if (520 <= analogValue && analogValue <= 600) {
    // S1 + S2 ON
    s1 = HIGH ;
    s2 = HIGH ;
  }

  // turn the ledPin
  digitalWrite(ledS1Pin, s1);
  digitalWrite(ledS2Pin, s2);
}

チャタリング対策

スイッチをONにした時の動作は通常は▼のように電圧が変化します。



スイッチの機械部分がバウンドする(接点の金属が跳ねる)事で、何度かに一度は▼のようにススイッチを連続してON/OFFしたような動きをする事があります。
これの現象を チャタリング といいます。
ボタンを押している間LEDが点灯する…くらいでしたらチャタリングが起きても実害はありませんが、ON/OFFで動作が変わったりON/OFFの回数をカウントしているようなプログラムでは誤動作の原因になります。

動作速度がシビアではない場合(時刻合わせやメニュー選択などのユーザーインターフェイスとか)であれば、ソフトウェアで例えば0.2秒毎にしかスイッチの状態をチェックしないなどすれば回避できます。

動作速度がシビアな場合はチャタリング防止回路を組み込んで誤動作を防ぐ必要があります。

 

解説動画