在 两轴机械臂+机械爪整体控制板设计与机械爪控制调试 双轴机械臂的控制中,使用了基于 BH38旋转编码器初步测试 作为两个关节的运动角度测量,但是由于BH38传感器采用了MODBUS协议,所使用的串口波特率(19200)无法改变,致使解读读取的时间大约是10ms(具体读取信号波形参见 BH60绝对位置编码器测试 ),这对于机械臂运动动态调整造成了困难。

  在 闭环步进电机平顺控制算法: 42HS48EIS,57HS 对于角度读取的时间延迟采用了补偿的方法,虽然有一定的效果,但是还是没有被彻底解决控制的平顺问题。

  下面测试ST-3806-15-RS角度传感器,希望解决以下问题:

  • 能够将角度读取的时间缩短到1ms左右;
  • 角度的分辨率提高到15bit。

■ 编码器ST-3806-15-RS


  • 编码器的基本资料参加: ST-3806系列单圈编码器 说明书
  • 对于编码器的测试参见: ST-3806系列单圈编码器 测试说明

1.基本信息

  • 型号:ST-3806-15-RS
  • 工作电压:DC5-24V
  • 接口定义:
红/RD 黑/BK 绿/GN 黄/YE 白/WH
+5~24V 0V 485A+ 485B- SET
  • 出品公司:上海默马科技有限公司

▲ 角度编码器 ST-3806-15-RS

01测试电路板设计


  对于博文中 基于STC8H1K28的双轴机械臂驱动模块 的模块进行修正。在传感器接口处增加一个管脚(设置SET),形成新的传感器读写模块。

  下面对应的电路板设计和软件设计。

1. SCH和PCB1

▲ #zxhn 01测试电路设计

2.软件工程文件2

  单片机的软件工程文件采用与基于STC8H1K28的双轴机械臂驱动模块相同的工程文件进行测试。但是由于原来的模块中存在着旧的代码,程序体积过大,所以建立新的测试软件3

02软件初步调试


1.设置UART2波特率

//------------------------------------------------------------------------------
void SetUART2Baud(unsigned long lnBaud) {unsigned long lnNumber;unsigned int nNumber;lnNumber = OSC_FREQUENCY;lnNumber /= lnBaud * 4;nNumber = 0xffff - (unsigned int)lnNumber;T2H = nNumber >> 8;T2L = nNumber & 0xff;
}

  下面是SetUART2Baud(9600)对应的TXD2的波形。

▲ 波特率=9600的波形

2.ST3806子函数

(1) 设置ST3806波特率

