繁体   English   中英

带有libmodbus的多个RS485从站

[英]Multiple RS485 slaves with libmodbus

我在RS485总线上有多个从站。 到目前为止,我一直在使用pymodbus ,但是我对它的性能和其他问题不太满意。 所以我想测试libmodus并改用它。

我写了一个最小的程序来读取我的奴隶的型号

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <modbus.h>
#include <errno.h>


char *bigendian_vec_to_str(uint16_t *vec, size_t vec_size, char *buff, size_t buff_len)
{
    memset(buff, 0, sizeof *buff * buff_len);
    int i;

    for(i = 0; i < vec_size; ++i)
    {
        uint16_t fl = vec[i] >> 8;
        uint16_t sl = vec[i] & 0xff;

        if(2*i >= buff_len - 1)
            return buff;

        if(fl == 0)
            return buff;

        buff[2 * i] = fl;

        if(2*i + 1 >= buff_len - 1)
            return buff;

        if(sl == 0)
            return buff;

        buff[2 * i + 1] = sl;
    }

    return buff;
}

char *get_model_name_of(modbus_t *modbus, int slave, char *buff, size_t buff_len)
{
    modbus_flush(modbus);
    modbus_set_slave(modbus, slave);

    int rc; 
    uint16_t reg[9];

    memset(reg, 0, sizeof reg);

    rc = modbus_read_registers(modbus, 0xe, 8, reg);
    if (rc == -1) {
        fprintf(stderr, "Error %d while reading: %s\n", errno, modbus_strerror(errno));
        return NULL;
    }   
    return bigendian_vec_to_str(reg, 8, buff, buff_len);
}


int main(void)
{
    modbus_t *modbus = modbus_new_rtu("/dev/ttyUSB0", 9600, 'N', 8, 1);

    modbus_rtu_set_serial_mode(modbus, MODBUS_RTU_RS485);

    if (modbus_connect(modbus) == -1) {
        fprintf(stderr, "Connexion failed: %s\n", modbus_strerror(errno));
        modbus_free(modbus);
        return -1;
    }

    char buff[1024];
    int i;

    for(i = 2; i < 5; ++i)
    {
        printf("Model of slave %d: %s\n", i, get_model_name_of(modbus, i, buff, sizeof buff));
    }

    modbus_free(modbus);
    return 0;
}

当我运行这段代码时,我得到了

Model of slave 2: LEFS25B-600
Error 110 while reading: Connection timed out
Model of slave 3: (null)
Model of slave 4: LEHF10K2-16

第二个模块没有响应,这似乎很奇怪。 因此,我使get_model_name_of遍历了2,3,4,2,3,4,2,3,4 ....,并且读取的第二次尝试均以Error 110 while reading: Connection timed out结束, Error 110 while reading: Connection timed out 在iine modbus_set_slave(modbus, slave); 我加了

usleep(0.005 * 1000000);

然后我没有超时了。 我读了两次手册页,但没有发现任何警告我的信息。 我还搜索了google,但发现的“相似”线程均无济于事。

处理多个奴隶的最佳方法是什么? 为什么在这里增加半毫秒的睡眠会有所帮助? 我的意思是libmodus上的代码可以

static int _modbus_set_slave(modbus_t *ctx, int slave)
{
    /* Broadcast address is 0 (MODBUS_BROADCAST_ADDRESS) */
    if (slave >= 0 && slave <= 247) {
        ctx->slave = slave;
    } else {
        errno = EINVAL;
        return -1;
    }

    return 0;
}

在上下文中设置内部值。 在上下文中内部值的更改与对总线的读取/写入之间是否存在时间限制? 如果是这样,在set_slave之后我应该等待多长时间? 为什么libmodbus设置从全球ID而不是其作为一个参数的read / write方法,其他库(比如pymodbus )呢?

还是我只是错误地使用了此API?

谢谢

我可能错了..但是据我所知。 Modbus主站发出一个针对特定从站号的请求。 目的是从目标从站接收答复,然后将请求发送到下一个从站,并等待第二个从站的答复。 如果发送请求时没有等待第一个从属服务器的答复,则可能会错过第二个从属服务器(或第三个或任何编号的从属服务器)的答复,而第一个从属服务器正在发送和接收答复。主。

我不太擅长C语言编程..但是我建议您检查一下..因为我认为这可能就是为什么增加延迟似乎有帮助的原因...(另外.. Modbus协议的一部分确实需要暂停信号传输至定义传输的开始和结束。)如果我是对的,那么只有知道了要发送的数据的大小和计算响应的时间后,延迟的使用才能很好地工作。对于其他情况,某种握手会是安全的。例如读取线圈。表明是否刷新了数据并准备好作为可能的交通信号灯从从机读取数据。 控制去往其他从站的请求的时间,并避免响应冲突。 再次..我不太擅长C语言,如果我对程序有误解..请忽略我所说的内容..如果有帮助,。我很高兴听到。

彼得

暂无
暂无

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

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