英鹏飞电机相关的资料还是比较难找到,刚好项目有用到,就随便几句在这边说下如何用Modbus通讯的方式来控制电机的。
资源下载:https://download.csdn.net/download/rotion135/89933099
资料包含(通讯文档+文章中提到的程序Demo)
测试的电机型号:TST42-48R
目录
软件界面:
1.通讯默认参数
文档中也有说明
程序中用到的通讯客户端:ModbusClient modbus;
连接的部分代码:
string portName = this.comboBox1.SelectedItem.ToString();
int baudRate = Convert.ToInt32(this.comboBox2.SelectedItem.ToString());
modbus = new ModbusClient(portName);
modbus.Baudrate = baudRate;
modbus.Parity = Parity.None;
modbus.StopBits = StopBits.One;
modbus.Connect();
if (!modbus.Connected)
{
MessageBox.Show("连接失败");
return;
}
我自己封装好的通用型客户端类,支持TCP/RTU
Nuget包引用 LS.Helper Nuget管理器 搜索Rotion就能看到我上传的所有资源包了,欢迎大家下载使用。
2.读取基本数据
这边示例读取的数据有:
电机实时位置、电机实时速度、电机实时电流以及报警状态
还有软件正负限位的读取和设置
具体对应的地址可以查看文档,要区分好单地址(16位)和双地址(32位),高低位等等
下边是读取实时速度和实时电流:
var H19 = new int[2];
lock (_lock)
H19 = modbus.ReadHoldingRegisters(0x0019, 2);
if (H19.Length > 0)
{
this.lb_currentspeed.Text = H19[0].ToString();//电机实时速度
this.lb_currentA.Text = H19[1].ToString();//电机实时电流
}
读取实时位置,双地址-32位 读取两个地址然后进行转换
var 实时位置 = new int[2];
lock (_lock)
实时位置 = modbus.ReadHoldingRegisters(0x0004, 2);
this.lb_实时位置.Text = ModbusClient.ConvertRegistersToInt(实时位置).ToString();
报警状态,要做数值转换:
读取0x00A3地址的值,然后将它转换成2进制,然后再取2进制末尾的4位,那么报警值就对应(0000-1111) 刚好16个数字 0-F 对应列表中的错误类型;
历史报警有需要的也是一样的方式进行截取,再转换;
//报警状态
var Error = new int[1];
lock (_lock)
Error = modbus.ReadHoldingRegisters(0x00A3, 1);
this.lb_error.Text = GetErrorState(Error[0]);
/// <summary>
/// 获取错误信息
/// </summary>
/// <param name="error"></param>
/// <returns></returns>
private string GetErrorState(int error)
{
string msg = "";
try
{
string bin = NumberConvert.DEC_BIN(error);
bin = bin.PadLeft(4, '0');
string bin_error = bin[3].ToString()+ bin[2].ToString() + bin[1].ToString() + bin[0].ToString() ;
int dev_error = NumberConvert.BIN_DEC(bin_error);
switch (dev_error)
{
case 0:
msg = "正常";
break;
case 1:
msg = "电机相位过流";
break;
case 2:
msg = "供电电压过高";
break;
case 3:
msg = "供电电压过低";
break;
case 4:
msg = "电机A相开路";
break;
case 5:
msg = "电机B相开路";
break;
case 6:
msg = "其他报警或位置超差";
break;
case 7:
msg = "内部24V电压偏移";
break;
case 8:
msg = "AI电压错误";
break;
case 9:
msg = "BI电压错误";
break;
case 10:
msg = "编码器错误";
break;
default:
msg=dev_error.ToString();
break;
}
}
catch(Exception ex)
{
}
return msg;
}
软件正负限位也是 32位的:
读取操作:
var PN = new int[8];
lock (_lock)
PN = modbus.ReadHoldingRegisters(0x006E, 4);
//软件正负限位
var s_negative = ModbusClient.ConvertRegistersToInt(new int[] { PN[0], PN[1] });
var s_positive = ModbusClient.ConvertRegistersToInt(new int[] { PN[2], PN[3] });
this.tb_Positivelimit.Text = s_positive.ToString();
this.tb_Negativelimit.Text = s_negative.ToString();
写入操作:
List<int> value = new List<int>();
var p = ModbusClient.ConvertIntToRegisters(positive);
var n = ModbusClient.ConvertIntToRegisters(negative);
value.AddRange(n);
value.AddRange(p);
lock (_lock)
{
modbus.WriteMultipleRegisters(0x006E, value.ToArray());
}
3.电机参数的操作
电机参数,常使用到的就是下列参数,刚好地址是连在一起,就可以多地址读取和多地址写入。
读取操作:
var 电机速度 = new int[4];
lock (_lock)
电机速度=modbus.ReadHoldingRegisters(0x0096, 5);
this.tb_DJ启动速度.Text = 电机速度[0].ToString();
this.tb_DJ停止速度.Text = 电机速度[1].ToString();
this.tb_DJ加速时间.Text = 电机速度[2].ToString();
this.tb_DJ减速时间.Text = 电机速度[3].ToString();
this.tb_DJ运行速度.Text = 电机速度[4].ToString();
写入操作:
List<int> value = new List<int>()
{
Int_启动,Int_停止,Int_加速,Int_减速,Int_运行
};
modbus.WriteMultipleRegisters(0x0096, value.ToArray());
4.正转/反转/启动/停止
这个只用一个地址0x00C8,写不同数值则代表不同的功能,相对简单了
//电机正向运行
if (modbus != null && modbus.Connected)
{
lock (_lock)
{
modbus.WriteSingleRegister(0x00C8, 1);
}
}
//反向运行
if (modbus != null && modbus.Connected)
{
lock (_lock)
{
modbus.WriteSingleRegister(0x00C8, 257);
}
}
//电机停止
if (modbus != null && modbus.Connected)
{
lock (_lock)
{
modbus.WriteSingleRegister(0x00C8, 0);
}
}
//电机急停
if (modbus != null && modbus.Connected)
{
lock (_lock)
{
modbus.WriteSingleRegister(0x00C8, 256);
}
}
5.点动控制
点动控制,也是只使用了一个地址 0x00CA 各个功能是按位拆分进行解析
点动各个位的组装解析:
连续点动要持续的发送指令,Demo中用的线程,鼠标按下启动线程,鼠标抬起则结束线程
下面只介绍正转了,反转则bin[0]=1即可,详情也可以下载程序查看
var s_speed = this.tb_点动速度.Text;
int speed = 0;
if (!int.TryParse(s_speed, out speed))
{
return;
}
speed = MathHelper.NumRange(speed, 0, 511);
var bin = new int[16];
bin[0] = 0;//正转 0 CW 1 CCW
//14-6 速度 0-511
string bin_speed = NumberConvert.DEC_BIN(speed);
bin_speed = bin_speed.PadLeft(9, '0');
int index = 1;
foreach (var s in bin_speed)
{
bin[index] = Convert.ToInt16(s.ToString());
index++;
}
bin[10] = 0;//0减速停止 1立即停止
bin[15] = 1;//0 为停止 1为运行
string bin_value = string.Join("", bin);
int dec_value = NumberConvert.BIN_DEC(bin_value);
_点动中 = true;
Task.Run(() =>
{
while (true)
{
if (!_点动中)
{
return;
}
lock (_lock)
{
modbus.WriteSingleRegister(0x00CA, dec_value);
}
Thread.Sleep(10);
}
});
6.绝对位置
设置当前位置,可以将当前位置标为0位,然后使用绝对位置进行定点运动
//运行到绝对位置
var S_绝对位置 = this.tb_绝对位置.Text;
int Int_绝对位置 = 0;
if (!int.TryParse(S_绝对位置, out Int_绝对位置))
{
return;
}
if (modbus != null && modbus.Connected)
{
lock (_lock)
{
var vlaue = ModbusClient.ConvertIntToRegisters(Int_绝对位置);
modbus.WriteMultipleRegisters(0x00D0, vlaue);
}
}