Cape comms2를 사용하여 Beaglebone Black에서 RS485 통신 문제 해결

Cape comms2를 사용하여 Beaglebone Black에서 RS485 통신 문제 해결

TLDR: BeagleBone Black에서 직렬 통신(RS485)이 작동하지 않습니다. 이 문제를 어떻게 해결하나요?

——

나 이후질문해결책을 찾지 못했습니다. 지금은 통신의 Linux 측면을 탐색 중입니다.

상황을 요약하자면: BeagleBone black이 장착된 RS485 9600 보드, 8N1 통신 문제를 해결하고 있습니다.케이프커뮤니케이션즈 2. uart는 /dev/ttyS4에 연결됩니다. 내 소프트웨어는 nodejs로 개발되었으며 RS485 통신 문제 해결을 위한 간단한 버전이 있습니다(코드는 질문 끝에 있습니다).

내가 가지고 있는 데비안 버전:

$ uname -a
Linux pepsr-drix 4.14.108-ti-r131 #1stretch SMP PREEMPT Tue Mar 24 19:18:37 UTC 2020 armv7l GNU/Linux

UART 구성은 다음과 같습니다.

$ cat /boot/uEnv.txt
#Docs: http://elinux.org/Beagleboard:U-boot_partitioning_layout_2.0

uname_r=4.14.108-ti-r131
#uuid=
#dtb=

###U-Boot Overlays###
###Documentation: http://elinux.org/Beagleboard:BeagleBoneBlack_Debian#U-Boot_Overlays
###Master Enable
enable_uboot_overlays=1
###
###Overide capes with eeprom
uboot_overlay_addr0=/lib/firmware/BB-UART1-00A0.dtbo
uboot_overlay_addr1=/lib/firmware/BB-UART2-00A0.dtbo
uboot_overlay_addr2=/lib/firmware/BB-UART4-00A0.dtbo
uboot_overlay_addr3=/lib/firmware/BB-UART5-00A0.dtbo
###
###Additional custom capes
#uboot_overlay_addr4=/lib/firmware/<file4>.dtbo
#uboot_overlay_addr5=/lib/firmware/<file5>.dtbo
#uboot_overlay_addr6=/lib/firmware/<file6>.dtbo
#uboot_overlay_addr7=/lib/firmware/<file7>.dtbo
###
###Custom Cape
#dtb_overlay=/lib/firmware/<file8>.dtbo
###
###Disable auto loading of virtual capes (emmc/video/wireless/adc)
#disable_uboot_overlay_emmc=1
#disable_uboot_overlay_video=1
#disable_uboot_overlay_audio=1
#disable_uboot_overlay_wireless=1
#disable_uboot_overlay_adc=1
###
###PRUSS OPTIONS
###pru_rproc (4.14.x-ti kernel)
uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-14-TI-00A0.dtbo
###pru_rproc (4.19.x-ti kernel)
#uboot_overlay_pru=/lib/firmware/AM335X-PRU-RPROC-4-19-TI-00A0.dtbo
###pru_uio (4.14.x-ti, 4.19.x-ti & mainline/bone kernel)
#uboot_overlay_pru=/lib/firmware/AM335X-PRU-UIO-00A0.dtbo
###
###Cape Universal Enable
enable_uboot_cape_universal=1
###
###Debug: disable uboot autoload of Cape
#disable_uboot_overlay_addr0=1
#disable_uboot_overlay_addr1=1
#disable_uboot_overlay_addr2=1
#disable_uboot_overlay_addr3=1
###
###U-Boot fdt tweaks... (60000 = 384KB)
#uboot_fdt_buffer=0x60000
###U-Boot Overlays###

cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet

#In the event of edid real failures, uncomment this next line:
#cmdline=coherent_pool=1M net.ifnames=0 lpj=1990656 rng_core.default_quality=100 quiet video=HDMI-A-1:1024x768@60e

##enable Generic eMMC Flasher:
##make sure, these tools are installed: dosfstools rsync
#cmdline=init=/opt/scripts/tools/eMMC/init-eMMC-flasher-v3.sh

직렬 포트를 보면 a) 모두가 준비되어 있습니다(RTS|CTS|DTR|DSR). b) 전송 데이터 크기가 증가합니다. c) 수신 데이터 크기가 1로 고정되어 있습니다.

$ sudo cat /proc/tty/driver/serial
[sudo] password for debian: 
serinfo:1.0 driver revision:
4: uart:8250 mmio:0x481A8000 irq:34 tx:1917 rx:1 brk:1 RTS|CTS|DTR|DSR
4: uart:8250 mmio:0x481A8000 irq:34 tx:2008 rx:1 brk:1 RTS|CTS|DTR|DSR
4: uart:8250 mmio:0x481A8000 irq:34 tx:2060 rx:1 brk:1 RTS|CTS|DTR|DSR
...
4: uart:8250 mmio:0x481A8000 irq:34 tx:4400 rx:1 brk:1 RTS|CTS|DTR|DSR

