Arduino读光栅数据
最近在工作中,需要使用光栅尺,但是之前的程序是电气工程师通过PLC控制,然后使用需要使用modbus协议去读取结果,使用相当的不智能,优化的话,那位电气工程师已经离职,没人接手。
为了更好的使用这个光栅尺,我决定自己来优化一下。PLC开发不太懂,但没事,我手头有个空闲的ESP32C3,使用MCU去读个脉冲信号,我觉得问题不大。
在拿到光栅尺,我看了下规格:精度1um,TTL信号输出,一个脉冲的计数为4um,接口为DB9,当然接线与传统的RS232串口定义完全不一样。
这里接线就不做过多的描述,毕竟设备不一样,光栅尺的输出信号分为了A/B/Z,然后我们来看下光栅的A/B信号:
这时候有使用arduino玩过编码器,一看就知道,这不就是编码器,于是顺手把USB逻辑分析仪拿出来,运动一下光栅,看下数据波形,一个波形的时间大约在3-400ms。
于是arduino的开发就简单了,两个pin脚中断触发,然后读编码器一般计数就行了。为了让使用过程中能实现自动上报数据,于是我增加了一个pin脚中断,在上升或者下降触发的时候能自动把计数数据发到串口,这样在到达我需要测试数据的时候,ESP32C3能把数据自动上报。
所以arduino的代码我设计为3块:
1、中断计数、中断上报;
2、串口协议生成;
3、串口数据通讯。
既然已经有了单片机程序,那上位机也必不可少,那就直接简单点,使用C#进行数据开发。
那就直接开发,使用arduino开发虽然不能深入了解单片机的开发精髓,但是我们要的是能拿来直接用。
中断定义:
const int A_pin = 1; // 定义A管脚引脚号
const int B_pin = 2; // 定义B管脚引脚号
const int P_pin = 3;
const int interruptPinA = digitalPinToInterrupt(A_pin);
const int interruptPinB = digitalPinToInterrupt(B_pin);
const int interruptPinP = digitalPinToInterrupt(P_pin);
在初始化中增加代码:
// 设置中断回调函数
attachInterrupt(interruptPinA, countPulseA, CHANGE);
attachInterrupt(interruptPinB, countPulseB, CHANGE);
attachInterrupt(interruptPinP, countPulseP, CHANGE);
中断函数关键代码:
A脚中断部分:
// 在A脉冲中寻找上升沿信号,若A编码器引脚为高电平,
// 若B编码器引脚为低电平,Counter计数+1,否则-1
if (digitalRead(A_pin) == HIGH) {
if (digitalRead(B_pin) == LOW) {
count = count + 1;
}
else {
count = count - 1;
}
}
else // 在A脉冲中寻找下降沿信号
{
if (digitalRead(B_pin) == HIGH) {
count = count + 1;
}
else {
count = count - 1;
}
}
B脚中断部分:
// 在B脉冲中寻找上升沿信号
if (digitalRead(B_pin) == HIGH)
{
if (digitalRead(A_pin) == HIGH) {
count = count + 1;
}
else {
count = count - 1;
}
}
else {
if (digitalRead(A_pin) == LOW) {
count = count + 1;
}
else {
count = count - 1;
}
}
P脚就是自动发送串口数据,协议是自己定义的就不具体描述,基本协议思路:
定义好协议的帧头、流水号、数据长度、数据位、数据内容、校验位以及帧尾,这样基本不会有问题。至于校验,简单的就是累加、或者直接使用现成的校验方式,比如CRC16等。
上位机就简单的使用C#进行数据收发,我选择使用winform进行编写。
当前.net的版本较多,既然支持的直接使用推荐的.net8.0,在.net8.0的环境中是没有serialport控件,需要使用nuget来获取system.io.ports控件:
功能就简洁点,直接获取串口,然后直接读数据内容:
至于功能就基于serialport控件:
搜索本地串口:
cb_comname.Items.Clear();
cb_comname.Items.AddRange(SerialPort.GetPortNames());
if (cb_comname.Items.Count > 0)
{
cb_comname.SelectedIndex = 0;
}
打开串口:
try
{
sp.PortName = comname;
sp.BaudRate = bs;
sp.Open();
isok = sp.IsOpen;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
数据收发:
sp.DataReceived += Sp_DataReceived;
处理事件的函数内容:
int len=sp.BytesToRead;
if (len > 0)
{
byte[] buf=new byte[len];
sp.Read(buf, 0, len);
//处理数据
}
顺便使用了closexml来保存记录的光栅数据,使用起来相当完美,有时间再录制一个视频。
基于 AVR 单片机实现轮胎控制系统的设计方案
轮胎模具用于成型轮胎,其加工质量对轮胎的生产非常重要。为了生产出好的轮胎,必须对轮胎模具加工质量提出高的要求。传统的加工质量检测法主要是靠百分表,人为采集数据后分析得出加工质量报告。这种办法的局限性是需要操作者有一定的工作经验,而且取样过程人为控制,精度受到一定影响。近几年来,轮胎模具工业随着轮胎的大量需求而得到了快速发展,传统的检测方法不能满足市场需求。光栅尺是一种数字位移测量设备,测量范围可达几十米,测量精确在微米级;激光测距仪是一种非接触测量设备,可以对不规则表面的目标位移进行测量,但是测量距离较小。将大范同的光栅尺和非接触测量的激光测距仪结合起来就可以实现对不规则面的目标距离进行测量。将光栅尺读头与激光测距仪固定在机械横梁上,运用步进电机控制横梁的运动,分别对模具不同层面的内径进行测量。
系统采用 AVR 单片机实现控制步进电机和光栅尺数据读取,通过接收上位机的控制命令,AVR 单片机控制步进电机运动,数显表数据和激光控制器位移数据自动经串口发送给上位机,从而完成对模具内径的自动测量。
1 系统组成基于 AVR 的轮胎内径测量系统主要由 AVR 单片机、上位机、光栅尺、数显表、激光测距仪、驱动器、步进电机、电子手轮、行程开关等组成。其功能框图如图 1 所示。
单片机选用的是爱特梅尔公司的 ATmega16;上位机采用研华公司生产的 ARK3360L 工控机,它拥有多个 RS232 接口;激光测距仪采用的是日本基恩士公司的 LK-G85 激光测距传感器和 LK-G3001V 激光测距控制器,其分辨率为 0.1μm,测量范围 -15~+15 mm,测量距离为 80 mm;光栅尺采用广州诺信数字测控设备有限公司的 KA300 型系列光栅位移测量设备,读数由其公司的 SDS6 型数显表实现。最终的内径计算由上位机接收到激光测距仪数据和光栅尺数据后完成。
2 系统功能分析
2.1 模具内径测量方法
轮胎模具置于静止的工作平台之上,旋转测量平台处于工作平台的中心位置,在旋转测量平台上的横梁和立柱可以沿径向和垂直两个方向移动,激光感测头置于测量横粱上。根据轮胎模具的内径不同,沿径向移动测量横梁,将激光感测头移动至测量范围内,即可测得激光感测头至轮胎模具内圆的距离,再通过利用光栅尺测量横梁径向移动的距离,换算出轮胎模具的内径。通过控制电机旋转测量平台,就可以按照节距逐一测量轮胎模具内径,从而得到轮胎模具的圆度。将测量横梁沿立柱垂直移动,就可以测量轮胎模具不同垂向高度的内径,从而得到模具的圆锥度。
测量系统一共有 3 个步进电机控制测量设备沿 3 方向运动;两把光栅尺读取水平和垂直位移数据,还有激光测距仪实现非接触位移测量,其测量结构如图 2 所示。
2.2 测量原理和功能实现
轮胎模具花纹块剖面如图 3 所示:花纹块最上边的是模具胎口,其加工的误差一般较小,选取作为基准。设胎口离花纹块中心线 X1 的距离为 RT,把这个内圈设定为基准圈。轮胎模具内径测量是基于模具胎口半径 RT 已知的前提下,由程序控制整个测量过程。
在保证待测模具的平面度和同心度状态下,调整转动电机和垂直位移电机,使得激光感测头位于被测点上方的已知胎口直径位置。调整水平位移电机,使得激光感测头与胎口被测点的水平距离为 80±0.5 mm,激光传感器在这个距离下测量精度最高。
根据胎口半径 RT 和胎口被测点的激光测距值、水平光栅尺读数,可以得到如下等式:
其中,XL 是激光测距值,XR 是水平光栅尺读数,这两个值可以多次测量取平均,XS 是系统装配和放置待测模具时的固有值,即如图设备中心 X0 离花纹圈中心 X1 的距离,相对于垂直方向的每个被测点而言,XS 在整个测量过程中是不变的,因此可以得到下式:
当测量臂垂直移动至待测模具被测点的垂直位置后,平移激光感测头至距离被测点 80±0.5 mm 处,然后读取被测点的激光测距值 XL’和水平光栅尺读数 XR’,则被测点的半径满足:
只要按照上述方法逐点测量和计算出各个被测点的直径,就可以完成圆度测量了。
在整个测量过程中,由于要避开模具的花纹,因而对测量点有一定的要求。使用 ATmega16 精确控制步进电机运行可以找到待测点,并在此基础上加入手轮控制器微调步进电机找到合适位置后再采集数据,这样就可以对人为设定的测量点进行测量。
2.3 设备的行程控制
在测量设备水平和垂直移动极限位置处放置行程开关来保证运行安全,为了降低成本,通过测量转盘的所有信号没有采用电滑环而使用电缆直接连接。因此设备在旋转时不能总是沿一个方向旋转,否则会扭断电缆。本设计中旋转角度不超过 360°,为了区分旋转的 0°和 36 0°,在测量转盘指定的位置处分别放置两个并排的行程开关。通过判断这两个行程开关动作的先后次序来确定旋转的位置,然后决定可旋转的方向。
3 单片机设计
主要思路:上位机对电机进行测量步骤的控制,通过发送命令使步进电机沿设计思路正确测量数据。而在某些测量点上,需要人工干预时通过转动手轮即可微调电机。而行程开关可以限制机械转动的位置,也可以用于复位设置。
3.1 步进电机的驱动
步进电机的运行要有步进电机驱动器,把控制系统发出的脉冲信号转化为步进电机的角位移。步进电机的转速与脉冲信号频率成正比,步进角度与脉冲数目成正比。步进电机启动时,必须有升速、降速过程,升降速的设计至关重要。如果设计不合适,将引起步进电机的堵转、失步、升降速过程慢等问题。为了实现升降速,用阶梯型频率变化来模拟频率线性变化过程。如图 4 所示。
步进电机脉冲的产生由定时器 1 和定时器 2 实现,ATmega16 控制器接收到上位机的命令后,首先获取需要转动的步数,然后根据相应命令打开相应定时器的计数功能。控制程序中用定时器 1 控制二路脉冲输出,定时器 2 控制一路脉冲输出,从而完成 3 路电机的控制。
定时器 2 使用 CTC 模式,匹配中断使能。通过匹配中断,在 OCR2 端口可以输出脉冲,通过设定寄存器 OCR2 寄存器的值可以改变输山脉冲频率。定时器 1 使用相位与频率修正模式,在不同串口命令下分别设置 ICR1、OCR1A 和 OCR1B 寄存器的值并打开不同的匹配中断,从而可以分别在 OC1A 和 OC1B 端口输出匹配脉冲。其输出频率控制和定时器 2 原理一样,只是还需要改变计数上限值 ICR1。由于 3 路电机不同时运动,因此每次只有一个定时器处于打开状态,其余则需要关闭。
在程序运行中,设置了一个全局变量保存电机运行的步数。在收到上位机的命令后,控制程序首先将该步数写入片内 EEPROM 中再执行。由于 EEPROM 数据掉电不丢失,因此系统掉电后复位时可以从 EEPROM 中取出数据然后执行下一次操作。
3.2 手轮微调控制
手轮的作用主要是实现微调设备找到合适的测量点。电子手轮一共有两路脉冲输出,两路脉冲相位差决定了手轮的旋转方向。手轮的控制采用定时器 0,使用计数模式。定时器 0 没置为 CTC 模式,上升沿触发,OCR0 为 1,计数初始值为 0,中断使能。当外部上升沿触发时计数到 1 时触发中断,在中断子程序里面根据手轮状态产生相应的脉冲输出。
在手轮中断子程序中,首先将计数器自动清零等待下一个手轮脉冲。然后判断正反信号和手轮档位状态,ATmega16 根据状态信息通过延时方法产生一定数量的脉冲控制步进电机。手轮状态共有 Z、Y、X 3 个方向,X1、X10、X100 3 个档位。若手轮在 X 档位则在相应端口(该端口同时也是定时器脉冲输出口)输出一定数目的脉冲。改变延时的大小可以改变输出频率,但是由于延时输出脉冲的最大频率决定于晶振,因此输出脉冲受到一定影响。延迟方法产生的脉冲不能精确控制步进电机的步进角度,但是可以用于微调。
手轮的正反信号通过 D 触发器来判断。将手轮脉冲 A 作为 CLK 信号,脉冲 B 为 CP 信号,复位端和置位端接高电平。当手轮正转时脉冲 A 脉冲与脉冲 B 的相位差为正 90 度,D 触发器输出高电平;若反转 A 脉冲与 B 脉冲的相位差为负 90 度,输出低电平。
3.3 串口模块
上位机和单片机主要采用 UART 异步通信,收发按字节处理。单片机接收上位机命令时采用 UART 查询方法实现数据接收。其通信格式为:起始字+控制字节+步数+结束字,数据使用国际通用标准 ASCII 码格式,如表 1 所示。
设计过程中使用 ICCAVR 编译器编写单片机控制程序,可以使用 atoi 函数将 ASCII 码格式步数转化为整型数据。
相关问答
光栅尺 如何与 单片机 连接?你说的开关型霍尔传感器吧?要看传感器输出电压幅值,如果电压较低,采用比较器放大到单片机电源电压,如果电压较高,采用分压电阻分压至单片机电源电压,如果高...
光栅尺 线序定义和光栅尺怎么接?光栅尺线序定?直接输出4-20mA电流量(或是其他模拟量的),可以在PLC中把他当成模拟量来处理。光栅尺输出A,B,RI三路TTL信号,每路信号驱动能力一般大于10mA。光栅尺的输...