嵌入式开发板RS485多节点串口编程——关节力矩传感器数据读取

本文介绍了使用嵌入式开发板通过RS485通信协议读取关节力矩传感器数据的过程,包括RS485通信协议原理、传感器通讯机制和力矩值读取步骤,以及实际的测试程序。文章强调了在嵌入式工作中串口通信的重要性,并提供了代码示例。
摘要由CSDN通过智能技术生成

嵌入式开发板RS485多节点串口编程——关节力矩传感器数据读取

最近学业繁忙,主要是准备找工作,有一段时间没分享了,今天给大家分享一下我最近利用TI AM4376开发板RS485串口读取两个关节力矩传感器的数据,我们这个关节力矩传感器用在外骨骼机器人上。后面我也会将我最近找工作的经历分享给大家,主要包括笔试、面试的准备,希望能给正在准备找工作的应届生一些帮助。

一、RS485通信协议原理

之前面试国电南京自动化时,面试官就问了有关串口和总线通信协议的问题,所以如果你是打算找嵌入式相关的工作,这方面一定要准备充分。今天我们先详细介绍一下RS485的通信协议。

1、RS485与RS232的异同

首先是逻辑电平的不同,RS232的逻辑正电平是-3-15,逻辑负电平为+3+15,而RS485的逻辑正电平+2+6V,,负电平在-2-6V,和RS232是相反的。

其次是工作方式不同,RS232是全双工,发送和接收可以同时进行,而RS485是半双工,发送和接收不能同时进行。

2、RS485可以挂载多少个节点

RS485可以外接最多32个设备,CAN可以外接110个节点,传统RS232只允许一对一的通信,不过利用modbus协议可以外接多个设备,

二、关节力矩传感器

1、通讯机制

在RS485总线通讯网络中,上级系统为主设备(调度端),各力矩传感器为从设备(被调度端)。采用轮询应答通讯机制,即:由主设备向从设备发送命令帧,从设备收到与其ID相对应的指令后才能进行响应,并向主设备发送当前工作状态数据。从设备在没有收到主设备数据帧或ID不符的情况下维持当前状态不变。默认id:01

各力矩传感器的超时判断时间为主设备发出指令后0.5ms。

2、写设备地址

因为我们要与两个设备节点通信,所以要区分两个出厂设备,通过写设备地址通信协议,改变关节力矩传感器的设备地址,这样我们以后发送数据和接收数据的时候就会以设备地址为校验,01设备只接收地址位为01的数据,02设备只接收地址位位02的数据。

下表展示的就是写地址指令,我们只需要修改第八个字节,即设置地址字节,一个设备设置为01,也就是默认的,另一个设置成02,这样就区分了两个设备。

字节 序号信号名称字长数据类型内容备注
1帧头8位无符号整型AAH
2帧头8位无符号整型BBH
3帧头8位无符号整型CCH
4帧头8位无符号整型DDH
5命令标识8位无符号整型01H01H工作指令
6数据长度8位无符号整型0EH1个字节
7传感器地址8位无符号整型[0,FFH]原始设备ID
8设置地址8位无符号整型[0,FFH]更新后设备ID
9CRC16校验8位无符号整型[0,FFH]CRC16高位
10CRC16校验8位无符号整型[0,FFH]CRC16低位
11帧尾8位无符号整型DDH
12帧尾8位无符号整型CCH
13帧尾8位无符号整型BBH
14帧尾8位无符号整型AAH
3、力矩值读取

下表为力矩值读取协议:

字节序号信号名称字长数据类型内容备注
1帧头8位无符号整型AAH
2帧头8位无符号整型BBH
3帧头8位无符号整型CCH
4帧头8位无符号整型DDH
5指令字8位无符号整型03H03H—读取力矩值
6数据长度8位无符号整型0EH1个字节
7设备ID8位无符号整型[0,FFH]
8保留位8位无符号整型[0,00H]保留
9CRC校验8位无符号整型[0,FFH]CRC16高位
10CRC校验8位无符号整型[0,FFH]CRC16低位
11帧尾8位无符号整型DDH
12帧尾8位无符号整型CCH
13帧尾8位无符号整型BBH
14帧尾8位无符号整型AAH

