質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

Q&A

解決済

2回答

1260閲覧

ESP32でボタンの同時押しが検知できない件

morleyrobertson

総合スコア12

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

C++

C++はC言語をもとにしてつくられた最もよく使われるマルチパラダイムプログラミング言語の1つです。オブジェクト指向、ジェネリック、命令型など広く対応しており、多目的に使用されています。

Arduino

Arduinoは、AVRマイコン、単純なI/O(入出力)ポートを備えた基板、C言語を元としたArduinoのプログラム言語と、それを実装した統合開発環境から構成されたシステムです。

0グッド

2クリップ

投稿2018/10/15 07:08

編集2018/10/18 11:12

前提・実現したいこと

ESP32-DevKitCと74HC138(デコーダ、デマルチプレクサ)と8個のボタンを使い、
次のような回路を組みました。
イメージ説明

発生している問題・エラーメッセージ

Arduinoで同様の回路を組んだ時は、正常にボタンの同時押しが検知できたと思うのですが、
ESP32ではうまく検知できていません。
8本の信号線がバッティングしないようダイオードを噛ませております。
任意のボタンAを押したままにしておいて、別のボタンBを押すと、
ボタンAを押しているにも関わらず離された時の処理が走ってしまい、Bの押下も検知されません。

該当のソースコード

C++

1//Mux control pins 2int s0 = 12; 3int s1 = 13; 4int s2 = 14; 5int controlPin[] = {s0, s1, s2}; 6 7int muxChannel[8][3] = { 8 {0, 0, 0}, //channel 0 9 {1, 0, 0}, //channel 1 10 {0, 1, 0}, //channel 2 11 {1, 1, 0}, //channel 3 12 {0, 0, 1}, //channel 4 13 {1, 0, 1}, //channel 5 14 {0, 1, 1}, //channel 6 15 {1, 1, 1}, //channel 7 16}; 17 18int loop_0_7 = 0; 19 20void setup() { 21 22 pinMode(s0, OUTPUT); 23 pinMode(s1, OUTPUT); 24 pinMode(s2, OUTPUT); 25 26 digitalWrite(s0, LOW); 27 digitalWrite(s1, LOW); 28 digitalWrite(s2, LOW); 29 30 pinMode(27, INPUT_PULLUP); 31 32 Serial.begin(115200); 33 34} 35 36void loop() { 37 //74HC138の0ピン~7ピンに順次Lowを出力していきます。 38 for (int i = 0; i < 3; i ++) { 39 if(muxChannel[loop_0_7][i]) { 40 if(i==0) GPIO.out_w1ts = ((uint32_t)1 << 12); 41 else if(i==1) GPIO.out_w1ts = ((uint32_t)1 << 13); 42 else if(i==2) GPIO.out_w1ts = ((uint32_t)1 << 14); 43 }else{ 44 if(i==0) GPIO.out_w1tc = ((uint32_t)1 << 12); 45 else if(i==1) GPIO.out_w1tc = ((uint32_t)1 << 13); 46 else if(i==2) GPIO.out_w1tc = ((uint32_t)1 << 14); 47 } 48 } 49 //ボタンが押されたかどうかをESP32の27ピンで検知しています。 50 //内部抵抗でプルアップしているため、ボタンが押されていないときはHIGH(1)、 51 //押されたときはLOW(0)となります。 52 byte res1 = (GPIO.in >> 27) & 0x1; 53 //ボタンが押された時は、その時のloop_0_7の値を読み取ります。 54 //これがボタン番号となります。 55 if(!res1){Serial.println(loop_0_7);delay(100);} 56 //↑ボタンが押されたときは、res1が0となり、その時のloop_0_7の値を画面出力します。 57 //押されている間は100msごとに出力し続けます。 58 //離される(res1が1に戻る)と画面への出力がストップします。 59 60 if(loop_0_7==7) loop_0_7=0; 61 else loop_0_7++; 62 63}

この原因がお分かりになる方いらっしゃいますでしょうか。

