简体   繁体   English

如何协调响应与 Beaglebone black 上 RS485 通信的请求?

[英]How to reconcile response with request on a RS485 communications on a Beaglebone black?

I have a Beaglebone black running on linux Debian with a cape Comms2 with RS485 connectivity (the linux serial port device is at /dev/ttyS1).我有一个运行在 linux Debian 上的 Beaglebone black,带有带有 RS485 连接的 cape Comms2(linux 串行端口设备位于 /dev/ttyS1)。

I have no issue at making thinks communicate with a BMS (battery management system) device except that its protocol looks so weird that I can't safely sync between my requests and its responses.我对让 thinks 与 BMS(电池管理系统)设备进行通信没有任何问题,只是它的协议看起来很奇怪,以至于我无法在我的请求和它的响应之间安全地同步。

Let me dive into the protocol which I reversed engineered: the frame for asking voltage, current and SoC (State of charge) is 0x90 and the frame is as follows:让我深入研究一下我逆向工程的协议:询问电压,电流和SoC(充电状态)的帧是0x90 ,帧如下:

<Buffer a5 40 90 08 00 00 00 00 00 00 00 00 cs>

With cs being the checksum (cumulative sum of all bytes, keeping the LSB). cs是校验和(所有字节的累积和,保留 LSB)。

The 13-byte response is as follows: 13字节响应如下:

<Buffer 69 40 86 00 84 00 00 75 30 03 e2 4c 00>

To decode the frame, skipping the 3-first bytes, we do:为了解码帧,跳过前 3 个字节,我们这样做:

  • bytes 3, 16-bit BE: voltage, apply scale 0.1V: 0x0084 = 132 * 0.1 = 13.2 V字节 3,16 位 BE:电压,应用标度 0.1V:0x0084 = 132 * 0.1 = 13.2 V
  • bytes 5, 16-bit BE: skip字节 5,16 位 BE:跳过
  • bytes 7, 16-bit BE: current, apply offset 30000, then scale 0.1A 0x7530 = 30000 - 30000 = 0A字节 7,16 位 BE:电流,应用偏移量 30000,然后缩放 0.1A 0x7530 = 30000 - 30000 = 0A
  • bytes 8, 16-bit BE: SoC, apply scale 0.1%: 0x03e2 = 994 * 0.1 = 99.4%字节 8,16 位 BE:SoC,应用比例 0.1%:0x03e2 = 994 * 0.1 = 99.4%

My code log gives the following values, which are as expected.我的代码日志给出了以下值,符合预期。

Pepsr v2.2.236 4:08:15 PM [pepsr-olenlab2] -- ✅- RS 485: voltageCurrentSoc: { voltage: 13.200000000000001, current: 0, soc: 99.4 }

So far so good.到目前为止,一切都很好。

But now, as I need much more data from the BMS, I must request more frame on a periodic way.但现在,由于我需要来自 BMS 的更多数据,我必须定期请求更多帧。 I implemented a Q/A system in a setInterval() as follows:我在setInterval()中实现了一个问答系统,如下所示:

class Rs485 {

    // … blah blah …

    start() {
        
        // == Analyze the received frames
        serialport.on('data',  data => {
                
            // Append data
            this.readingBytes = this.readingBytes.concat(Array.from(data))
            //this.log('data received: ', data, 'as array', Array.from(data), 'length is', this.readingBytes.length)
        
            // Data is OK?
            if (this.readingBytes.length == 13) {
                this.parseMessage(new Buffer.from(this.readingBytes))
                this.readingBytes = []
            }
        })
        
        // == Prepare the next frame to be requested
        this.askFor = 0
        this.askForCount = Object.keys(Rs485.FRAME_TYPE).length
        
        
        const request = () => {
            const key = Object.keys(Rs485.FRAME_TYPE)[this.askFor]
            const type = Rs485.FRAME_TYPE[key]
            //this.log('Now asking for ', this.askFor, 'th type, aka', key, ', value:', type)
            this.request(type)
        }
        
        // == On open…
        this.serialport.on('open', () => {
            this.success('Successfully open')
        
            request()
        })
        
        // == Periodically ask for the next frame type (1Hz)
        setInterval(() => {
            if (!this.serialport.isOpen) {
                this.log("Port Open Status: " + this.serialport.isOpen)
                return
            }
            request()
        },1e3)
    }

}

parseMessage() simply does what we did above based on the frame type. parseMessage()只是根据帧类型做我们上面做的事情。

As you can see, I store the current requested frame type in a variable and I assume the next packet to be received to be the response of the request.如您所见,我将当前请求的帧类型存储在一个变量中,并假设要接收的下一个数据包是请求的响应。

One thing I guess I must make clear is that I didn't found a hook in the response header that I can link to the request.我想我必须澄清的一件事是,我没有在响应 header 中找到可以链接到请求的挂钩。

So my question is how I can improve the communication model so that I can better reconcile response with request?所以我的问题是如何改善 model 的通信,以便更好地协调响应与请求?

If you only ever send requests of the same type (eg the battery voltage, current and SoC query) then there's no practical need to associate requests with responses.如果您只发送相同类型的请求(例如电池电压、电流和 SoC 查询),那么实际上没有必要将请求与响应相关联。 You can get away with just firing a new request every second without even looking at responses.你甚至可以不用查看响应而每秒触发一个新请求。 If a few frames go missing or get corrupted during transmission, no harm done - as long as the subsequent responses arrive, you'll have fresh data.如果在传输过程中有几帧 go 丢失或损坏,不会造成任何伤害 - 只要后续响应到达,您就会有新数据。

When you want to detect communication failure in this solution, start a timer on receiving a response (timer value depends on your system - maybe 10-60 seconds?) and declare a communication failure if you haven't received any new responses before the timeout expires.当您想在此解决方案中检测通信故障时,在收到响应时启动一个计时器(计时器值取决于您的系统 - 可能是 10-60 秒?)如果您在超时之前没有收到任何新响应,则声明通信失败到期。

If you send requests of different types then - yes, you need to remember which type of request got sent most recently and wait for the correct response.如果您发送不同类型的请求 - 是的,您需要记住最近发送的请求类型并等待正确的响应。 In this solution you need to start a timer with each request, then wait until the current request frame either receives the corresponding reply frame or times out.在此解决方案中,您需要为每个请求启动一个计时器,然后等待直到当前请求帧收到相应的回复帧或超时。 Don't send a new request before this happens.在此之前不要发送新请求。 Process a single request-response transaction to its successful or unsuccessful end before starting a new one.在开始新事务之前,将单个请求-响应事务处理到成功或不成功结束。 This way any transmission failures on the communication line get caught by the timeout and requests and responses shouldn't fall out of sync.这样,通信线路上的任何传输失败都会被超时捕获,并且请求和响应不应该不同步。 Again, the timeout values depend on your system.同样,超时值取决于您的系统。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM