盈动线性绝对值编码器(光栅尺)的测试记录

这款盈动的线性绝对值编码器型号为: CAPLIN-A-485

其安装好光栅尺后的外型下面这样的.

工作的时候,信号端子和光栅尺是固定的, 滑头由电机带动.

编码器数据由485口主动抛出, IPC可以在适当时机读取.

这款产品的通讯格式如下:

默认的波特率为9600,每桢起始位为0,数据位8位,停止位1位,没有校验和。
一串完整的数据以“55 AA”或者“AA 55”开头(每传输一次绝
对位置交替一次),跟着4桢为绝对值位置,例如:
“55 AA + XX XX XX XX”->”AA 55+XX XX XX XX”->”55 AA+ XX XX
XX XX”->”AA 55+XX XX XX XX”……..
注:XX为绝对位置数据

传输上来的 32 位数据
(1) 低 20 位为 4mm 细分位置, 满量程对应 4mm 长度,最小精
度物理长度是(4mm/4096)。
(2)高 12 位为 4mm 累加位置,其最低位对应的物理长度为4mm.
如下:
‘’ AAAA-AAAA-AAAA’’+’’XXXX-XXXX-XXXX-NNNN-NNNN’’

解析可以直接用’’ AAAA-AAAA-AAAA-XXXX-XXXX-XXXX’高24 位化为十进制,如上个例子化为十进制得 232315,则所对应的绝对位置为(232315/4096)*4mm=226.870mm。

笔者通过串口助手采集了一段数据,如下:

AA 55 00 05 19 E3 55 AA 00 05 19 E3 AA 55 00 05 19 E3 55 AA 00 05 19 E3 AA 55 00 05 19 E3 55 AA 00 05 19 E3 AA 55 00 05 19 E3 55 AA 00 05 19 E3 AA 55

标红字符之间的就是我们要得到的数据.

笔者写了一个光栅尺的类,  你只需要适时读取这个类的Curposition属性即可得到当前的光栅尺读数.

 1   class GratingRuler:SerialPort
 2     {
 3         private Timer t1;
 4         private double curPosition;
 5         public double CurPosition
 6         {
 7             get
 8             {
 9                 return curPosition;
10             }
11         }
12         private IList<byte> readBuff;
13         public GratingRuler()
14         {
15             try
16             {
17                 this.PortName = "COM4";
18                 this.BaudRate = 9600;
19                 this.DataBits = 8;
20                 this.StopBits = StopBits.One;
21                 this.Parity = Parity.None;
22                 readBuff = new List<byte>();
23                 this.ReadBufferSize = 1024;
24                 this.Open();
25             }
26             catch (Exception e1)
27             {
28                 throw e1;
29             }
30
31             t1 = new Timer(
32                 new TimerCallback( readRulerValue),
33                 null,0,100);
34         }
35
36         private void readRulerValue(object a)
37         {
38             double res = 0.0f;
39             List<byte> dataBuff = new List<byte>();
40             byte[] sbyteAry = new byte[1024];
41             var cary = this.Read(sbyteAry, 0, this.ReadBufferSize);
42             for (int i = sbyteAry.Length - 1; i > 0; i--)
43             {
44                 if ((sbyteAry[i] == 0xAA && sbyteAry[i - 1] == 0x55) ||
45                     (sbyteAry[i] == 0x55 && sbyteAry[i - 1] == 0xAA))
46                 {
47                     dataBuff.Add(sbyteAry[i - 2]);
48                     dataBuff.Add(sbyteAry[i - 3]);
49                     dataBuff.Add(sbyteAry[i - 4]);
50                     dataBuff.Add(sbyteAry[i - 5]);
51                     res = getvalue(dataBuff);
52                     this.DiscardOutBuffer();
53                     dataBuff.Clear();
54                     break;
55                 }
56             }
57             curPosition = res;
58         }
59
60         private double getvalue(List<byte> dataBuff)
61         {
62             Int32 v= BitConverter.ToInt32(dataBuff.ToArray(), 0);
63             string s = Convert.ToString(v, 2);
64             s = s.PadLeft(32, ‘0‘);
65             double g12 = Convert.ToInt32(s.Substring(32 - 12, 12), 2);
66             double d20 = Convert.ToInt32(s.Substring(8, 12), 2);
67             double res1 = g12 * 4 + (d20 / 4069) * 4;
68             var ss1 = s.Substring(32 - 24, 24);
69             double res2= ((double)(Convert.ToInt32(s.Substring(32-24, 24), 2)) / 4096) * 4;
70             return res2;
71         }
72
73
74     }

