嵌入式开发板RS485多节点串口编程-关节扭矩传感器数据读取
最近学习很忙,主要是准备找工作,有一段时间没有分享,今天和大家分享我最近用的TI AM4376开发板RS485串读取两个关节扭矩传感器的数据,我们的关节扭矩传感器用于外骨骼机器人。以后我也会和大家分享我最近找工作的经历,主要包括笔试和面试的准备,希望能准备找工作的应届毕业生有所帮助。
一、RS485通信协议原理
面试南京国电自动化之前,面试官问了串口和总线通信协议,所以如果打算找嵌入式相关工作,一定要做好充分的准备。今天我们就详细介绍一下RS通信协议485。
1、RS485与RS232的异同
首先是逻辑电平的差异,RS逻辑正电平为-332-逻辑负电平为15 3 15,而RS485逻辑正电平 2 6V,,负电平在-2-6V,和RS232是相反的。
二是工作方式不同,RS232是全双工,可同时进行发送和接收RS485是半双工,发送和接收不能同时进行。
2、RS485能挂多少节点?
RS485最多可外接32个设备,CAN传统节点可外接110个节点RS232只允许一对一通信,但使用modbus协议可以外接多个设备,
二、关节扭矩传感器
1、通讯机制
在RS在485总线通信网络中,上级系统为主要设备(调度端),各扭矩传感器为从设备(调度端)。采用轮询响应通信机制,即从主设备发送命令帧,从设备收到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位 | 无符号整型 | 01H | 01H工作指令 |
6 | 数据长度 | 8位 | 无符号整型 | 0EH | 1个字节 |
7 | 传感器地址 | 8位 | 无符号整型 | [0,FFH] | 原始设备ID |
8 | 设置地址 | 8位 | 无符号整型 | [0,FFH] | 更新后设备ID |
9 | CRC16校验 | 8位 | 无符号整型 | [0,FFH] | CRC16高位 |
10 | CRC16校验 | 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位 | 无符号整型 | 03H | 03H—读取力矩值 | |
6 | 数据长度 | 8位 | 无符号整型 | 0EH | 1个字节 | |
7 | 设备ID | 8位 | 无符号整型 | [0,FFH] | ||
8 | 保留位 | 8位 | 无符号整型 | [0,00H] | 保留 | |
9 | CRC校验 | 8位 | 无符号整型 | [0,FFH] | CRC16高位 | |
10 | CRC校验 | 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、力矩传感器数据读取
下表为力矩传感器返回的数据格式:
8~9 | 传感器数据 | SNS_data | 16位 | 有符号浮点数(保留一位小数) | [-300,300] | Nm | 0.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中编译程序并下载到开发板中:
运行结果如下:
完整源码我放在公众号河边小乌龟爬中了,需要的自取,回复<关节力矩传感器数据读取>即可获得。
我是河边小乌龟爬,学习嵌入式软件开发路上的一名小学生,欢迎大家相互交流哇。公众号:河边小乌龟爬。