基于 Modbus 的工业数据采集、控制(part 3)

news2024/12/26 2:12:03

Modbus 设备(利用 slave 模拟)

在这里插入图片描述

在这里插入图片描述

Modbus 采集程序

client.c

#include "client.h"

modbus_t *ctx;
key_t key_shm, key_msg;
int shmid, msgid;
struct shm *shm0;
struct msgbuf msg0;

void *collector(void *arg) {
   

    struct shm *p = (struct shm *)arg;
    while (1){
   
        sleep(1);
        if (modbus_read_registers(ctx, 0, 4, p->buf) < 0) {
   
            perror("Failed to modbus_read_registers");
            return NULL;
        }

        printf("LIGHT SENSOR: %d\n", p->buf[0]);
        printf("ACCELERATION SENSOR-X: %d\n", p->buf[1]);
        printf("ACCELERATION SENSOR-Y: %d\n", p->buf[2]);
        printf("ACCELERATION SENSOR-Z: %d\n\n", p->buf[3]);
    }
    pthread_exit(0);
}

void *control(void *arg) {
   

    while (1){
   
        msgrcv(msgid, &msg0, sizeof(msg0)-sizeof(long), 250, 0);
        printf("LED: %c\n", msg0.ctl[0]);
        printf("BUZZER: %c\n\n", msg0.ctl[1]);
        modbus_write_bit(ctx, msg0.ctl[0]-48, msg0.ctl[1]-48);
    }
    pthread_exit(0);
}

int main(int argc, char const *argv[])
{
      
    if (argc != 3) {
   
        printf("Please input %s <ip> <port>. \n", argv[0]);
        return -1;
    }

    init_modbus(&ctx, argv[1], atoi(argv[2]));

    shm0 = init_shared_memory(&key_shm, &shmid);
    printf("The key(shm): %#x\n", key_shm);
    printf("The shmid: %d\n", shmid);

    init_msg_queue(&key_msg, &msgid);
    msg0.mtype = 250;
    printf("The key(msg): %#x\n", key_msg);
    printf("The msgid: %d\n", msgid);

    pthread_t tid1, tid2;

    if (pthread_create(&tid1, NULL, collector, shm0)) {
   
        perror("Failed to create a thread named collector");
        return -1;
    }

    if (pthread_create(&tid2, NULL, control, msg0.ctl)) {
   
        perror("Failed to create a thread named input");
        return -1;
    }

    pthread_join(tid1, NULL);
    pthread_join(tid2, NULL);

    // shmdt(p);
    // shmctl(shmid, IPC_RMID, NULL);
    // msgctl(msgid, IPC_RMID, NULL);
    modbus_close(ctx);
    modbus_free(ctx);
    return 0;
}

client.h

#ifndef __CLIENT_H_
#define __CLIENT_H_

#include <stdio.h>
#include <modbus.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/shm.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/msg.h>

#define SHM_SIZE 64

struct shm {
   
    uint16_t buf[4];
    // int flag;
};

struct msgbuf {
   
    long mtype;    		/* message type, must be > 0 */
    uint8_t ctl[2]; 	/* message data */
};

int init_modbus(modbus_t **, const char *, int);
struct shm *init_shared_memory(key_t *, int *);
int init_msg_queue(key_t *, int *);

#endif

func.c

#include "client.h"

int init_modbus(modbus_t **ctx, const char *ip, int port) {
   

    *ctx = modbus_new_tcp(ip, port);
    if (*ctx == NULL) {
   
        perror("Failed to modbus_new_tcp");
        return -1;
    }

    if (modbus_set_slave(*ctx, 1) < 0) {
   
        perror("Failed to modbus_set_slave");
        return -2;
    }

    if (modbus_connect(*ctx) < 0) {
   
        perror("Failed to modbus_connect");
        return -3;
    }

    return 0;
}

struct shm *init_shared_memory(key_t *key, int *shmid) {
   
    
    *key = ftok("./client.c", 'v');        // ftok(任意文件名/路径名, 任意字符);
    if (key < 0) {
   
        perror("Failed to ftok");
        return NULL;
    }

    *shmid = shmget(*key, SHM_SIZE, IPC_CREAT | IPC_EXCL | 0666);
    if (*shmid < 0) {
   
        if (errno == EEXIST)
            *shmid = shmget(*key, SHM_SIZE, 0666);
        else {
   
            perror("Failed to shmget");
            return NULL;
        }
    }