【2018年10月17日追記】
2つのボタンを同時に押したときの不具合は、キーの組み合わせによって異なることが分かりました。
以下、キーの組み合わせと不具合の対応を記載します。
回路図中の8個のボタンを左から0番、1番、2番、3番、4番、5番、6番、7番ボタンとしますと、
■ 0番ボタンを押しながら
1番~7番ボタンを押しても、画面に0を出力し続ける(他のボタンの入力を受け付けない)。
■ 1番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(1番ボタンは離されたと判断されてしまう)。
2番~7番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
■ 2番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(2番ボタンは離されたと判断されてしまう)。
1番、3番、5番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
4番、6番、7番ボタンを押しても、画面に2を出力し続ける(他のボタンの入力を受け付けない)。
■ 3番ボタンを押しながら
0番~7番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
■ 4番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(4番ボタンは離されたと判断されてしまう)。
1番、3番、5番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
2番ボタンを押すと、画面に2を出力し続ける(4番ボタンは離されたと判断されてしまう)。
6番ボタン、7番ボタンを押しても、画面に4を出力し続ける(他のボタンの入力を受け付けない)。
■ 5番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(5番ボタンは離されたと判断されてしまう)。
1番~7番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
■ 6番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(6番ボタンは離されたと判断されてしまう)。
1番~7番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。
■ 7番ボタンを押しながら
0番ボタンを押すと、画面に0を出力し続ける(7番ボタンは離されたと判断されてしまう)。
1番~6番ボタンを押すと、画面に何も出力されなくなる(すべてのボタンが押されてないと判断されてしまう)。

といった具合です。

ちなみに、下の画像のように、もう1列足して、左から8番~15番ボタンとし、
上の列のボタン1個を押しながら、下の列のボタン1個を押すと期待した通りの出力をしてくれます。
例えば、上の列の0番ボタンと下の列の8番ボタンを同時に押すと、
0
8
0
8
0
8
と交互に出力してくれます。
イメージ説明
本当は同じ列の2個のボタンでも同じように交互に出力して欲しかったのですが、
上記のとおり、予期しない出力をしてしまっています。

【2018年10月18日追記】

同時押しが出来ない問題の前に、
もともとボタンの入力とボタン番号の画面出力が異なる謎の現象が起きていました。
0番ボタンを押すと「4」を画面に出力、4番ボタンを押すと「0」を画面に出力。
この現象がどうにも解消されないため、苦肉の策で配線を入れ替えることにしました。
0番ボタンと74HC138のY4ピンを、4番ボタンを74HC138のY0ピンに接続。
最初の回路図の配線がごちゃごちゃとしているのはそのためです。
このようにすると、左のボタンから0 1 2 3 4 5 6 7と期待通りの値を出力してくれるため、
謎は残るものの、まぁ良いかと思って、同時押しができない問題に取り掛かりました。
そして、以前同じようにArduinoと74HC138とボタンとダイオードを使って同様の回路を組んだときは
期待通りの動きをしてくれていたため、昨夜もう一度それらを組んで、当時のコードを実行しました。
そこで思い出したのは、ボタンの入力とボタン番号の画面出力が異なる現象はArduinoでも
発生していたこと。この現象はプリスケーラの設定を変えることで正常にできたこと。
あと、同時押しを可能にするダイオードの繋ぎ方でした(下図)。
左はダメ。右はおk。
同時押しを可能にするダイオードの繋ぎ方
そして、ESP32に戻って、ダイオードを正確に繋いで試してみようとしたところ、
1つのボタンの入力さえブレブレになってしまいました。
0番ボタンを押すと、0、5、6を出力。
1番ボタンを押すと、1、2を出力。
2番ボタンを押すと、2、3、4を出力。
3番ボタンを押すと、3、4を出力。
4番ボタンを押すと、1、2、4を出力。
5番ボタンを押すと、5、6を出力。
6番ボタンを押すと、0、6、7を出力。
7番ボタンを押すと、0、7を出力。
ちょっと僕の手に負える感じじゃないなと感じています。
別のICを使うなど、ほかの方法を考え始めています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tmp

2018/10/15 08:56

ソースに押されたと判断する部分と、離されたと判断する部分の記載おねがいします。
tmp

2018/10/16 08:51

現象として、押されてるキーが1つならどのキーも押された状態になるが2つ以上のキーを押すとどのキーも押されていない状態になるという認識でよろしいでしょうか?ハード的な信号の確認はできるのでしょうか?(例えば入力信号の確認など)
morleyrobertson

2018/10/17 05:06

tmpさん、質問頂きましてありがとうございます。入力信号の確認につきましては、オシロスコープやロジックアナライザなどを所持していないため、Arduino IDEのシリアルプロッタで確認するぐらいのことしかできていません。また2つ以上のキーが押された時の現象は、キーの組み合わせによって変化しますので、後ほど投稿内容に詳細情報を追記いたします。お手数おかけ致しますが、そちらをご覧いただければと存じます。
tmp

2018/10/18 03:56 編集

すいません、最初こちらに書いてしまいましたが、回答の方に書きました。
guest

回答2

0

ベストアンサー

2列の写真ですが、見るとダイオードが意味のない状態になってるように見えますが、大丈夫でしょうか?