注意下面的代码中, 提取了0xAA,0x55或者0x55,0xAA之间的数据, 还需要按计算机内存字节顺序(高位在后,低位在前) 排列一下, 才可以解释为正确正确的32位数字.

如下面代码中按5,4,3,2的顺序重排列了一次.

 if ((sbyteAry[i] == 0xAA && sbyteAry[i - 1] == 0x55) ||
                    (sbyteAry[i] == 0x55 && sbyteAry[i - 1] == 0xAA))
                {
                    dataBuff.Add(sbyteAry[i - 2]);
                    dataBuff.Add(sbyteAry[i - 3]);
                    dataBuff.Add(sbyteAry[i - 4]);
                    dataBuff.Add(sbyteAry[i - 5]);
                    res = getvalue(dataBuff);
                    this.DiscardOutBuffer();
                    dataBuff.Clear();
                    break;
                }

下面的代码把这4个字节的内容拼成32位数,并且按照此款编码器的通讯格式解析出最终的位置值, 单位mm

private double getvalue(List<byte> dataBuff)
        {
            Int32 v= BitConverter.ToInt32(dataBuff.ToArray(), 0);
            string s = Convert.ToString(v, 2);
            s = s.PadLeft(32, ‘0‘);
            double g12 = Convert.ToInt32(s.Substring(32 - 12, 12), 2);
            double d20 = Convert.ToInt32(s.Substring(8, 12), 2);
            double res1 = g12 * 4 + (d20 / 4069) * 4;
            var ss1 = s.Substring(32 - 24, 24);
            double res2= ((double)(Convert.ToInt32(s.Substring(32-24, 24), 2)) / 4096) * 4;
            return res2;
        }

上面笔者用串口助手抓取的数据为:

00 05 19 E3

按上面的代码, 解析出来位置值为: 326.4716796mm

朋友们可以把这个结果数据代入代码中验证一下, 就能很快明白了.

这个类中,有几点经验需要记录一下:

1. 不要在DataReceived事件中取得串口读数, 因为编码器会不断丢数据过来, 这个事件会不断触发.

正确的做法是在需要的时候, 才去读一下当前串口缓冲区中的数据, 然后立刻丢弃缓冲区中的数据.

2. 不要把"取当前编码器的值" 这个功能设计成一个包含串口读取动作的函数,

因为调用者可能会在多个线程中同时调这个功能, 或者在循环中高速调用这个功能. 这样会造成串口无法响应这种并行处理或者高速的请求.

正确的做法是在类中以私有方法按一定速度以单线程读取当前的串口数据. 对外部公开一个属性, 供调用者读取当前编码器的值. 在本类中, 是在一个内部独立的线程中以一定速度持续读取串口数据的, 对外则公开一个属性curPosition

对这款产品的使用感觉

1. 滑动读头距离光栅尺的距离, 以及平行关系. 还有光栅尺贴的时候的平整性, 都会影响读数的精准度.  可以说是安装的时候要小心翼翼, 是个细活.

2. 目前见到最好的精度是在小数点后第3位跳动, 也就是um级别. 但是仍然发现在同一位置,有时候有可能跳出一个很小的值来, 然后又恢复正常. 感觉如果是高速运动需要时实反馈时, 这东西有些让人担心. 如果在运动后,静止下来测量走了多远, 还是可以的.

3. 如果你设备冷启动上电后, 有时候你不动一下滑头, 读出来的数值为0, 动一下后, 编码器又"活"过来了, 开始持续有数据发出来.

4. 见过的一个最严重的问题是: 有一天突然发现所有数值被加上了9000, 即昨天还在531的位置, 今天变成了9531了, 就好像是数据被累计了一样. 这个情况是在使用了一个月后突然出现的. 厂家认为我们是程序有问题. 但显然不是, 因为之前跑了那么久都是好的.  后来我发现断掉设备所有的电源后, 再开又好了. 真是不得其解.

由于测试工程是用于验证另一个项目, 本编码器光栅尺只是其中的一个元件, 所以我就不把原代码发出来了.

时间: 2024-10-16 08:46:36

盈动线性绝对值编码器(光栅尺)的测试记录的相关文章

光栅尺与PLC的配合使用

http://www.ymmfa.com/read-gktid-1644629.html 在论坛上看到有人提出光栅尺与PLC如何配套使用的问题.结合本人使用过光栅尺的经历,写了这篇文章.希望能提供有用的参考. 一.结构和工作原理 光栅尺由有标尺光栅(尺体)和读数头两部分组成.尺体装在移动部件上,读数头装在固定部件上.也有人把读数头装在移动部件上(针对尺体移动不方便的情况),测量效果是一样的,不一样的是信号线移动不方便. 尺体移动就是一对光栅中的主光栅(标尺光栅)和副光栅(指示光栅)进行相对位移,