최소 세션을 테스트하기 위해 bash 스크립트를 작성했지만 최소 세션에서는 아무 것도 나타나지 않습니다.

$ cat ./testRs485.sh
#!/bin/bash
echo 'RS485 test script by Sdl on October 2021 @ Will’s Kissimmee, FL, USA (/dev/ttyS4 serial 9600 bauds 8N1)'
echo 'Asking for Daly BMS information'

DEVICE=/dev/ttyS4

stty -F $DEVICE speed 9600 cs8 -cstopb -echo
#echo -en "\xD2\x03\x00\x0C\x01\x57\xAA" > $DEVICE
echo 'Query voltage and current'
echo -en "\xa5\x40\x90\x08\x00\x00\x00\x00\x00\x00\x00\x00\x7d" > $DEVICE

# Expected response: 69 40 86 00 83 00 00 75 30 01 e8 4f 

sleep 10
echo 'Query nominal capacity and cell voltage'
echo -en "\xa5\x40\x50\x08\x00\x00\x00\x00\x00\x00\x00\x00\x3d" > $DEVICE
# Expected response : 69 40 85 00 00 c3 50 00 00 00 00 11 
sleep 10

내 설정에 어떤 문제가 있나요?

부록:

Nodejs testRs485.js 코드:

$ cat testRs485.js
/**
 * @abstract RS 485 test file 
 * @file src/testRs485.js
 * @module pepsr
 *
 * @summary RS485 tester
 *
 * @Copyright © 2019-2021 - All rights reserved
 * @author SDL 
 * @created RS485 testing code by Sdl on Saturday December 18th 2021 8:41pm @ Will’s Hoadland av. in Kissimmee, FL, USA.
 */



 const devices = {
        bmsMaster: 0x01,
        bluetoothApp: 0x20,
        gprs: 0x40,
        hostComputer: 0x80,
}
const messages = {
        socVoltageCurrent: 0x90,
}

const dalyHeader = 0xa5
const device = devices.gprs
const message = messages.socVoltageCurrent
const payloadLength = 8




function pack(address, action, parameter, data) {
        var length = String('00' + data.length.toString()).slice(-2);
        var bufferAsString = address + action + parameter + length + data;
        var check = 0;
        for (var i = 0; i < bufferAsString.length; ++i) {
                check += bufferAsString.charCodeAt(i)
        }
        var checkSum = String('000' + String(check % 256)).slice(-3);
        var buffer = Buffer.from(bufferAsString + checkSum),
                carriageReturn = Buffer.from('\r');
        return Buffer.concat([buffer, carriageReturn]);
}


/**
 * Computes the check sum
 * @param {[uint8]} data The data buffer 
 * @param {Number} length The number of bytes 
 * @returns The ine-byte checksum
 */
function checksum(buffer, length) {
        let checksum = 0
        for (let i=0; i<length; i++) {
                checksum += buffer[i]
        }
        return checksum & 0xff
}


setInterval(function() {
        console.log("timer that keeps nodejs processing running");
}, 1000 * 60);


var SerialPort = require('serialport')

const portDevice = '/dev/ttyS4'
var port = new SerialPort(portDevice, {
        autoOpen: false,
        baudRate: 9600,
        dataBits: 8,
        stopBits: 1,
        parity: 'none',

        // COntrol flow: none
        /*xon: false,
    xoff: false,
    rtscts: false*/
}, false)

function open () {
        if (port.isOpen) return;
        console.log('Opening serial port', portDevice, '…')
    port.open(err => {
        if (!err) {
                        console.log('Serial port is open')
                        return
                }
        console.err('Port is not open:', err)

                // next attempt to open after 10s
        setTimeout(open, 10000)
    });
}

// == On open…
port.on('open', () => {
        console.log('Successfully open')
        console.log("In port.open():", port.isOpen)
        console.log('Preparing message to be sent')

        const messagetoSend = new Buffer.from([
                dalyHeader, 
                device, 
                message, 
                payloadLength, 
                0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
                0x7d // checksum to be computed
        ])
        //pack('001', '00', '740', '=?')

        const ccs = checksum(messagetoSend, messagetoSend.length-1)
        const cs = messagetoSend[messagetoSend.length-1]

        console.log('Computed checksum is', ccs, ', stored checksum is', cs, 'on the',messagetoSend.length, '-byte packet', messagetoSend)

        messagetoSend[messagetoSend.length-1] = ccs

        let counter = 1

        setInterval(function() {
                console.log(`About to send message #${counter++}:`, messagetoSend)
                const sent = port.write(messagetoSend, err => {
                        if (err) {
                                return console.error('Send error:',err)
                        }
                        console.log('Sent message successfuly')

                        if (false) {
                                console.log('Draining serial')
                                port.drain(() => console.log('Drain done'))
                        }
                })
                console.log('Send returned', sent)

        }, 15000)
})

port.on('data', data => {
        console.log('Received data: ' + data);
})

port.on('close', () => {
        console.log('Serial port closed')
        console.log('Reopening')
        open()
})

port.on('error', err => {
        console.error('Error:', err);
})

open()

관련 정보