追記10/18 19:00
ダイオードがブレッドボードの同じ番号のAとDに刺さってるように見えて、このブレッドボードはAとDは、つながってるのではないでしょうか?
その場合は、ダイオードが付いていない状態と同じになると思います。
そして、2列の写真で判断しましたが、1列の時も同じように接続していないでしょうか?
そうすると症状として1つのボタン押しの時は、正常で2つ以上の場合は、出力がぶつかり出力不定になるのではと思います。

追記10/19
回路図で入れ替えててるのは、気が付いてましたが、何かの使いまわしでそうなってるものだと思っていました。
ボタン0と4が入れ替わるのは、74HC138の出力がESP32の出力から読み取りまですぐの為に間に合わないからと思われます。ESP32の3つの出力を順に出力していきますが、最終の14PIN出力直後に即読むため、その14PINの出力後74HC138の出力変化前の状態の結果を読み取ってしまうからと思われます。
14PINが変化するのは、ボタン7から0 , 3から4 で 14PInが前の状態だとすると 0のとき4の状態に、4の時は、0の状態になり、症状にあいます。
GPIOの出力後、GPIOの入力までにほんの少し待ちをいれるか、もう少し速い138に変えれば、正常に読み取れたと思います。
プリスケーラと書いていますが、なんのプリスケーラを変えたのかわかりませんが、おそらく処理を遅くしたことで74HC138が間に合うようになったのでしょう。

投稿2018/10/18 03:54

編集2018/10/19 03:39
tmp

総合スコア277

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

morleyrobertson

2018/10/18 08:54

ダイオードの質問、ありがとうございます。 昨夜、新たな現象が出てきてしまい、ダイオードどころの話ではなくなってしまいました。 長文になりそうですので、今から追記いたします。 お手数ですが、そちらをご覧下さい。
morleyrobertson

2018/10/18 10:31

■追記への返答 そうなんですよ。ダイオードの繋ぎ方を昨夜思い出しました。その辺りも追記いたします。 ありがとうございます。
morleyrobertson

2018/10/21 12:06

tmpさん、アドバイスの通り今試してみたところ、全ての問題が解決いたしました!本当に、本当にありがとうございます!たった1マイクロ秒のdelayを入れるだけで、あらゆる不具合が解消しました。 このページをご覧になった皆様へ  同じESP32でも、スイッチサイエンス社製のESPr Deveroper32では同じ回路、同じコードを実行しても、やはり不具合は出たままとなっています。74HC138に限らずロジックICを使う場合は、ESPr Deveroper32は不向きだと感じています。ご参考までに。
guest

0

画像を拡大しても、マルチプレクサの型番が確認できませんでしたが、ふつう、このテのICにはプルアップ/プルダウン抵抗が必要です。

また、どうも回路的におかしいようですが、もうちょっと鮮明な拡大された回路図を提示してください


ああ、HC138なんですね。
それだと、マルチプレクサのアドレス選択のコード出力が間違ってます。

GPIO.out_w1ts = (GPIO.out_w1ts & ~(0x7<<12))|((loop0_7&0x7) << 12);

だけでいいでしょ

投稿2018/10/15 09:09

編集2018/10/15 09:31
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

morleyrobertson

2018/10/15 10:33

y_waiwaiさん ご回答ありがとうございます。 コードの中の for (int i = 0; i < 3; i ++) { if(muxChannel[loop_0_7][i]) { if(i==0) GPIO.out_w1ts = ((uint32_t)1 << 12); else if(i==1) GPIO.out_w1ts = ((uint32_t)1 << 13); else if(i==2) GPIO.out_w1ts = ((uint32_t)1 << 14); }else{ if(i==0) GPIO.out_w1tc = ((uint32_t)1 << 12); else if(i==1) GPIO.out_w1tc = ((uint32_t)1 << 13); else if(i==2) GPIO.out_w1tc = ((uint32_t)1 << 14); } } の箇所が GPIO.out_w1ts = (GPIO.out_w1ts & ~(0x7<<12))|((loop0_7&0x7) << 12); に置き換え可能ということでしょうか。
y_waiwai

2018/10/15 10:34

そゆことだけど、きちんと理解して使いましょうねっ
morleyrobertson

2018/10/15 11:04

y_waiwaiさん 返信ありがとうございます。 111を12ビット左にシフトする。 loop_0_7と111のビットを比較する。 共に「1」の場合だけ「1」にして、12ビット左にシフトする。 と理解しました。 今、実機で試したのですが、動作が前より意図しない感じになってしまいましたので、考えてみます。 ありがとうございました。
tmp

2018/10/16 09:01

GPIO.out_w1tsは、現在の出力ポートの状態ではありません、ライトオンリーでセットしたいところの対応ビットを1にするものです。リードするとどのような値が読み取れるか特に書いていませんし、また、セットしかできませんのでGPIO.out_w1tcのクリアする方も必要です。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問