今から始める電子工作 ⑤ ディジタル入力 その1 スイッチ1個の基本
前回までのLチカのスケッチは、ディジタル出力の利用例でした。I/Oポートは、入力にも使えます。
●ディジタル入力用サンプル例のスケッチを読み込む
スケッチ例->02.Digital ->Button
スケッチです。最初の部分のコメントは省きました。
スイッチを押すとボード上のD13のLEDが点灯するという内容です。
const int buttonPin = 2;
は、buttonPinは、整数型の定数(じょうすう)だと宣言(定義)しています。
int buttonState = 0;
は、buttonStateは整数型の変数だと宣言(定義)しています。
変数は、初期値を代入した後変更ができますが、定数は変更ができません。変更する必要がない場合はconstを使って定数にします。
if (buttonState == HIGH)
もし、buttonStateは'1'ならば、という条件文です。HIGH=1、LOW=0はArduinoのどこかで定義されています。'1'と'0'ならばブール型があります。
bool buttonState = false;
のように定義します。falseは'0'、trueが'1'です。C/C++言語も同様に使えます。
buttonState == HIGH を buttonState == true や buttonState == 1 に変更しても同じように動作します。
ちなみに、Pythonでは、True、Falseです。
// constants won't change. They're used here to set pin numbers: const int buttonPin = 2; // the number of the pushbutton pin const int ledPin = 13; // the number of the LED pin // variables will change: int buttonState = 0; // variable for reading the pushbutton status void setup() { // initialize the LED pin as an output: pinMode(ledPin, OUTPUT); // initialize the pushbutton pin as an input: pinMode(buttonPin, INPUT); } void loop() { // read the state of the pushbutton value: buttonState = digitalRead(buttonPin); // check if the pushbutton is pressed. If it is, the buttonState is HIGH: if (buttonState == HIGH) { // turn LED on: digitalWrite(ledPin, HIGH); } else { // turn LED off: digitalWrite(ledPin, LOW); } }
回路図です。
入力端子と直列に100Ωの抵抗が入っています。なくても動作しますし、この10年ほどで、入っていない回路のほうがほとんどになっています。
役割は保護抵抗です。入力と出力を間違って設定してしまったときなど、不測の事態が起こったときに、マイコン内部の回路を保護します。もしかしたら、そうい保護回路がすでにマイコンに入っているかもしれません。
配線しました。
コンパイル&アップロードします。D13のLEDが点灯します。どこにも点灯しろという命令はないのですが。
スイッチを押すと、LEDは消灯します。
●ディジタル・ピン
https://docs.arduino.cc/learn/microcontrollers/digital-pins/
オフィシャルのこのWebページには、
Arduino (Atmega) ピンはデフォルトで入力に設定されているため、入力として使用する場合は pinMode() で明示的に入力として宣言する必要はありません。このように構成されたピンは、ハイ・インピーダンス状態にあると言われます。入力ピンは、サンプリングしている回路に非常に小さな負荷をかけます。これは、ピンの前にある 100MΩの直列抵抗器と同等です。
と書かれているので、setup()内の入力設定をコメントアウトして実行してみました。
先ほどの最初のスケッチと同様に動作しました。
●プルアップとプルダウン
じつは、このマイコンの入力等価回路を検索しても見つからないので想像するだけなのですが、pinMode(buttonPin, INPUT); を実行したとき、スイッチは、マイコン内部のバッファ回路につながっている思われます。バッファがどのような回路かも不明ですが、入力インピーダンスは高いと、上記にも書かれています。バッファはそういう性質があるのですが。
入力端子に、電源から10k~47kΩの抵抗をつなぎます。すると、入力端子はHIGHになります。この状態を、プルアップするといいます。
GNDから入力端子に、10k~47kΩの抵抗をつなぎます。すると、入力端子はLOWになります。この状態を、プルダウンするといいます。
どちらかの状態にして、スイッチをつなぎます。プルアップしている回路では、スイッチを押すとHIGH->LOWになります。プルダウンしている回路では動作は逆になります。
上記の実験回路のように、プルアップもプルダウンもしないで使うと何が起こるのでしょうか。普通は正しく動作しますが、入力インピーダンスが高いと、ノイズを拾いやすいのです。なので、環境によっては、勝手に入力が入ったようになることがあり得ます。なので、HIGHもしくはLOWのどちらかの状態にしておくのが、問題(誤動作)を起こしにくいのです。
inputのコマンドにはもう一つあって、INPUT_PULLUPを指定できます。
●タクト・スイッチ
大きさや押す部分の長さなど、いろいろなタクト・スイッチが市販されています。家電機器などのスイッチに使われますが、ほとんど、このような形状のスイッチを見ることはありません。
家電などの操作パネルはアルミやプラスチックでできていて、押す部分が少し盛り上がっています。この裏にタクト・スイッチが隠れています。
多くの製品は4本足で、長辺同士、短辺同士は内部でつながっています。2本足の製品もあります。長辺と短辺が判別しにくいので、テスタで当たって確認をしてください。
回路図では、次のように書かれていることが多いようです。
スイッチにはチャタリングという悩ましい動作が伴います。人が1回押したのに、複数回マイコン側では押されたという反応をすることがあります。なので、チャタリング防止回路を入れたり、ソフトウェア側でや遺作をする場合もあります。
タクト・スイッチは、オシロスコープで見ると、あまりチャタリングは発生していません。
●変数、定数の命名方法
今回利用したサンプルのプログラムでは、 buttonPin や ledPin という変数、定数名が出てきました。変数などは、何度もスケッチ内に出てくるので、ほかの変数と間違えないようなつづりにする必要があります。
多くの事例では、二つの単語をつなげます。ここでは、二番目のPinの最初の文字を大文字にしています。ほかにも命名方法はあって、
button_pin led_pin
というようなアンダスコアでつなげるのもよく見ます。マイナス記号でもよいのですが、言語によっては別の解釈になることもあって、あまり使われません。
筆者が初めて命名方法という解説を読んだのは、NeXT社のObjective-Cの解説書でした。それまで、C言語の書籍では読んだことがありませんでした。
前回、for文の中で、iという変数名が2か所で使われていました。
for (int i = 0; i < 20; i++)
と
for (int i = 0; i < 20; i++)
です。二つの場所にある i は、別物です。for文内では、ローカル変数の扱いになり、for文を抜けるとほかの場所では使えない(通用しない)変数になります。なので、int iと整数であることを定義して使います。i である必要もなく、j や k が使われることもありますし、countというような長い変数名を使うこともあります。
buttonPin や ledPin はstep()やloop()関数の外で宣言されているので、グローバル変数、定数になり、いろいろな関数内でもそのまま利用できます。