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

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

新規登録して質問してみよう
ただいま回答率
85.49%
Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

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

Raspberry Pi

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

Q&A

解決済

3回答

5441閲覧

Socket通信をPCとラズパイ間にLANケーブルを接続してやりたい

nyahaha

総合スコア1

Windows 10

Windows 10は、マイクロソフト社がリリースしたOSです。Modern UIを標準画面にした8.1から、10では再びデスクトップ主体に戻され、UIも変更されています。PCやスマホ、タブレットなど様々なデバイスに幅広く対応していることが特徴です。

Python 2.7

Python 2.7は2.xシリーズでは最後のメジャーバージョンです。Python3.1にある機能の多くが含まれています。

Python 3.x

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

Raspberry Pi

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

Python

Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

0グッド

0クリップ

投稿2021/12/09 16:04

前提・実現したいこと

Windows10(以降PC)で DUALSHOCK 4 の入力をpygameを使って読み取り、socket通信にてLANケーブルを介して Raspberry Pi 4 Model B(以降ラズパイ) へ DUALSHOCK 4 のデータを送信、そのデータをもとにGPIOへ出力するというのが今回したいことです。

発生している問題

socket通信のUDPにてつい数日前まで通信できていたのですが、これまで作業していた部屋とは違う場所へ行ったところ、ラズパイ側で受信が出来ずに「recv()」関数でプログラムが止まってしまいます。
「recv()」関数でプログラムが止まっていたことはどうやって確認したかと言うと、「print("1")」を「recv()」の直前に書いた場合には表示出来ており、「recv()」の直後に書いた場合では表示されなかったため、「recv()」関数でプログラムが止まっていたと判断しました。
これまでの作業部屋には無線ルーターがあり、無線ネットワークがギリギリ届かない程度離れたら「recv()」関数でプログラムが止まってしまったので、LANケーブルではなく無線ルーターを介してこれまでsocket通信をしていたのではないかと現状では疑っております。
ラズパイ側が受信できない状態でプログラムが止まっているだけなので、エラーメッセージ等はありません。

PC側(socket通信的にクライアント)のソースコード

python3