else IFARG0("sb115200") {printf("Set ST3806 baud 115200:\r\n");ON(ST3806_SET1_PIN);WaitTime(3000);OFF(ST3806_SET1_PIN);WaitTime(1000);SetUART2Baud(9600);ucRet = ST3806SetBaud115200();printf("Set Result: %bd\r\n", ucRet);SetUART2Baud(115200);

  请注意,在前面设置波特率前,设置SET管脚为高电平3秒钟,以保证ST3806被初始化为缺省的9600波特率。

  如下是在115200下读写485总线波形。时间长度大约是2.2ms.

▲ 读取数据的485总线波形

(2) 读取ST3806角度

  ST3806的角度值是在寄存器地址00(0x00),前后两个字节(高端字节在前)表示了一个15bit的角度值。

//------------------------------------------------------------------------------
unsigned int ST3806Buffer2Number(void) {unsigned int nNumber;nNumber = g_ucST3806Buffer[3];nNumber = (nNumber << 8) + g_ucST3806Buffer[4];return nNumber;
}//------------------------------------------------------------------------------
unsigned int ST3806ReadNumber(unsigned char ucChannel) {ST3806SetChannel(ucChannel);ST3806ReadData2Buffer();return ST3806Buffer2Number();
}

  在读取时间上,ST3806返回数据的时刻具有某种随机性。这一点在控制方面需要谨慎。

▲ 读取时间的不确定性

  在快速读取的时候,这种结果的返回抖动则更加的明显。结果的抖动时间前后大约1.5ms左右。

▲ 在快速读取的时候,这种结果返回的抖动更加明显

03C51代码


/*
**==============================================================================
** ST3806.C:             -- by Dr. ZhuoQing, 2020-09-14
**
**==============================================================================
*/#include "C51BASIC.H"
#include "STC8H.H"//------------------------------------------------------------------------------
#define ST3806_GLOBALS        1              // Define the global variables
#include "ST3806.H"//------------------------------------------------------------------------------//------------------------------------------------------------------------------
void ST3806Init(unsigned char ucAddress) {OFF(ST3806_DIR1_PIN);PM_PP(ST3806_DIR1_PIN);OFF(ST3806_DIR2_PIN);PM_PP(ST3806_DIR2_PIN);OFF(ST3806_SET1_PIN);PM_PP(ST3806_SET1_PIN);OFF(ST3806_SET2_PIN);PM_PP(ST3806_SET2_PIN);g_ucST3806Address = ucAddress;    g_ucST3806Channel = ST3806_CHANNEL_1;
}//------------------------------------------------------------------------------
void ST3806SetChannel(unsigned char ucChannel) {g_ucST3806Channel = ucChannel;OFF(ST3806_DIR1_PIN);OFF(ST3806_DIR2_PIN);
}void ST3806DirON(void) {if(g_ucST3806Channel == ST3806_CHANNEL_1) {OFF(ST3806_DIR2_PIN);ON(ST3806_DIR1_PIN);} else {OFF(ST3806_DIR1_PIN);ON(ST3806_DIR2_PIN);        }}void ST3806DirOFF(void) {OFF(ST3806_DIR2_PIN);OFF(ST3806_DIR1_PIN);
}//------------------------------------------------------------------------------
unsigned int ModbusCRC(unsigned char * pByte, int nLength) {unsigned int nCRC;unsigned int i;unsigned char ucByte, j;nCRC = 0xffff;for(i = 0; i < nLength; i ++) {ucByte = *(pByte + i);nCRC ^= (unsigned int)ucByte;for(j = 0; j < 8; j ++) {if((nCRC & 0x1) != 0) {nCRC >>= 1;nCRC ^= 0xA001;} else nCRC >>= 1;}        }return nCRC;
}//------------------------------------------------------------------------------
void ST3806AppendCRC(unsigned char ucLength) {unsigned int nCRC;nCRC = ModbusCRC(g_ucST3806Buffer, ucLength);g_ucST3806Buffer[ucLength + 1] = (unsigned char)(nCRC >> 8);g_ucST3806Buffer[ucLength] = (unsigned char)nCRC;
}//------------------------------------------------------------------------------
void ST3806SendBuffer(unsigned char ucLength) {unsigned char i;ST3806AppendCRC(ucLength);ST3806DirON();for(i = 0; i < ucLength + 2; i ++) {UART2SendChar(g_ucST3806Buffer[i]);}ST3806DirOFF();UART2_CLEAR;}//------------------------------------------------------------------------------
unsigned char ST3806SetBaud115200(void) {unsigned char i, c;g_ucST3806Buffer[0] = g_ucST3806Address;g_ucST3806Buffer[1] = 0x10;g_ucST3806Buffer[2] = 0x0;g_ucST3806Buffer[3] = 0x3;g_ucST3806Buffer[4] = 0x0;g_ucST3806Buffer[5] = 0x1;g_ucST3806Buffer[6] = 0x2;g_ucST3806Buffer[7] = 0x0;g_ucST3806Buffer[8] = 0x5;ST3806SendBuffer(9);for(i = 0; i < 100; i ++) {if(UART2ReceChar(&c) == 0) break;}if(i < 100)g_ucST3806Buffer[0] = c;else return 1;
/*        for(i = 1; i < 8; i ++) {if(UART2ReceChar(&c)) return 10+i;g_ucST3806Buffer[i] = c;}
*/   return 0;
}//------------------------------------------------------------------------------
unsigned char ST3806ReadData2Buffer(void) {unsigned char i, c;g_ucST3806Buffer[0] = g_ucST3806Address;g_ucST3806Buffer[1] = 0x3;g_ucST3806Buffer[2] = 0x0;g_ucST3806Buffer[3] = 0x0;g_ucST3806Buffer[4] = 0x0;g_ucST3806Buffer[5] = 0x1;ST3806SendBuffer(6);g_ucST3806Buffer[3] = 0x0;g_ucST3806Buffer[4] = 0x0;g_ucST3806Buffer[5] = 0x0;g_ucST3806Buffer[6] = 0x0;for(i = 0; i < 10; i ++) {if(UART2ReceChar(&c) == 0) break;}if(i < 10)g_ucST3806Buffer[0] = c;else return 1;for(i = 1; i < 9; i ++) {if(UART2ReceChar(&c)) return 1;g_ucST3806Buffer[i] = c;}return 0;}//------------------------------------------------------------------------------
unsigned char ST3806ReadConfig2Buffer(void) {unsigned char i, c;g_ucST3806Buffer[0] = g_ucST3806Address;g_ucST3806Buffer[1] = 0x3;g_ucST3806Buffer[2] = 0x0;g_ucST3806Buffer[3] = 0x0;g_ucST3806Buffer[4] = 0x0;g_ucST3806Buffer[5] = 0x3;ST3806SendBuffer(6);for(i = 0; i < 10; i ++) {if(UART2ReceChar(&c) == 0) break;}if(i < 10)g_ucST3806Buffer[0] = c;else return 1;for(i = 1; i < 11; i ++) {if(UART2ReceChar(&c)) return 1;g_ucST3806Buffer[i] = c;}return 0;
}//------------------------------------------------------------------------------
unsigned int ST3806Buffer2Number(void) {unsigned int nNumber;nNumber = g_ucST3806Buffer[3];nNumber = (nNumber << 8) + g_ucST3806Buffer[4];return nNumber;
}//------------------------------------------------------------------------------
unsigned int ST3806ReadNumber(unsigned char ucChannel) {ST3806SetChannel(ucChannel);ST3806ReadData2Buffer();return ST3806Buffer2Number();
}//==============================================================================
//                END OF THE FILE : ST3806.C
//------------------------------------------------------------------------------
/*
**==============================================================================
** ST3806.H:            -- by Dr. ZhuoQing, 2020-09-14
**
**  Description:
**
**==============================================================================
*/
#ifndef __ST3806__
#define __ST3806__
//------------------------------------------------------------------------------
#ifdef ST3806_GLOBALS#define ST3806_EXT
#else#define ST3806_EXT extern
#endif // ST3806_GLOBALS
//------------------------------------------------------------------------------
//==============================================================================//------------------------------------------------------------------------------//------------------------------------------------------------------------------
#define ST3806_ADDRESS          1
#define ST3806_DIR1_PIN         1, 2
#define ST3806_DIR2_PIN         1, 3
#define ST3806_SET1_PIN         2, 4
#define ST3806_SET2_PIN         2, 3 //==============================================================================
void ST3806Init(unsigned char ucAddress);         // ucAddress: Default is 1#define ST3806_CHANNEL_1        0
#define ST3860_CHANNEL_2        1ST3806_EXT unsigned char g_ucST3806Channel;
void ST3806SetChannel(unsigned char ucChannel);
void ST3806DirON(void);
void ST3806DirOFF(void);//------------------------------------------------------------------------------
#define ST3806_BUFFER     16ST3806_EXT unsigned char xdata g_ucST3806Buffer[ST3806_BUFFER];
ST3806_EXT unsigned char xdata g_ucST3806Address;unsigned int ModbusCRC(unsigned char * pByte, int nLength);
void ST3806AppendCRC(unsigned char ucLength);//------------------------------------------------------------------------------
void ST3806SendCharBuffer(unsigned char ucLength);unsigned char ST3806ReadData2Buffer(void);
unsigned char ST3806ReadConfig2Buffer(void);unsigned int ST3806Buffer2Number(void);//------------------------------------------------------------------------------
unsigned int ST3806ReadNumber(unsigned char ucChannel); // Return about 2ms(&115200bps)unsigned char ST3806SetBaud115200(void);//==============================================================================
//             END OF THE FILE : ST3806.H
//------------------------------------------------------------------------------
#endif // __ST3806__

※ 附录


  ■ 相关文献链接:

  • 两轴机械臂+机械爪整体控制板设计与机械爪控制调试
  • BH38旋转编码器初步测试
  • BH60绝对位置编码器测试
  • 闭环步进电机平顺控制算法: 42HS48EIS,57HS
  • ST-3806系列单圈编码器 说明书
  • ST-3806系列单圈编码器 测试说明
  • 基于STC8H1K28的双轴机械臂驱动模块:步进电机42HS348E,BH32角度传感器

  1. 设计AD工程文件:AD\XQWF\2020\机械臂\CNT2AXESCLAWSTC8H.SchDoc ↩︎

  2. 单片机软件工程文件:C51\STC\Project\XQWF\2020\STC8H2AXES\STC8H2AXES.uvproj ↩︎

  3. 新建的测试C51工程文件:C51\STC\Project\XQWF\2020\TestST3806\TestST3806.uvproj ↩︎

角度编码器 ST-3806-15-RS相关推荐

  1. 微型角度编码器 : KYTB-1503-1024

    简 介: 通过ESP32 对于KYTB角度编码器进行测试,初步验证了KYTB的基本功能.由于ESP32的端口中断具有最大上限频率,通过实验测量到这个频率大约为26kHz. 关键词: 角度编码器,KYT ...

  2. pwm控制舵机转动角度程序_Mixly 第15课 舵机的使用

    第15课  舵机的使用 舵机的旋转不像普通电机那样只是转圈圈,它可以根据你的指令旋转到0至180度之间的任意角度然后精准的停下来.舵机的转动的角度是通过调节PWM(脉冲宽度调制)信号的占空比来实现的. ...

  3. 海德汉角度编码器RCN727F与替代型号RCN8390F参数对比

    广州希洛登自动控制技术有限公司 海德汉圆光栅尺编码器RCN727F是 fanuc系统专用的绝对式编码器 Fanuc02串口孔径有60和100mm2种 电缆有0.5米.1米.3米.5米几大类 精度是2角 ...

  4. HM编码器代码阅读(15)——帧间预测之AMVP模式(三)xGetBlkBits函数

    GetBlkBits函数的主要功能是计算使用某种PU划分模式的时候,该种模式占用的比特数 Void TEncSearch::xGetBlkBits( PartSize eCUMode, Bool bP ...

  5. 计算编码器零点电角度偏移量

    编码器零点电角度偏移量 同步电机的控制,转子的位置是必要的反馈.电机的磁极的换向,控制的是电角度. 编码器的安装和电角度,存在误差. 机械角度的反馈,在多极对数时,需要做一个电角度的转换,进入控制的转 ...

  6. rs=st.executeQuery(sql);报错

    rs=st.executeQuery(sql);一直是红色显示无法解析Statement中的方法excuteQuery package com.dao;import com.Utils.JDBCUti ...

  7. ST-3806系列单圈编码器 说明书

    ▲ 角度编码器 ST-3806-15-RS https://item.taobao.com/item.htm?spm=a1z09.2.0.0.745e2e8dPZ3LXR&id=5928237 ...

  8. 【机器人】从机械臂示教器导出编码器数据到U盘中的操作步骤

    工业机器人 注:这里针对我使用的工业机械臂CRP1410,不同机器人操作方式不完全相同 Question:当机械臂按照运动指令运动后,如何将运动过程中的编码器数据导出到U盘进而在计算机中进行处理呢? ...

  9. 步进电机基础(6.2)-步进电机的特性测量方法-动态特性的测量法和步距角度精度的测量

    步进电机基础(6.2)-步进电机的特性测量方法-动态特性的测量法和步距角度精度的测量 前言 基本信息 前言说明 6.2 动态特性的测量法 1 . 滑轮平衡法 2 . 磁滞制动法 3 . 利用扭力棒转矩 ...

最新文章

  1. python的requests模块功能_《Python数据可视化编程实战》—— 1.7 安装requests模块-阿里云开发者社区...
  2. 为什么我们不应该使用过多的线程
  3. python 正整数 连续多个数之和_vijos - P1302连续自然数和 (公式推导 + python)
  4. python字符串和List:索引值以 0 为开始值,-1 为从末尾的开始位置;值和位置的区别哦...
  5. 编程不仅是写代码!?
  6. 接口进阶 java 1614956772
  7. Java Protected 解读
  8. void main(){char str[] = “\tab\n\014\\\“;printf(“%d“,strlen(str))}
  9. spark记录(7)SparkCore的调优之数据倾斜调优
  10. 区块链 共识算法 分类
  11. Decorator设计模式(装饰)
  12. SC-GlowTTS论文阅读
  13. 喜讯 | 哈特公寓荣誉获最佳新锐公寓奖
  14. 基于lerna重构Concis组件库
  15. [ ERROR ] Suite ‘Test1‘ contains no tests matching tag ‘run‘ and matching name ‘Test1.test2‘ in suit
  16. 下载文件、根据链接生成二维码
  17. win10中文字符乱码解决方案
  18. 输出一句英文话语中的单词数量
  19. Struts2框架简单入门
  20. 御剑系列扫描工具(五款)下载

热门文章

  1. [转]为什么程序员总是写糟糕的代码?这3个原因
  2. iOS开发网络篇—GET请求和POST请求
  3. 排除hotnews主题内容页面上的热点图片推荐里的分类-hotnews主题top_hot.php
  4. EFMVC - ASP.NET MVC 3 and Entity Framework 4.1 Code First 项目介绍
  5. 在.NET 3.5 平台上使用LINQ to SQL创建三层/多层Web应用系统 (Part 1)
  6. Python3.5模块‘OS’‘sys’
  7. webstrom常用键
  8. 开发人员学Linux(4):使用JMeter对网站和数据库进行压力测试
  9. 使用JDBC进行批处理
  10. MyEclipse设置JSP页面默认编码方式