我有一个Arduino Rs485网络,正在尝试在Raspberry Pi中添加一个。Pi能够向Arduino发送消息,但无法接收

2024-09-29 20:26:54 发布

您现在位置:Python中文网/ 问答频道 /正文

我的网络由多个连接到Max485的Arduino组成。这些Arduino可以完美地交谈

我目前正在尝试将一个树莓Pi连接到网络中。我一直在关注this tutorial

我已经启用了UART引脚,并禁用了通过串行传输的shell

对于测试,我有wiredTX(GPIO 14/引脚8)到MAX485上的DI,RX(GPIO 15/引脚10)到RO,GPIO 4(引脚7)到DE&;重新。它还为两个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和raspberry pi那里得到任何信息。rs.read(1)不返回任何内容,或返回一些随机噪声。我哪里做错了


Tags: datagpioreturniftimecountermsgbyte
1条回答
网友
1楼 · 发布于 2024-09-29 20:26:54

在阅读您的问题时,您似乎正在为RPi上的GPIO引脚提供5V逻辑

对于快速测试来说,这可能没问题,但从长远来看,某些东西可能会损坏。如果转换器支持,最好使用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代码仍然没有报告任何内容,那么您可以确定问题出在那里(对于这样一个简单的任务,如果代码有点过于复杂,那么您的代码看起来很好)

相关问题 更多 >

    热门问题