1import pygame 2from pygame.locals import * 3import socket 4import time 5 6host = "192.168.10.21" 7port = 55555 8sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) 9 10def Constrain( val, min_val, max_val ): 11 if val > max_val: 12 return max_val 13 elif val < min_val: 14 return min_val 15 else: 16 return val 17 18def Map( val, in_min, in_max, out_min, out_max ): 19 temp = ( val - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min 20 return ( Constrain( temp, out_min, out_max ) ) 21 22def main(): 23 # [LX, LY, RX, RY, L2, R2] 24 stick = [ 0, 0, 0, 0, 0, 0 ] # スティックは(-255 ~ 255), L2とR2は(0 ~ 255) 25 button = 0 # 2進数化してボタン情報を1つの変数にまとめる 26 27 pygame.joystick.init() 28 29 try: 30 j = pygame.joystick.Joystick( 0 ) 31 j.init() 32 print( "ジョイスティックの名前:", j.get_name(), end=" " ) 33 print( "ボタンの数:", j.get_numbuttons(), end=" " ) 34 print( "スティックの数:", j.get_numaxes() ) 35 except pygame.error: 36 print( "ジョイスティックが接続されていません" ) 37 38 pygame.init() 39 40 while True: 41 for e in pygame.event.get(): 42 if e.type == QUIT: 43 return 44 if( e.type == KEYDOWN and 45 e.key == K_ESCAPE ): 46 return 47 48 stick[0] = int( Map( j.get_axis(0), -1.0, 1.0, 0, 127 ) ) 49 stick[1] = int( Map( j.get_axis(1), 1.0, -1.0, 0, 127 ) ) 50 stick[2] = int( Map( j.get_axis(2), -1.0, 1.0, 0, 127 ) ) 51 52 button = 0 53 button |= j.get_button(0) 54 for i in range(1, 4): 55 button <<= 1 56 button |= j.get_button(i) 57 for i in range(9, 15): 58 button <<= 1 59 button |= j.get_button(i) 60 61 print( button, end=" " ) 62 print( stick[0], end=" " ) 63 print( stick[1], end=" " ) 64 print( stick[2], end=" " ) 65 66 message = "%d,%d,%d,%d" % ( button, stick[0], stick[1], stick[2] ) 67 sock.sendto( message.encode( 'utf-8' ), ( host, port ) ) 68 69 time.sleep(0.05) 70 71if __name__ == '__main__': 72 main() 73

ラズパイ側(socket通信的にサーバー)のソースコード

python3

1# -*- coding: utf-8 -*- 2 3import socket 4import time 5 6host = "192.168.10.21" 7port = 55555 8sock = socket.socket( socket.AF_INET, socket.SOCK_DGRAM ) 9sock.bind( ( host, port ) ) 10 11import pigpio 12FREQ = 10000 13dout_pin = [ 24, 25, 8, 7, 13, 5, 6, 11, 9, 10 ] 14dire_pin = [ 4, 17, 14, 15 ] 15pwm_pin = [ 27, 22, 2, 3 ] 16pi = pigpio.pi() 17 18for i in range(0, 10): 19 pi.set_mode( dout_pin[i], pigpio.OUTPUT ) 20 21for i in range(0, 4): 22 pi.set_mode( dire_pin[i], pigpio.OUTPUT ) 23 pi.set_mode( pwm_pin[i], pigpio.OUTPUT ) 24 pi.set_PWM_frequency( pwm_pin[i], FREQ ) 25 26class Static: 27 data = False 28 return_val = False 29 30def Constrain( val, min_val, max_val ): 31 if val > max_val: 32 return max_val 33 elif val < min_val: 34 return min_val 35 else: 36 return val 37 38def Map( val, in_min, in_max, out_min, out_max ): 39 temp = ( val - in_min ) * ( out_max - out_min ) / ( in_max - in_min ) + out_min 40 return ( Constrain( temp, out_min, out_max ) ) 41 42def PushButton(button): 43 if( button == 0 and Static.data == False ): 44 Static.data = False 45 Static.return_val = False 46 elif( button != 0 and Static.data == False ): 47 Static.data = True 48 Static.return_val = True 49 elif( button != 0 and Static.data == True ): 50 Static.data = True 51 Static.return_val = False 52 elif( button == 0 or Static.data == True ): 53 Static.data = False 54 Static.return_val = False 55 return Static.return_val 56 57while True: 58 try: 59 rcv = sock.recv( 31 )          # ここでプログラムが止まる! 60 rcvmsg = rcv.decode( 'utf-8' ) 61 ps4_data = rcvmsg.split( "," ) 62 63 # ボタンのデータに再変換 64 cross = ( int(ps4_data[0]) >> 9 ) & 1 65 circle = ( int(ps4_data[0]) >> 8 ) & 1 66 square = ( int(ps4_data[0]) >> 7 ) & 1 67 triangle = ( int(ps4_data[0]) >> 6 ) & 1 68 L1 = ( int(ps4_data[0]) >> 5 ) & 1 69 R1 = ( int(ps4_data[0]) >> 4 ) & 1 70 up = ( int(ps4_data[0]) >> 3 ) & 1 71 down = ( int(ps4_data[0]) >> 2 ) & 1 72 left = ( int(ps4_data[0]) >> 1 ) & 1 73 right = int(ps4_data[0]) & 1 74 75 delta_dire = False 76 if ( up > 0 or right > 0 ): 77 delta_dire = True 78 else: 79 delta_dire = False 80 81 _right = False 82 _left = False 83 if ( right > 0 ): 84 _right = True 85 if ( left > 0 ): 86 _left = True 87 88 _up = False 89 _down = False 90 if ( up > 0 ): 91 _up = True 92 if ( down > 0 ): 93 _down = True 94 95 pi.write( dout_pin[0], triangle ) 96 pi.write( dout_pin[1], cross ) 97 pi.write( dout_pin[2], R1 ) 98 pi.write( dout_pin[3], _up ) 99 pi.write( dout_pin[4], _down ) 100 pi.write( dout_pin[5], circle ) 101 pi.write( dout_pin[6], square ) 102 pi.write( dout_pin[7], _right ) 103 pi.write( dout_pin[8], _left ) 104 pi.write( dout_pin[9], delta_dire ) 105 106 jacobian = [ [ 1, -1, 1 ], [ 1, 1, 1 ], [ -1, 1, 1 ], [ -1, -1, 1 ] ] 107 robot_vel = [ 0, 0, 0 ] 108 for i in range( 0, 3 ): 109 robot_vel[i] = int( Map( int(ps4_data[i+1]), 0, 127, -255, 255 ) ) 110 111 dead_zone = 0.15 112 for i in range( 0, 3 ): 113 if abs( robot_vel[i] ) < 255 * dead_zone: 114 robot_vel[i] = 0 115 116 wheel_vel = [ 0, 0, 0, 0 ] 117 for i in range( 0, 4 ): 118 wheel_vel[i] += jacobian[i][0] * robot_vel[0] 119 wheel_vel[i] += jacobian[i][1] * robot_vel[1] 120 wheel_vel[i] += jacobian[i][2] * robot_vel[2] 121 122 max_vel = 0 123 for i in range( 0, 4 ): 124 if ( abs( wheel_vel[i] ) > max_vel ): 125 max_vel = abs( wheel_vel[i] ) 126 127 if max_vel > 255: 128 for i in range( 0, 4 ): 129 wheel_vel[i] *= 255 / max_vel 130 Constrain( wheel_vel[i], -255, 255 ) 131 132 dead_zone = 0.05 133 for i in range( 0, 4 ): 134 if abs( wheel_vel[i] ) < 255 * dead_zone: 135 wheel_vel[i] = 0 136 137 for i in range( 0, 4 ): 138 if wheel_vel[i] > 255 * 0.01: 139 pi.write( dire_pin[i], 0 ) 140 pi.set_PWM_dutycycle( pwm_pin[i], abs( wheel_vel[i] * 0.5 ) ) 141 elif wheel_vel[i] < -255 * 0.01: 142 pi.write( dire_pin[i], 1 ) 143 pi.set_PWM_dutycycle( pwm_pin[i], abs( wheel_vel[i] * 0.5 ) ) 144 else: 145 pi.write( dire_pin[i], 0 ) 146 pi.set_PWM_dutycycle( pwm_pin[i], 0 ) 147 148 print( left, end=" " ) 149 print( down, end=" " ) 150 print( up, end=" " ) 151 print( right, end=" " ) 152 print( L1, end=" " ) 153 print( R1, end=" " ) 154 print( square, end=" " ) 155 print( cross, end=" " ) 156 print( triangle, end=" " ) 157 print( circle, end=" " ) 158 print() 159 160 time.sleep(0.01) # Delay 1 ms 161 162 163 except KeyboardInterrupt: 164 sock.close() 165 for i in range(0, 14): 166 pi.set_mode( dout_pin[i], pigpio.INPUT ) 167 for i in range(0, 4): 168 pi.set_mode( pwm_pin[i], pigpio.INPUT ) 169 pi.stop() 170 break 171

「sock.recv( 31 )」でプログラムが止まっていると目星はつけていますが、そこ以外にもsocket通信に悪影響が出ている箇所がある可能性も否定できないので、長いかもしれませんが使用しているソースコードを全て提示させていただきました。

試したこと

ラズパイの「Wireless & Wired NetWork Setting」とPCの「インターネット プロトコル バージョン 4(TCP/IPv4)のプロパティ」にて、イーサネットのIPアドレス(192.168.10.21)を固定しましたが、上手くいきませんでした。偶発的な問題ではないことを確認するため、数回作業場所と作業場所外を往復し、両ソースコードを実行してみましたが、再現性高く作業場所ではsocket通信でき、作業場所外では全くsocket通信できませんでした。作業場所のルーターを介して出来ていたのだと考えると、他の無線ネットワークを介してやれば(根本的な解決にはならないが)通信できるのでは? と思って、私物のポケットWi-FiをPCへ接続し、コマンドプロンプトの「ipconfig」でIPアドレスを取得し、ラズパイの「Wireless & Wired NetWork Setting」とPCの「インターネット プロトコル バージョン 4(TCP/IPv4)のプロパティ」にてIPアドレス固定したのち、両ソースコードを実行しましたが、変わらず「recv()」関数でプログラムが止まってしまいます。

補足情報

LANケーブルはもちろんクロスではなくストレートを使用しています。
普段の作業場所にて通信をし、正常にsocket通信できる際は、ラズパイ側で「ifconfig」をするとIPアドレスは「192.168.10.21」、PC側で「ipconfig」をすると「169.254.36.224」と表示されます。

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

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

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

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

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

guest

回答3

0

LANケーブルはもちろんクロスではなくストレートを使用しています。

普段の作業場所にて通信をし、正常にsocket通信できる際は、ラズパイ側で「ifconfig」をするとIPアドレスは「192.168.10.21」、PC側で「ipconfig」をすると「169.254.36.224」と表示されます。

有線でつながっていませんね。

無線接続は、設定を含めて両方とも切りましょう。問題の切り分けができなくなります。

有線での接続は、ラズパイとPCをどのように接続していますか?
可能であれば、ハブには、PCとラズパイだけ接続するようにしましょう。

ラズパイのIP(192.168.10.21)は、有線のものですか?
そうでない場合、有線接続を設定しましょう。
ラズパイの有線の固定IPを設定する方法は検索すればみつかります。

PCのIPは設定できていません。 169.254.xxx.xxx は、DHCPで取得できなかったときに、機器間で調整して自動で付与されるものです。
WindowsでIPアドレスを固定で設定する方法は検索すればみつかります。

ラズパイとPCで相互にpingで疎通が取れるようになったか確認しましょう。

これでできるんじゃないでしょうか。

手順などは検索することになると思いますが、ラズパイにしても、PCにしてもバージョンによって手順が異なるので、そのあたりも確認しながら情報を収拾するといいでしょう。

投稿2021/12/10 01:56

TakaiY

総合スコア12743

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

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

0

コードの不具合、というよりも、ネットワークの不具合、というかんじがします
PC側からラズパイに、それぞれの場合にping飛ばしてみたらどうなるでしょうか

投稿2021/12/09 21:59

y_waiwai

総合スコア87747

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

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

0

自己解決

自己解決いたしました。
IPアドレスを両ソースコードとも「192.168.10.21」としていますが、大元の原因としてはPCとラズパイの固定IPアドレスをどちらも「192.168.10.21」としていたことでした。ソースコードのIPアドレスは同じIPアドレスの同じポートへ送受信する必要があるため同一のものを指定しますが、送信側のPCが「192.168.10.21」というIPアドレスを先に使用してしまうと、ラズパイが「192.168.10.21」というIPアドレスを使用することができずに「169.254.〜」のアドレスが割り当てられるためデータを受信できていませんでした。普段の作業場所でsocket通信が出来ていたのは恐らくラズパイ側が先に「192.168.10.21」というIPアドレスを使用していたためだと考えています。場所や、PCとラズパイの起動順など何かしらの理由で「192.168.10.21」というIPアドレスをどちらが先に使用するかが変わったのだと思いますが、どちらにせよ正しいやり方ではありませんでした。socket通信をする際は「192.168.10.〜」までが同一であれば良いので、データを受け取るラズパイ側を「192.168.10.21」のままで、PC側を適当に「192.168.10.22」と固定IPアドレスを変更することで解決いたしました。
回答していただいた方々ありがとうございました。また、回答への反応が遅れてしまい申し訳なかったです。また質問することがありましたらその時はよろしくお願いいたしますm(_ _)m

投稿2021/12/13 00:20

編集2021/12/13 01:41
nyahaha

総合スコア1

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.49%

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

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

質問する

関連した質問