我有一个 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通信吗?

RS-485 串行端口波特率性能效率

rs485通信OSI模型网络层

Pymodbus - 在 raspberry pi3 的 uart 上通过 rs485 读取电能表的输入寄存器

RS-232,RS-485,UART联系与区别