我有一个 Arduino Rs485 网络,正在尝试在 Raspberry Pi 中添加一个。 Pi 能够向 Arduino 发送消息,但无法接收
Posted
技术标签:
【中文标题】我有一个 Arduino Rs485 网络,正在尝试在 Raspberry Pi 中添加一个。 Pi 能够向 Arduino 发送消息,但无法接收【英文标题】:I have an Arduino Rs485 network, and am trying to add a in Raspberry Pi. The Pi is able to send messages to the Arduino's, but is unable to receive 【发布时间】:2020-06-13 14:39:29 【问题描述】:我的网络由多个连接到Max485 的 Arduino 组成。这些 Arduino 可以完美地相互交流。
我目前正在尝试将 Raspberry Pi 连接到网络中。我一直在关注this tutorial。
我已启用 UART 引脚,并禁用了 shell over serial。
为了测试,我有wired TX(GPIO 14/pin 8)到 MAX485 上的 DI,RX(GPIO 15/pin 10)到 RO,GPIO 4(pin 7)到 DE & RE。它还为两个 MAX485 芯片供电,并且两个芯片都接地。 在 arduino 方面,我目前使用的是Mega。它有 TX3 到 DI,RX3 到 RO,引脚 2 到 DE/RE。这两个设备是此网络上的唯一设备。
Raspi Python:
import time
import serial
import RPi.GPIO as GPIO
from time import sleep
GPIO.setwarnings(False)
GPIO.setmode(GPIO.BOARD)
#sets pin 7 on the GPIO as DE/RE
GPIO.setup(7, GPIO.OUT, initial=GPIO.LOW)
rs = serial.Serial(port='/dev/serial0', timeout=5, baudrate=9600)
data = bytearray()
msgIn = bytearray()
addr = 1
# Splits each byte into two, then unfold each half-byte to make a full byte.
# The slave will take this data, and fold it back to readable form
# This is to ensure anything being read by the slave is actual data, not noise.
def foldOpen(where, what):
hb = what >> 4
where.append((hb << 4) | (hb ^ 0x0F))
lb = what & 0x0F
where.append((lb << 4) | (lb ^ 0x0F))
# Unfolds the folded data
def unFold():
sByte, cByte = False, 0
timeout = time.perf_counter()
while((time.perf_counter() - timeout) < 1):
inByte = rs.read()
if((inByte >> 4) != ((inByte & 0x0F) ^ 0x0F)):
return 0
inByte >>= 4
if(sByte):
cByte <<= 4
cByte |= inByte
return cByte
else:
cByte = inByte
sByte = True
timeout = time.perf_counter()
return 0
# add's each piece of data into the crc
def AddCrc(crc, n):
for i in range(0, 8):
mix = (n ^ crc) & 0x01
crc >>= 1
if(mix):
crc ^= 0x8C
n >>= 1
return crc & 0xFF
#Receives a start bit, then address, then data length, then data, and finally crc.
#If everything is formatted correctly, the right amound of data is passed and crc correct
#it will return true
def recvMsg(msg):
msgState = crc = msgL = 0
timeout = time.perf_counter()
while(msgState <= 4):
if(rs.in_waiting > 0):
if(msgState < 1):
inByte = rs.read()
sleep(1)
else:
inByte = unFold()
if(msgState == 4):
for x in msg:
crc = AddCrc(crc, x)
if(crc == inByte):
return 1
elif(msgState == 3):
msg.append = inByte
if(len(msg) == msgL):
msgState = 4
elif(msgState == 2):
msgL = inByte
msgState = 3
elif(msgState == 1):
if(inByte == addr):
msgState = 2
else:
msgState = 5
elif(msgState == 0):
print('Start bit is ')
print(inByte)
if(inByte == 2):
print('accepted')
msgState = 1
if((time.perf_counter() - timeout) >= 5):
msgState = 5
#Sends a message, starting with start bit (2), addr, msg length, data, and crc
def sendMsg(where, size, what):
GPIO.output(7, GPIO.HIGH)
msg = bytearray()
crc = 0
msg.append(2)
foldOpen(msg, where)
foldOpen(msg, size)
for x in what:
foldOpen(msg, x)
for x in what:
crc = AddCrc(crc, x)
foldOpen(msg, crc)
rs.write(msg)
rs.flush()
GPIO.output(7, GPIO.LOW)
#creating random data to send to slave for testing
data = bytearray()
info = ord('A')
info2 = 45
data.append(info)
data.append(info2)
sendMsg(2, len(data), data)
#reads 1 byte, just so I know I made a connection
timer = time.perf_counter()
while((time.perf_counter() - timer) < 10):
if(rs.in_waiting):
inByte = rs.read(1)
print(inByte)
Arduino 代码:
#include <RS485_Comm.h>
byte enablePin = 2;
byte check = 0;
size_t rsWrite (const byte what)
Serial3.write (what);
Serial3.flush();
bool rsAvailable ()
return Serial3.available ();
int rsRead ()
return Serial3.read ();
RS485 myChannel (rsWrite, rsAvailable, rsRead, 20, 2, 2, 1);
//name(Write CB, AvailableCB, ReadCB, buffer, Epin, Addr, Debug)
void setup()
Serial.begin(9600);
Serial3.begin(9600);
myChannel.begin();
Serial.print("A-OK");
void loop()
if (myChannel.recvMsg())
if (myChannel.getMsg()[0] == 'A')
Serial.print("A-OK");
byte msgOut[] = "A";
myChannel.sendMsg(msgOut, sizeof(msgOut), 1);
同样,我可以从 Raspi 向 Arduino 发送消息。相同的 Arduino,以相同的配置接线,可以与网络上的其他 Arduino 来回通信。
我无法从 Arduino 获取任何信息到树莓派。 rs.read(1) 不返回任何内容或一些随机噪声。我哪里错了?
【问题讨论】:
你在树莓派上/boot/cmdline.txt
的设置是什么?
Arduino代码还是python???
糟糕,刚刚解决了这个问题。
和@hcheung 它的“console=tty1 root=PARTUUID=ea7d04d6-02 rootfstype=ext4 lift=deadline fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles”
【参考方案1】:
阅读您的问题,您似乎正在使用 5V 逻辑为您的 RPi 上的 GPIO 引脚供电。
这对于快速测试可能没问题,但从长远来看,可能会损坏某些东西。如果您的转换器支持,您最好使用 3.3V 作为 MAX485 的电源电压(其中一些板仅适用于 5V,而另一些似乎是双电压)。
您的 RPi 上的 UART RX 似乎有问题,也许您应该验证它是否仍然正常。您可以按照以下步骤操作:
1) 移除 RPi 40 针连接器上的所有电线。
2) 将 RPi 的 UART 上的 RX 短接至 TX(引脚 8 与引脚 10 短接)。
3)运行minicom:sudo minicom -D /dev/serial0
4) 在屏幕上键入任何内容。如果您能看到您正在输入的内容,则表示您的 UART 正在工作。
5) 按 CTRL+A 然后按 E 来激活回声。在屏幕上键入其他内容,现在您应该会看到每个击键出现两次。
6)点击CTRL+A然后X退出minicom。
如果您需要进一步对 UART 进行故障排除,有许多教程提供了更多详细信息。例如,请参阅here。
如果这些 UART 测试成功,您可以继续将 RPi 连接到 Arduino 并再次运行 minicom,这次您可以选择波特率:
sudo minicom -D /dev/serial0 -b 9600
然后打开你的 Arduino 看看你是否收到了。
如果您这样做了,但您的 Python 代码仍然没有报告任何内容,您可以确定问题出在那儿(如果对于这样一个简单的任务来说有点过于复杂,您的代码看起来还不错)。
【讨论】:
以上是关于我有一个 Arduino Rs485 网络,正在尝试在 Raspberry Pi 中添加一个。 Pi 能够向 Arduino 发送消息,但无法接收的主要内容,如果未能解决你的问题,请参考以下文章
LabVIEW Arduino RS-485智能农业监测系统(项目篇—4)
Arduino Uno可以运行两个以上的软件uart通信吗?