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

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

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

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

Q&A

解決済

1回答

4056閲覧

ラズパイ MCP23017 I2C通信について

_magurochan

総合スコア13

Raspbian

Raspbianは、DebianベースのRaspberry Pi用ディストリビューション。ハードウェア浮動小数点演算を有効にすることが可能で、Webブラウズなどの速度を向上できます。

Python 3.x

Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

Raspberry Pi

Raspberry Piは、ラズベリーパイ財団が開発した、名刺サイズのLinuxコンピュータです。 学校で基本的なコンピュータ科学の教育を促進することを意図しています。

0グッド

0クリップ

投稿2020/01/12 15:55

編集2020/01/13 06:50

#実現したこと
I2Cで接続している、IOエキスパンダー MCP23017を使って、タクトスイッチが押されているか取得する。

押していたら1、そうでなければ0を出力

pigpioを使用。

とりあえず、GPA0-7まで入力として使い、プルアップもしておく。

#試したこと・困っていること

下のを実行しました。数値が押していたら0xfe(254)、そうでなければ0xff(255)が出力されてしまいました。

Python3

1import pigpio 2 3ICADDR = 0x20 4 5REG_IODIRA = 0x00 #IO setting for A 6REG_GPPUA = 0x0c #PullUp for A 7REG_GPIOA = 0x12 #IN A 8REG_OLATA = 0x14 #OUT A 9 10pi = pigpio.pi() 11hndl = pi.i2c_open(1, ICADDR) 12 13#IO setting 14#i2c_write_byte_data(handle、reg、byte_val) 15pi.i2c_write_byte_data(hndl,REG_IODIRA,0xff) #Aの全部、入力にする 16 17#pullup 18#i2c_write_byte_data(handle、reg、byte_val) 19pi.i2c_write_byte_data(hndl,REG_GPPUA,0xff) #とりあえずAの全てプルアップします。 20 21while True: 22 print (pi.i2c_read_i2c_block_data(hndl,REG_GPIOA,0x01))

#追記1

data = pi.i2c_read_i2c_block_data(hndl,REG_GPIOA,0x1) print(hex(~data&0xff))

にしたところ

Traceback (most recent call last): File "python-osc.py", line 35, in <module> print(hex(~data&0xff)) TypeError: bad operand type for unary ~: 'tuple'

このようなエラーになりました。

dataの出力される情報が良くないと思い、dataを変えました

Python3

1data = pi.i2c_read_byte_data(hndl,REG_GPIOA) 2print(hex(~data&0xff))

すると

Python

10x0 #何も押していない 20x1 #ボタン1を押している時 30x2 #ボタン2を押している時 40x3 #ボタン1とボタン2を同時に押している時

と出力されました。
たぶん、入力するポートを**pi.i2c_read_byte_data()**では指定できないからだと思います。

他に、

Python

1data = pi.i2c_read_byte_data(hndl,0x01)#ポート1だけ読み込むの意味 2print(hex(~data&0xff))

では、エラーが出なかったけど、数値が変更されずでした。

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

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

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

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

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

退会済みユーザー

退会済みユーザー

2020/01/12 21:48

もし装置がちゃんと動いていて、通信もちゃんとできていて、とりあえずしのげればよい、というのであれば、プログラム側で255-int(帰ってきた値)をすれば「押していたら1、そうでなけれ0」になりそうですがいかがでしょうか?
guest

回答1

0

ベストアンサー

プルアップしているのなら、スイッチはピンとGNDの間に入れるのも普通にやることで、そうだとすればスイッチを押したときがL、離すと(スイッチのつながっていない端子も)Hというのは全く正常です。「出力されてしまった」というものではないでしょう。

エキスパンダーを使うということはそれ以外の端子も制御されるはずで、その時にどういう結果を期待しているのかによっても適切な手段は変わりますが、とりあえずビット反転してから8bitだけ取り出し

Python

1data = pi.i2c_read_i2c_block_data(hndl,REG_GPIOA,0x01) 2print(hex(~data&0xff))

とでもしてみたらどうでしょう。


修正。
pi.i2c_read_i2c_block_data()の返り値はタプルで、最初の要素が得られたデータの数、次がbyte配列でデータそのもの、とのことです。hnd1のI2Cバスのデバイスの、REG_GPIOAレジスタから1バイトを読みだした値を使って計算をしたいのですから、
print(hex(~(data[1][0])&0xff))
ということになるかと思います。

投稿2020/01/12 23:30

編集2020/01/13 08:14
thkana

総合スコア7639

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

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

thkana

2020/01/13 01:38

表示フォントによっては見にくいみたいだから一応言っておくと、 ~dataの~はマイナスじゃないです。チルダ(波線)ですので、よく見るとうねうねしてると思います。
_magurochan

2020/01/13 06:51

追記しました コピペして実行しましたが、エラーになったりします。。。
thkana

2020/01/13 07:43

> 押していたら0xfe(254)、そうでなければ0xff(255)が出力 とあったのでそれだけ見て回答してしまったのは私のミスですけれど、プログラムを組むには使用する関数等の使い方はきちんと調べて、エラーが出たならエラーメッセージをきちんと検討して、「あちこちをとりあえず変えてみる」ではなく根拠のある対応をしましょう。 pi.i2c_read_i2c_block_data()の返り値はタプルで、最初の要素が得られたデータの数、次がbyte配列でデータそのもの、とのことです。hnd1のI2Cバスのデバイスの、REG_GPIOAレジスタから1バイトを読みだした値を使って計算をしたいのですから、 print(hex(~(data[1][0])&0xff)) というのが求める式のようです。エラーメッセージからi2c_read_i2c_block_data()はタプルを返してるのかな? というのを読み取って、その関数の仕様を確認する、と追っていけば状況が把握できるでしょう。 あるいは、直接Aポートの値を返すpi.i2c_read_byte_data(hndl,REG_GPIOA)を使えば返り値をそのまま受け取れる、ということですね。
_magurochan

2020/01/13 13:50

ありがとうございます。 複数のボタンを押すと、足されてしまうのは治らなかったです。
thkana

2020/01/13 14:15

> 治らなかった え? それが問題だとは質問のどこにも書いてないですよ。 ポートは8ビット分を一括で読み出しますから、当然複数のスイッチが押されていればその複数全てについて反応が得られます。 では、どうなればいいのですか? (もはや別の話題なので質問を新たに立てた方がいいかも知れませんが)
_magurochan

2020/01/13 18:16

仕様上、 1と2のボタン同時押しで0x03でなく、0x01と0x02で分けて表示させるというのは結構厳しいでしょうか? それか、 ボタンのピンを飛ばし飛ばしにして、ボタン1→0x01・ボタン2→0x03・ボタン3→0x05とすれば、 ボタン1→0x01 ボタン1・2の同時押し→0x04 ボタン2→0x03 ボタン2・3の同時押し→0x08 ボタン3→0x05 と区別は出来そうな気がしますが。。。
_magurochan

2020/01/14 12:11

この件、解決できました。
_magurochan

2020/01/14 12:39

ボタン1のみ押した時 0x1 ボタン2 0x2 ボタン3 0x4 ボタン4 0x8 ボタン5 0x10 と出力されました。 また、同時押しの場合も、それぞれ違う数値が出力されていました。
thkana

2020/01/14 12:48

時間がなくて返信出来ませんでしたが解決したようでなにより。 ボタンを押したときの値を2進数で表記してみると理屈がわかりやすいかもしれません。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問