树莓派中通过 wifi 的 Python 套接字

标签 python sockets networking tcp raspberry-pi

我用 python 编写了一个套接字。基本上有 2 个树莓派相互交谈并使用套接字通过 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()

最佳答案

您的代码中有些地方不是惯用的。还有一些事情可能会影响其行为。

if (GPIO.input(04)==True):

你应该这样写这个语句:

if GPIO.input(4):

我删除的括号完全是多余的。它们没有区别。

我还将 04 更改为 4 因为 04 是八进制文字。它对这个特定值没有影响,因为八进制 4 和十进制 4 是相同的值。不过,在这里使用八进制令人困惑和惊讶(如果使用八进制引用 GPIO 引脚是惯用的,这可能是在这里使用八进制的原因,但据我所知不是)。由于您的 PIN 码恰好是 8 或更大,所以这里没有使用八进制表示法,我猜这是无意的。

我还删除了与 True 的显式比较。您几乎不应该与 True 进行比较。如果 GPIO.input(4) 返回 True,则 GPIO.input(4) == True 的计算结果为 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() 的调用。这将使您看到循环体运行的频率。如果您注意到时间间隔,那么您就有了第一条线索。

关于树莓派中通过 wifi 的 Python 套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22531127/

相关文章:

python - 检查应用程序是否在服务器或本地运行

c# - 每个套接字地址(协议(protocol)/网络地址/端口)通常只允许使用一次

java - 应用引擎 : Keep Socket Open more than 2 Minutes

ruby - Socket.recv 有效但无法获取或读取?

excel - 访问共享网络文件夹

java - netty - 我可以引导一个新客户端来连接 channel 处理程序中的其他服务器吗?

python - 如何诊断不每周运行的 cron.weekly 脚本

python - 如何设置pyplot的刻度数和标签

python - 如何调试 ImportError(sys.path 正确)

java - 服务器/客户端通信不工作java