IGC 控制器通信开发

更新时间:
2024-04-26
下载文档

IGC 控制器通信开发

本节介绍了如何通过不同的开发方式,实现 IGC 控制器与 HMI 的通信。

本例程是在“IGC 控制器双机通信”中 VSOA Client 端开发 的工程基础上增加 Modbus 功能,与 HMI 设备采用 Modbus TCP 协议进行通讯,实现 HMI 可视化展示的效果。

说明:

由于本例程依赖的是“IGC 控制器双机通信 > VSOA Client 端开发”章节,所以本案例将依托上面的章节内容,运行在 IGC1500 控制器上。

前提条件

根据之前的学习,已经能熟练掌握 SylixOS 开发环境 RealEvo-IDE 的基本使用方法。如:新建工程,添加依赖文件及依赖路径,配置目标设备和工程编译运行等操作。

操作前需保证 IGC 控制器已经部署 VSOA 环境。若还未部署,可按照“IGC 控制器双机通信 > 环境准备”中 操作步骤 进行部署。

HMI 设备寄存器定义

寄存器说明
40001电机启动/停止状态寄存器
40002电机速度寄存器(单位:r/min)

操作步骤

步骤 1:创建 App 工程

  1. 参考“IGC 控制器双机通信 > VSOA Client 端开发”中 步骤 1,创建 app_vsoa_client_modbus 工程,并添加 VSOA 和 yyjson相关依赖文件和头文件路径。

  2. 删除 app_vsoa_client_modbus.cpp 文件,并且把“IGC 控制器双机通信 > VSOA Client 端开发”中 app_vsoa_client 工程案例“src\”目录下的 app_vsoa_client.cpp、packet_json.h、packet_json.cpp 全部复制到 app_vsoa_client_modbus 工程中的“src\”目录,如图所示。

  3. 下载 app_vsoa_client_modbus 示例工程open in new window,工程中包含 libmodbus 文件夹,将 libmodbus 文件夹复制到用户的 app_vsoa_client_modbus 工程中,如图所示。

  4. 为工程添加 libmodus 库依赖。

  5. 为工程添加 libmodbus 库头文件路径。

步骤 2:创建 Modbus 线程

  1. 在 app_vsoa_client_modbus.cpp 文件中,添加 libmodbus 库头文件。

    #include "modbus.h"
    
  2. 编写 Modbus 处理线程。创建 Modbus tcp master,连接 Modbus tcp slave HMI 设备,而后每隔一段时间,将电机速度写入 HMI 设备的 40002 寄存器中,并对 40002 寄存器的值进行监听。当数据变化时,程序通过 VSOA RPC 向 VSOA Server 端发送电机的“启动/停止”命令请求。

    static  void *modbus_pthread (void  *arg)
    {
        modbus_t             *ctx;
        state_data_t          l_state_data;
        uint16_t              temp;
        bool                  flag;
    
        /*
         *  init modbus tcp master, and connect slave
         */
        ctx = modbus_new_tcp("192.168.1.133", 502);
        do {
            sleep(1);
            if (modbus_connect(ctx) == -1) {
                fprintf(stderr, "Connection failed: %s\n", modbus_strerror(errno));
    
            } else {
                break;
            }
        } while (1);
    
        while (1) {
            usleep(100 * 1000);
            memcpy(&l_state_data, &state_data, sizeof(state_data));
    
            /*
             *  write motor speed to HMI
             *  calc: r/min, motor encode 23 bit = 8,388,608
             */
            modbus_write_register(ctx, 1, ((int64_t)l_state_data.motor_speed * 60) / 8388608);
    
            /*
             *  read start btn is not press
             *  if press, then call vsoa rpc to set vsoa server
             */
            modbus_read_registers(ctx, 0, 1, &temp);
            flag = (0 == temp) ? 0 : 1;
            if (l_state_data.run_flag != flag) {
                bool                      ret;
                vsoa_url_t                url;
                vsoa_header_t            *vsoa_hdr;
                vsoa_payload_t            reply, send;
                vsoa_client_sync_call_t  *sync;
    
                sync = vsoa_client_sync_create(true);
    
                /*
                 *  when the situation CODESYS as the VSOA Server, 
                 *  the following "url.url" should be replaced by (char *)"/plc/motor0/control"
                 */
                url.url        = (char *)"/control";
                url.url_len    = strlen(url.url);
                send.data      = NULL;
                send.data_len  = 0;
                send.param     = ethercat_motor_control_json_stringify(flag);
                send.param_len = strlen(send.param);
                ret = vsoa_client_sync_call(client, VSOA_CLIENT_RPC_METHOD_SET,
                                            &url, &send, sync, &vsoa_hdr, NULL);
                if (ret) {
                    if (vsoa_hdr) {
                        vsoa_parser_get_payload(vsoa_hdr, &reply);
                        char  err_msg[512] = {0};
                        bool  state;
                        if (control_ack_parse (reply.param, reply.param_len, &state, err_msg)) {
                            if (state) {
    
                            } else {
                                printf("conctrol motor msg err: %s\r\n", err_msg);
                            }
    
                        } else {
                            printf("conctrol motor send msg err\r\n");
                        }
    
                    } else {
                        fprintf(stderr, "Server not reply!\n");
                    }
    
                } else {
                    fprintf(stderr, "Synchronous RPC call error!\n");
                }
    
                ret = vsoa_client_sync_delete(sync);
            }
        }
    
    _pthread_exit:
        return  (NULL);
    }
    
  3. 在 app_vsoa_client_modbus.cpp 文件中,创建 modbus_pthread 线程。

    int main (int  argc, char  **argv)
    {
        ...
    
        /*
         * subscribe /state url topic
         * when the situation CODESYS as the VSOA Server, 
         * the following "url.url" should be replaced by (char *)"/plc/motor0/state"
         */
        vsoa_url_t    l_url = {0};
        l_url.url           = (char *)"/state";
        l_url.url_len       = strlen(l_url.url);
    
        vsoa_client_subscribe(client, &l_url, NULL, NULL, NULL);
        
        pthread_t  id;
        pthread_create(&id, NULL, modbus_pthread, NULL);
        
        /*
         * start circular monitoring
         */
        while (1) {
            FD_ZERO(&fds);
            max_fd = vsoa_client_fds(client, &fds);
    
            cnt = pselect(max_fd + 1, &fds, NULL, NULL, &timeout, NULL);
            if (cnt > 0) {
                if (!vsoa_client_input_fds(client, &fds)) {
                    vsoa_client_close(client);
                    fprintf(stderr, "Connection lost!\n");
                    return  (-1);
                }
            }
        }
    
        return  (0);
    }
    

步骤 3:部署工程环境

  1. 将 app_vsoa_client_modbus 应用工程部署到 IGC1500 控制器中,目标设备及路径如图所示。

  2. 右击 app_vsoa_client_modbus 应用工程进行上传部署。

文档内容是否对您有所帮助?
有帮助
没帮助