我在python中编写了一个套接字。基本上有2个覆盆子pi彼此交谈并使用套接字通过wifi发送gpio数据。代码有时完美无缺,但有时它或者不起作用或显示很多延迟。什么可能的问题。我错过了什么。我是网络和python的新手。请帮帮我!!
服务器代码是
#!/usr/bin/python
import RPi.GPIO as GPIO
import socket
HOST='192.168.0.106'
PORT=5002
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind((HOST, PORT))
s.listen(1)
conn, addr=s.accept()
s.setsockopt(socket.IPPROTO_TCP, socket.TCP_NODELAY, 1)
print 'Connected by', addr
GPIO.setmode(GPIO.BCM)
GPIO.setup(04, GPIO.IN)
GPIO.setup(17, GPIO.IN)
GPIO.setup(27, GPIO.IN)
while True:
if (GPIO.input(04)==True):
if (GPIO.input(17)==False):
if (GPIO.input(27)==False):
conn.send('0')
elif(GPIO.input(27)==True):
conn.send('1')
elif (GPIO.input(17)==True):
if (GPIO.input(27)==False):
conn.send('2')
elif (GPIO.input(27)==True):
conn.send('3')
elif (GPIO.input(04)==False):
conn.send('5')
s.close()
客户端代码在这里
#!/usr/bin/python
import socket
import RPi.GPIO as GPIO
HOST='192.168.0.106'
PORT=5002
s=socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((HOST, PORT))
GPIO.setmode(GPIO.BCM)
GPIO.setup(02, GPIO.OUT)
GPIO.setup(03, GPIO.OUT)
GPIO.setup(11, GPIO.OUT)
GPIO.setup(10, GPIO.OUT)
while 1:
data=s.recv(8096)
if data=='0':
print 'Forward'
GPIO.output(02,True)
GPIO.output(03, False)
GPIO.output(11, False)
elif data=='1':
print 'Backward'
GPIO.output(02, False)
GPIO.output(03, True)
GPIO.output(11, True)
GPIO.output(10, False)
elif data=='2':
print 'Left'
GPIO.output(02, False)
GPIO.output(03, False)
GPIO.output(11, False)
GPIO.output(10, True)
elif data=='3':
print 'Right'
GPIO.output(02, True)
GPIO.output(03, False)
GPIO.output(11, False)
GPIO.output(10, False)
elif data=='5':
print 'Stop'
GPIO.output(02, False)
GPIO.output(03, False)
GPIO.output(11, False)
GPIO.output(10, False)
s.close()
答案 0 :(得分:4)
有些事情对您的代码不是惯用的。还有一些事情可能会对其行为产生影响。
if (GPIO.input(04)==True):
你应该这样写这样的语句:
if GPIO.input(4):
我删除的括号完全是多余的。他们没有任何区别。
我还将04
更改为4
,因为04
是八进制文字。这个特定值没有区别,因为八进制4和十进制4是相同的值。然而,在这里使用八进制是令人困惑和惊讶的(如果使用八进制来引用GPIO引脚是惯用的,这可能是在这里使用八进制的原因,但据我所知它不是)。由于您的引脚号码恰好是8或更大,因此不是使用八进制表示法编写的,我猜这是无意的。
我还删除了与True
的显式比较。你几乎不应该与True
进行比较。如果GPIO.input(4) == True
返回True
,则GPIO.input(4)
会评估为True
。所以你也可以跳过额外的比较(或者从另一个角度来看,你为什么不写if (GPIO.input(4) == True) == True:
?)。
类似于以下行:
if (GPIO.input(27)==False):
你应该写这个:
if not GPIO.input(27):
你几乎不应该与False
进行比较。
也许更严重:
if (GPIO.input(27)==False):
conn.send('0')
elif(GPIO.input(27)==True):
conn.send('1')
我认为你的应用程序在你的程序中对此引脚进行两次采样并不重要 - 但这就是你正在做的事情。第一个GPIO.input(27)
很可能会返回True
而第二个调用将返回False
。在这种情况下,您的程序不会采取任何行动 - 谁知道后果。
相反,你应该写一些像:
if GPIO.input(27):
conn.send('1')
else:
conn.send('0')
也许最重要的是
while 1:
data=s.recv(8096)
if data=='0':
这是套接字API的误用。您最多要求8096个字节,然后处理结果,就像您最多要求1个字节一样。伴随程序总是一次写入1个字节并不重要。允许TCP将这些写入合并在一起。
相反,你应该写:
while 1:
data = s.recv(1)
if data=='0':
嗯,这不是理想的写作方式,但这是使代码按照您的意图执行的最小变化。
目前尚不清楚这是否与您遇到的问题有关但缺乏您的特定硬件我怀疑任何人都可以实际重现该问题。
在使用代码修复这些问题后,您的下一个调试步骤应该是缩小首次出现延迟的位置。
发送端的GPIO引脚可能受到干扰,数据不再出现。也许GPIO库中的某些内容在某些输入下是行为不端的。也许其中一个raspberrypis上的网络堆栈存在问题 - 由于资源限制或硬件故障或其他我无法猜测的事情等等。
因此,请对发件人进行检测,以便了解是否定期发送数据或是否在此处引入延迟。如果它定期发送数据,则检查接收器是否定期接收数据。如果是,那么你可能已经将问题缩小到GPIO库或接收端的引脚。
仪器可以非常简单。例如,尝试在循环内放置一些打印以及time.time()
的调用。这将让您了解循环体运行的频率。如果你发现时间上有差距,那么你就得到了第一条线索。