Simotion 绝对值编码器使用外部开关回零

转Simotion 绝对值编码器使用外部开关回零 问题来源: 西门子的1FK7二代电机,目前已经没有增量编码器.标准的编码器选项是单圈绝对值,或多圈绝对值.在某些应用中,如印刷机的版辊.模切轴.飞剪电机等,需要使用外部开关来回零.下文描述了使用外部开关回零所需要的步骤. 1 在轴的编码器设置中,将单圈绝对值编码器配置为增量方式.只有增量编码器才可以选择主动回零选项“Active homing”. 2 在S120驱动参数P495中,设置使用外部开关代替电机零脉冲.只能使用快速输入点DI8~DI15

Asp.net与Flex交互测试记录

一.利用asp.net为Flex提供数据服务,flex为前端表现. 二.flex通过三种方式四种代码实现来取数据.分别为     HttpService. WebService. RemoteObject. RemoteObjectAMF0. 三.Project文件夹中的 Vs2010Service提供HttpService.Webservice服务:         Vs2008RemoteObject提供RemoteObject服务. 四.FluorineFx.NET+RemoteObjec

redis window 安装测试--记录

1.下载地址https://github.com/dmajkic/redis/downloads 2.打开一个cmd窗口,使用cd命令切换到指定目录(D:\redis\64bit)运行 redis-server.exe redis.conf . 3.在开一个cmd(D:\redis\64bit)  运行 redis-cli.exe -h 127.0.0.1 -p 6379,其中 127.0.0.1是本地ip,6379是redis服务端的默认端口 4. 测试: set test "11111111

达梦数据库的TPCC测试记录

达梦数据库的TPCC测试记录 测试环境本文主要目的是介绍使用 benchmarksql工具进行 TPCC 测试的步骤使用工具版本:benchmarksql-4.1.1 服务器:华为泰山v1CPU:海思1616 32核x2;内存:192G;硬盘:1.2Tx5系统:中标麒麟 release V7Update6/(Chromium)-aarch64 1.上传数据库的驱动包jar文件上传目录:/home/setup/tpcc/benchmarksql-4.1.1/lib/ 2.初始化相关配置1.创建测试

iOS / OXS LeanCloud云存储方案简单测试记录

说明 LeanCloud是我目前认定的非常适合于小型网络手机游戏开发,特别是小型创建业者团队进行网络游戏开发的优秀云存储方案.为此,我先后在Node.js环境.Android环境和iOS在进行了测试调试,感觉非常满意,当然少量数据的测试并不代表真实环境的海量数据测试,仅供参考而已.以下简要记录了在iOS环境下对于LeanCloud提供的云存储服务测试情况,以及个别特殊情况的记录. 记录备案 我是严格安装https://leancloud.cn/docs/sdk_setup-ios.html处pn

入门级----测试的执行、环境的搭建、每日构建、测试记录和跟踪、回归测试、测试总结和报告

测试用例的准备,都是为了执行测试准备的. 测试环境的搭建 (1)测试数据:有些测试需要使用大批量的数据,例如容量测试.压力测试等.根据产品的具体测试要求,可能需要在数据库表插入大量的数据,准备大量的文件,生成大量的Socket包等. (2)有些测试需要专门的外部硬件设备,比如打印机,条码识别器,读卡机,指纹仪等.  如果是手机应用测试,可能要把所有支持的型号的手机都准备好.这些设备有些可以使用模拟器来模拟,有些则不能.模拟器比如夜神安卓模拟器.经常遇到在手机模拟器上可以执行的程序,在真正的手机上

LeanCloud C++ SDK安装测试记录

LeanCloud C++ SDK以开源方式作为githum项目存在,地址是:https://github.com/leancloud/cpp-sdk. 此SDK的主要目的是为以Cocos2d-X为代表的C++开发框架提供支持.因为本人主要使用Cocos2d-X C++开发手机游戏,同时又想测试leancould的云存储支持技术,所以选择了LeanCloud C++ SDK. 此SDK不同于leancloud其他官方SDK,操作略有些麻烦,但也不尽然.以下是本人根据上面开源项目中提供的安装指南操

BadUSB测试记录

0x00 前言 不是很新的东西,其他作者已对此做过研究测试,本文仅用来记录操作过程,保存日志,说明细节. 0x01参考资料 https://github.com/adamcaudill/Psychson https://github.com/hak5darren/USB-Rubber-Ducky/wiki/Payloads http://zone.wooyun.org/content/20001 0x02环境搭建 1.硬件 U盘 :东芝(TOSHIBA) 速闪系列 U盘 16GB (黑色) US