最近よく見かける、上下左右にメニューボタン、中央に決定ボタンがあるような、なんていうのか名前を知らないのですが、ファンクションボタンを作ってみました。
タクトスイッチ 6個を「up」「down」「right」「left」「set」「reset」のファンクションボタンとし、どのボタンが押されたかを検出します。今回の肝は電圧分圧方式でのボタン検出で、押したボタンによって入力電圧が変化するという仕組み。ググると考え方や抵抗値の計算方法が出てきますので参考にしてください。
二つ以上のボタンを同時に押した場合は優先順位がありますので、今回は「reset」を最優先のボタンとして並べてみました。
計算上の分電圧と実際の入力値は異なりますので、Arduino の入力値を実測してボタン判断のしきい値を決めています。
どのボタンが押されたかを表示するために、手元にあった 7 セグメント LED (アノードコモン) をシフトレジスタで表示させています。シフトレジスタは前に LED キューブで使っていた SN74LS164 です。こいつはストレージレジスタがありませんので、ドライブ用にトランジスタ 2N3906 を付けました。これによりデータ送信中は LED を表示させないようにしています。セグメントの電流は 7mA 程度、2N3906 は最大コレクタ電流 200mA ですので十分使えます。
回路図です。
ブレッドボードはこんな感じ。実際はこれを時計方向に 90° 回して実験していますので、右上のタクトスイッチは上下左右に 4 個のボタンと左下に reset 、右下に set という配置になってます。まぁどんな並びでも関係ないんですけど (^_^;) 押したボタンに応じて数字が表示されるという単純なものです。
フローチャートとスケッチです。ボタン判断のしきい値がフローチャートとスケッチで異なっていますが、最終的にはスケッチの値にしています。
// function-switch 2019.06.06 meyon
byte segmentData[7] = {
B1111110, // 0
B0110000, // 1
B1101101, // 2
B1111001, // 3
B0110011, // 4
B1011011, // 5
B1011111 // 6
};int driverPin = 11;
int clockPin = 12;
int dataPin = 13;
int displyNumber = 0;
int buttonPressed() {
int inputVoltage = analogRead(A0);if (inputVoltage > 947) {
return 0; //off
} else if (inputVoltage > 779) {
return 1; //set
} else if (inputVoltage > 602) {
return 3; //up
} else if (inputVoltage > 436) {
return 5; //right
} else if (inputVoltage > 268) {
return 4; //down
} else if (inputVoltage > 90) {
return 6; //left
} else {
return 2; //reset
}
}
void displyButtonNo() {
digitalWrite (driverPin, HIGH);
shiftOut(dataPin, clockPin, MSBFIRST, ~segmentData[displyNumber]);
digitalWrite (driverPin, LOW);
return;
}
void setup() {
pinMode (driverPin, OUTPUT);
pinMode (clockPin, OUTPUT);
pinMode (dataPin, OUTPUT);Serial.begin(9600);
}void loop() {
Serial.println(analogRead(A0));
if (buttonPressed() != 0) {
displyNumber = buttonPressed();
}
displyButtonNo();
}
例によって入力値の確認のためにシリアル出力を使ってます。
シフトレジスタもドライブ用トランジスタも LOW で点灯になります。これ勘違いするとすべてがおかしくなってしまいますので (^_^;)