如何让多线程成为我在树莓派之间的通信代码?
How to make multithread my communication code between Raspberry Pis?
我正在尝试通过 TCP 与两个 RPi 通信。一个树莓派是服务器,另一个是客户端。服务器部分包括电机和传感器,客户端部分包括操纵杆。我想将控制值从客户端发送到服务器,并将传感器值从服务器发送到客户端。我的代码可以单独执行这些操作,我可以控制从服务器到客户端的 BLDC,并将传感器值从客户端发送到服务器。但我正试图同时做这些。我该怎么做?
服务器代码:
import socket
import os
import time
os.system("sudo pigpiod")
time.sleep(1)
import pigpio
import RPi.GPIO as GPIO
pi = pigpio.pi()
ESC = 4
min_value = 1200
max_value = 2400
HOST = ''
PORT = 65458
a = 0
c = 0
def control():
data = conn.recv(1024)
stringdata = data.decode('ascii')
altan = int(stringdata)
alta = altan + 1000
print(alta)
pi.set_servo_pulsewidth(ESC, alta)
def update():
global a
global c
a = a + 5
c = c + 3
def sendsensorvalues():
b = 'd1' + str(a)
conn.send(b.encode('ascii'))
d = 'd2' + str(c)
conn.send(d.encode('ascii'))
update()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('CONNECTED BY', addr)
while True:
control()
sendsensorvalues()
客户代码:
import socket
import serial
from time import sleep
HOST = '169.254.78.190'
PORT = 65458
def sendmotor():
read = ser.readline()
a = int(read)
b = str(a)
s.sendall(b.encode('ascii'))
def displayfirst():
a = strdata[2:]
print('First senso value is : ' + a)
def displaysecond():
b = strdata[2:]
print('Second sensor value is : ' + b)
def getsensorvalues():
data = s.recv(1024)
strdata = data.decode('ascii')
if strdata[1] == '1':
displayfirst()
else:
displaysecond()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
ser = serial.Serial("/dev/ttyUSB0", 57600)
ser.baudrate = 57600
while True:
sendmotor()
getsensorvalues()
当我 运行 这个代码时,我得到错误:
Server part error, control() function takes two value
Client part error
服务器部分错误
服务器一次最多接收 1024 个字节 data = conn.recv(1024)
。从屏幕图像可以明显看出,发送的数据项是 516
并且一次收到两个连续的数据项 516516
,当解释为一个大数时会导致错误。解决此问题的一种方法是不发送可变长度的数据,而是发送固定长度的数据,并且只接收该数量的字节,例如。 G。使用 import struct
并在客户端更改
b = str(a)
s.sendall(b.encode('ascii'))
到
b = struct.pack('i', a) # length 4
s.sendall(b)
以及在服务器中更改
data = conn.recv(1024)
stringdata = data.decode('ascii')
altan = int(stringdata)
到
data = conn.recv(4)
altan = struct.unpack('i', data)[0]
客户端部分错误
显示的客户端错误可能是 strdata
由于服务器终止而为空的结果。除此之外,客户端与服务器有相同的问题,可能会接收连接的传感器值,您可以用类似的方式解决这个问题,例如。 G。通过改变
b = 'd1' + str(a)
conn.send(b.encode('ascii'))
到
conn.send(struct.pack('=2si', b'd1', a)) # length 6
…
在 UNIX 上执行 I/O 多路复用的标准方法是使用 select
。 Python 有一个标准绑定,select
module。
然而,这是相当低级的。
如果您使用的是 Python 3.4 或更高版本,我建议您改用 selectors
module。该页面底部的示例应该可以帮助您入门。
编辑: this guide 可能也会派上用场。它包含示例代码和解释。
我正在尝试通过 TCP 与两个 RPi 通信。一个树莓派是服务器,另一个是客户端。服务器部分包括电机和传感器,客户端部分包括操纵杆。我想将控制值从客户端发送到服务器,并将传感器值从服务器发送到客户端。我的代码可以单独执行这些操作,我可以控制从服务器到客户端的 BLDC,并将传感器值从客户端发送到服务器。但我正试图同时做这些。我该怎么做?
服务器代码:
import socket
import os
import time
os.system("sudo pigpiod")
time.sleep(1)
import pigpio
import RPi.GPIO as GPIO
pi = pigpio.pi()
ESC = 4
min_value = 1200
max_value = 2400
HOST = ''
PORT = 65458
a = 0
c = 0
def control():
data = conn.recv(1024)
stringdata = data.decode('ascii')
altan = int(stringdata)
alta = altan + 1000
print(alta)
pi.set_servo_pulsewidth(ESC, alta)
def update():
global a
global c
a = a + 5
c = c + 3
def sendsensorvalues():
b = 'd1' + str(a)
conn.send(b.encode('ascii'))
d = 'd2' + str(c)
conn.send(d.encode('ascii'))
update()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
conn, addr = s.accept()
with conn:
print('CONNECTED BY', addr)
while True:
control()
sendsensorvalues()
客户代码:
import socket
import serial
from time import sleep
HOST = '169.254.78.190'
PORT = 65458
def sendmotor():
read = ser.readline()
a = int(read)
b = str(a)
s.sendall(b.encode('ascii'))
def displayfirst():
a = strdata[2:]
print('First senso value is : ' + a)
def displaysecond():
b = strdata[2:]
print('Second sensor value is : ' + b)
def getsensorvalues():
data = s.recv(1024)
strdata = data.decode('ascii')
if strdata[1] == '1':
displayfirst()
else:
displaysecond()
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.connect((HOST, PORT))
ser = serial.Serial("/dev/ttyUSB0", 57600)
ser.baudrate = 57600
while True:
sendmotor()
getsensorvalues()
当我 运行 这个代码时,我得到错误:
Server part error, control() function takes two value
Client part error
服务器一次最多接收 1024 个字节 data = conn.recv(1024)
。从屏幕图像可以明显看出,发送的数据项是 516
并且一次收到两个连续的数据项 516516
,当解释为一个大数时会导致错误。解决此问题的一种方法是不发送可变长度的数据,而是发送固定长度的数据,并且只接收该数量的字节,例如。 G。使用 import struct
并在客户端更改
b = str(a)
s.sendall(b.encode('ascii'))
到
b = struct.pack('i', a) # length 4
s.sendall(b)
以及在服务器中更改
data = conn.recv(1024)
stringdata = data.decode('ascii')
altan = int(stringdata)
到
data = conn.recv(4)
altan = struct.unpack('i', data)[0]
客户端部分错误
显示的客户端错误可能是 strdata
由于服务器终止而为空的结果。除此之外,客户端与服务器有相同的问题,可能会接收连接的传感器值,您可以用类似的方式解决这个问题,例如。 G。通过改变
b = 'd1' + str(a)
conn.send(b.encode('ascii'))
到
conn.send(struct.pack('=2si', b'd1', a)) # length 6
…
在 UNIX 上执行 I/O 多路复用的标准方法是使用 select
。 Python 有一个标准绑定,select
module。
然而,这是相当低级的。
如果您使用的是 Python 3.4 或更高版本,我建议您改用 selectors
module。该页面底部的示例应该可以帮助您入门。
编辑: this guide 可能也会派上用场。它包含示例代码和解释。