    struct shm *p = shmat(*shmid, NULL, 0);     // 0 表示可读可写, 若只读则 SHM_RDONLY
    if (p == (void *)-1) {
   				   		// if (*p == -1) 也可以
        perror("Failed to shmat");
        return NULL;
    }

    return p;
}

int init_msg_queue(key_t *key, int *msgid) {
   

    *key = ftok("./client.h", 'v');
    if (*key < 0){
   
        perror("Failed to ftok");
        return -4;
    }

    *msgid = msgget(*key, IPC_CREAT | IPC_EXCL | 0666);
    if (

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1241578.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ArgoWorkflow教程(一)---DevOps 另一选择?云原生 CICD: ArgoWorkflow 初体验

来自&#xff1a;探索云原生 https://www.lixueduan.com 原文&#xff1a;https://www.lixueduan.com/posts/devops/argo-workflow/01-deploy-argo-workflows/ 本文主要记录了如何在 k8s 上快速部署云原生的工作流引擎 ArgoWorkflow。 ArgoWorkflow 是什么 Argo Workflows 是…

深入理解路由协议:从概念到实践

路由技术是Internet得以持续运转的关键所在&#xff0c;路由是极其有趣而又复杂的课题&#xff0c;永远的话题。 SO&#xff1a;这是一个解析路由协议的基础文章。 目录 前言路由的概念路由协议的分类数据包在网络中的路由过程理解路由表的结构路由器关键功能解析 前言 在互联…

文件差分服务设计

需求 OTA&#xff08;Over-The-Air&#xff09;升级是一种至关重要的技术&#xff0c;用于更新嵌入式设备的固件或软件&#xff0c;以确保设备具备最新功能和修复漏洞。在OTA升级过程中&#xff0c;使用差异算法工具&#xff08;如bsdiff、hdiffpatch和xdelta3&#xff09;能够…

eNSP-直连通信实验

实验拓扑&#xff1a; 实验需求&#xff1a; 1. 按照图中的设备名称&#xff0c;配置各设备名称 2. 按照图中的IP地址规划&#xff0c;配置IP地址 3. 测试R1与R2是否能ping通 4. 测试R2与R3是否能ping通 5. 测试R1与R3是否能ping通 实验步骤&#xff1a; 1. 加入设备&…

2023亚太杯数学建模C题思路 - 我国新能源电动汽车的发展趋势

1 赛题 问题C 我国新能源电动汽车的发展趋势 新能源汽车是指以先进技术原理、新技术、新结构的非常规汽车燃料为动力来源( 非常规汽车燃料指汽油、柴油以外的燃料&#xff09;&#xff0c;将先进技术进行汽车动力控制和驱动相结 合的汽车。新能源汽车主要包括四种类型&#x…

应用带通滤波器进行划痕检测

案例要求&#xff1a; 图为HALCON中的例图“surface_scratch”&#xff0c;请提取出图中的划痕。 案例分析&#xff1a; 图中明亮程度不一&#xff0c;划痕颜色较淡&#xff0c;因此不能用灰度BLOB分析的方法提取出目标区域。因此&#xff0c;先构造一个带通滤波器&#xff0…

Linux编程 文件操作 creat open

文件描述符 文件描述符在形式上是一个非负整数。实际上&#xff0c;它是一个索引值&#xff0c;指向内核为每一个进程所维护的该进程打开文件的记录表。当程序打开一个现有文件或者创建一个新文件时&#xff0c;内核向进程返回一个文件描述符。 启动一个进程之后&#xff0c;…

3.OpenFeign的使用

OpenFeign 文章目录 OpenFeign一. 什么是OpenFeign二. OpenFeign基础使用1.添加依赖2.配置Nacos配置信息3.在项目中开启OpenFeign4.编写OpenFeign调用代码5.调用OpenFeign接口 三. OpenFeign内置的超时重试机制1.配置超时重试2.覆盖Retryer对象 四.自定义超时重试机制1.自定义超…

vue3-生命周期

​&#x1f308;个人主页&#xff1a;前端青山 &#x1f525;系列专栏&#xff1a;Vue篇 &#x1f516;人终将被年少不可得之物困其一生 依旧青山,本期给大家带来vue篇专栏内容:vue3-生命周期 目录 vue3生命周期 vue3生命周期钩子 1.1 onMounted() 1.2 onUpdated() 1.3 onU…

Airtest结合Poco对控件实施精准截图,学起来!

1.前言 最近在Q群内发现有个小伙伴提出了一个很有趣的脚本需求&#xff0c;想要实现“通过选择器获取到了控件&#xff0c;然后截图这个控件范围”&#xff0c;根据我们的Airtest的局部截图接口以及poco控件的属性查询接口是可以很快实现的~ 2.接口查找 首先我们需要知道我们…

什么软件可以做报表?

报表在现代企业和组织中扮演着重要角色。它们是数据汇总、分析和展示的重要工具&#xff0c;为管理层和决策者提供洞察和指导。但是&#xff0c;报表的制作并非易事。使用Excel或手写代码开发报表可能会带来一系列痛点&#xff0c;而现代化的解决方案——比如VeryReport报表软件…

分布式锁之传统锁回顾(一)

1. 传统锁回顾 1.1. 从减库存聊起 多线程并发安全问题最典型的代表就是超卖现象 库存在并发量较大情况下很容易发生超卖现象&#xff0c;一旦发生超卖现象&#xff0c;就会出现多成交了订单而发不了货的情况。 场景&#xff1a; 商品S库存余量为5时&#xff0c;用户A和B同…

智能导视电子指路牌是什么?

SVIP-3800系列智能电子指路牌也称智慧指路灯杆&#xff0c;智能指路牌&#xff0c;导航立柱&#xff0c;多功能指示牌&#xff0c;多功能路标&#xff0c;智能指路机器人&#xff0c;智能导视指路牌&#xff0c;问路导航机器人&#xff0c;智能路牌&#xff0c;叁仟智慧路牌、智…

电商数据采集|电商API接口接入|从京东平台获取商品SKU 主图 价格 详情数据

在进行API开发过程中&#xff0c;数据异常常常令人头痛。我们的API开车软件经过精心设计和测试&#xff0c;能够准确识别并及时处理各类数据异常。拥有稳定的运行环境&#xff0c;保障了您的开发进程不受干扰&#xff0c;让您的工作更加顺畅高效。 京东获得JD商品详情 API 返…

AI助力钢铁产业数字化,python基于YOLOv5开发构建钢铁产业产品智能自动化检测识别系统

AI为工业产业智能化数字化赋能早已不是什么新鲜事&#xff0c;越来越多的行业和领域开始更大范围去拥抱AI&#xff0c;享受科技带来的变革力量&#xff0c;在我们之前的文章中也有很多相关领域项目的实践经历&#xff0c;本文的核心目标就是想要基于钢铁领域产品数据来开发构建…

VirtualBox下win主机如何访问linux虚拟机文件夹

目录 ​编辑 方法1&#xff1a;通过VirtualBox自带的共享文件夹&#xff08;Win->linux&#xff09; 方法2&#xff1a;通过Samba方法本地网络访问(Linux->win) 我使用的VirtualBox版本为7.0.4,主机是Window系统&#xff0c;虚拟机是Linux系统 方法1&#xff1a;通过Vir…

易点易动设备管理系统提升设备能耗管理和设备状态监控效率

如今&#xff0c;能源效率和设备状态监控对于企业来说变得越发重要。传统的设备管理方式往往存在能耗浪费和难以实时监控设备状态的问题。为了解决这些问题&#xff0c;易点易动设备管理系统应运而生。本文将介绍易点易动设备管理系统的功能和优势&#xff0c;以及如何通过它提…

深度学习之六(自编码器--Autoencoder)

概念 自编码器(Autoencoder)是一种神经网络架构,用于无监督学习和数据的降维表示。它由两部分组成:编码器(Encoder)和解码器(Decoder)。 结构: 编码器(Encoder): 接收输入数据并将其压缩为潜在表示(latent representation),通常比输入数据的维度要低。编码器的…

Sam Altman回归OpenAI,新董事会成员曝光!

11月22日下午&#xff0c;OpenAI在社交平台宣布&#xff0c;在原则上已达成协议&#xff0c;让 Sam Altman重返 OpenAI担任首席执行官&#xff0c;并重组董事会。稍后会公布更详细的内容。 初始董事会成员包括前Salesforce联合首席执行官Bret Taylor&#xff08;担任主席&…

【AI读论文】AutoML的8年回顾:分类、综述与趋势

论文标题&#xff1a;Eight years of AutoML: categorisation, review and trends 论文链接&#xff1a;https://link.springer.com/article/10.1007/s10115-023-01935-1 本文主要围绕自动机器学习&#xff08;AutoML&#xff09;展开了系统性的文献综述&#xff0c;总结了该领…