根据上面我们设置的地址,我们要下发的指令即为:

	static char byteSend1[14];
    static char byteSend2[14];
	byteSend1[0] = 0xAA;
	byteSend1[1] = 0xBB;
	byteSend1[2] = 0xCC;
	byteSend1[3] = 0xDD;
	byteSend1[4] = 0x03;
	byteSend1[5] = 0x0E;
	byteSend1[6] = 0x01;//关节1设备地址
	byteSend1[7] = 0;
    byteSend1[8] = 0xAE;
    byteSend1[9] = 0xB3;
    byteSend1[10] = 0xDD;
    byteSend1[11] = 0xCC;
    byteSend1[12] = 0xBB;
    byteSend1[13] = 0xAA;

	byteSend2[0] = 0xAA;
	byteSend2[1] = 0xBB;
	byteSend2[2] = 0xCC;
	byteSend2[3] = 0xDD;
	byteSend2[4] = 0x03;
	byteSend2[5] = 0x0E;
	byteSend2[6] = 0x02;//关节2设备地址
	byteSend2[7] = 0;
    byteSend2[8] = 0xA4;
    byteSend2[9] = 0xB3;
    byteSend2[10] = 0xDD;
    byteSend2[11] = 0xCC;
    byteSend2[12] = 0xBB;
    byteSend2[13] = 0xAA;
4、力矩传感器数据读取

下表为力矩传感器返回的数据格式:

字节 序号信号名称标识字长数据类型内容单位LSB****接口当量备注
8~9传感器数据SNS_data16位有符号浮点数(保留一位小数)[-300,300]Nm0.01传感器输出范围为-300.0~300.0Nm

举例:传感器返回数据:AA BB CC DD 33 0F 01 09 23 64 DD CC BB AA。AA BB CC DD帧头;0F 数据长度4位,为33 01 23 09;33读取力矩成功;01为传感器ID;09 23为力矩数据,高位在前低位在后,16位整形表示为0923H,转换为10进制为2339/10,力矩值为233.9Nm。传感器数据为F756时,高位在前低位在后,16位整形表示为F756H,转换为10进制为-2217/10,力矩值为-221.7Nm。

三、测试程序

因为整个代码比较多,这里我只将主程序中的指令下发和接收贴上来,完整的代码我会放在公众号中:河边小乌龟爬,回复<关节力矩传感器数据读取>即可获取。

这里为了为了清楚的表示下发和接收过程,我没有写成函数接口的形式,按照代码的可读性来说,这样的代码可读性较差,优化就交给你们了。

	while (1)
	{
		while(flag == 0 && flag1 == 0){
			if(i > 13){
				flag = 1;
				i = 0;
				break;
			}
			context = byteSend[i];
			iRet = write(fd, &context, sizeof(context));
			i++;
		}
		bzero(r_buf, 15);
		while(flag == 1&& flag1 == 0){
			//读传感器发送过来的数据,并解析处理
			if(j > 14){
				flag = 0;
                j = 0;
                flag1 = 1;
				break;
			}
			iRet = read(fd, &readtext, sizeof(readtext));
			r_buf[j] = readtext;
			//printf("read:%02x\n", r_buf[j]);
			j++;
                                                
		}
        usleep(10000);
        while(flag == 0 && flag1 == 1){
			if(i > 13){
				flag = 1;
				i = 0;
				break;
			}
			context = byteSend2[i];
			iRet = write(fd, &context, sizeof(context));
			i++;
		}
		bzero(r_buf2, 15);
		while(flag == 1&& flag1 == 1){
			//读传感器发送过来的数据,并解析处理
			if(j > 14){
				flag = 0;
                j = 0;
                flag1 = 0;
				break;
			}
			iRet = read(fd, &readtext, sizeof(readtext));
			r_buf2[j] = readtext;
			//printf("read:%02x\n", r_buf[j]);
			j++;                                     
		}
		if(r_buf[0] == 0xAA && r_buf[1] == 0xBB){
			printf("this joint 1 POS:%7.3f\n", ((float)((r_buf[7]<<8) | r_buf[8])/100));		
		}
		if(r_buf2[0] == 0xAA && r_buf2[1] == 0xBB){
			printf("this joint 2 POS:%7.3f\n", ((float)((r_buf2[7]<<8) | r_buf2[8])/100));		
		}
	}

在ubantu中编译程序并下载到开发板中:

image-20220612143058057

运行结果如下:

image-20220612143257604

完整源码我放在公众号河边小乌龟爬中了,需要的自取,回复<关节力矩传感器数据读取>即可获得。

我是河边小乌龟爬,学习嵌入式软件开发路上的一名小学生,欢迎大家相互交流哇。公众号:河边小乌龟爬。

团队提供丰富嵌入式项目学习,以及嵌入式方向毕业设计指导,欢迎咨询。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

河边小乌龟爬

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值