Unity对接轨道屏ModBus步骤:
将NModbus4.dll导入到Unity的Plugin下
NModbus4.dll百度网盘下载地址
链接:https://pan.baidu.com/s/1wAFljFuGdpCUGgb8-7gRSA?pwd=y38v
提取码:y38v
- 连接串口!
- 调用OpenSerial方法进行连接。
- 在开启Unity项目时,如果轨道是断电重启的,就需要重新给轨道设置初始位置。
- 首先要请求回参,向左复位或者向右复位,复位到限位器位置
- 需要一直读取寄存器状态,直到SQ1电平(右)或SQ2电平(左)的值为0时,是到达限位器位置 (0=>到限位 1=>未到限位)
- 到达限位器后需要向左或者向右移动30个脉冲,也就是差不多10毫米左右
- 移动完成后将轨道现在的位置设置为0
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using Modbus.Device;
using System.Threading;
namespace Modbus485
{
class MotorCtrl
{
enum MDRESULT
{
MDERR_SUCCESS, // 成功
/*以下为MODBUS错误*/
MDERR_FUNC = 0x01, // 无效功能码
MDERR_ADDR, // 无效寄存器地址
MDERR_VALUE, // 无效寄存器数据
MDERR_FAIL, // 操作失败
MDERR_ENSURE, // 请求已被确认
MDERR_BUSY, // 设备忙
MDERR_PARITY = 0x08, // 奇偶检验错误
MDERR_BADGATEWAY = 0x0a, // 不可用的网关路径
MDERR_GATEWAYERR, // 网关目标设备响应失败
/*以下为扩展错误*/
MDERR_FORBIDDEN = 0x40, // 禁止操作
MDERR_NOTSTUDY = 0x60, // 尚未学习
MDERR_NOTOPEN = 0x80, // 串口未打开
MDERR_COMM, // 通讯错误 (从机返回的地址或响应命令不一致)
MDERR_TIMEOUT, // 操作超时
MDERR_BUFFER, // 数据长度超出缓冲区的容量
MDERR_UNDEF = 0xff // 未定义错误
}
public struct RTSTATUS
{
public short nPWM; // PWM
public ushort nAmp; // 电机电流 电流值的1/10 单位mA
public short nPhaseFreq; // 换向频率
public ushort nFinishSta; // 完成状态
public ushort nPhasePosHi; // 脉冲数高半字
public ushort nPhasePosLo; // 脉冲数低半字
public ushort nLeftTimeHi; // 完成时间高半字
public ushort nLeftTimeLo; // 完成时间低半字
public short nIN1Voltage; // AI1电压 电压值的1/10 单位mV
public short nIN2Voltage; // AI2电压 电压值的1/10 单位mV
public short nIN3Voltage; // AI2电压 电压值的1/10 单位mV
public short nDiffVoltage; // 差分电压
public ushort bSQ1Level; // SQ1电平 右 0(到限位)/ 1(未到限位)
public ushort bSQ2Level; // SQ2电平 左 0(到限位)/ 1(未到限位)
public ushort nInPWM; // 输入PWM
public short nInFreq; // 输入频率
public ushort nInPulseHi; // 输入脉冲高半字
public ushort nInPulseLo; // 输入脉冲低半字
public ushort nLockSta; // 堵转状态
public ushort nErrorSta; // 错误状态
public ushort nMotorSpd; // 电机转速
public ushort bSpdDiv10; // 转速是除以10的
public ushort bSpdMulti; // 转速量程乘以10
public short nTemperature; // 温度
public ushort nPowerVoltage; // 电源电压
}
RTSTATUS rtstatus = new RTSTATUS();
/// <summary>
/// 私有串口实例
/// </summary>
public SerialPort serialPort = new SerialPort();
/// <summary>
/// 私有ModbusRTU主站字段
/// </summary>
public static IModbusMaster master;
/// <summary>
/// 打开串口
/// </summary>
/// <param name="_COM">端口</param>
/// <param name="_BaudRate">波特率</param>
/// <param name="_Parity">奇偶校验</param>
/// <param name="_DataBits">数据位</param>
/// <param name="_StopBits">停止位</param>
public bool OpenSerial(string _COM, int _BaudRate = 115200, Parity _Parity = Parity.Even, int _DataBits = 8, StopBits _StopBits = StopBits.One)
{
try
{
//设定串口参数
serialPort.PortName = _COM;
serialPort.BaudRate = _BaudRate;
serialPort.Parity = _Parity;
serialPort.DataBits = _DataBits;
serialPort.StopBits = _StopBits;
//创建ModbusRTU主站实例
master = ModbusSerialMaster.CreateRtu(serialPort);
//打开串口
if (!serialPort.IsOpen) serialPort.Open();
master.Transport.Retries = 0;
master.Transport.ReadTimeout = 200;
master.Transport.WriteTimeout = 200;
return true;
}
catch (Exception)
{
return false;
}
//关闭串口
//serialPort.Close();
}
public void CloseSerial()
{
//if (serialPort.IsOpen)
serialPort.Close();
}
/// <summary>
/// 判断是否打开
/// </summary>
/// <returns></returns>
public bool isOpen()
{
return serialPort.IsOpen;
}
/// <summary>
/// 复位!
/// </summary>
/// <param name="addr"></param>
/// <param name="mode">3 向左</param>
public void Ref(byte addr, ushort mode = 3)
{
master.WriteSingleRegister(addr, 0xaa, mode);
}
/// <summary>
/// 设置位置为0
/// </summary>
/// <param name="addr"></param>
public void Set0(byte addr)
{
master.WriteSingleRegister(addr, 0x700a, 1);
}
/// <summary>
/// 向右移动
/// </summary>
public void MoveRight(byte addr, ushort speed)
{
master.WriteSingleRegister(addr, 0x43, speed);
}
/// <summary>
/// 向左移动
/// </summary>
public void MoveLeft(byte addr, ushort speed)
{
master.WriteSingleRegister(addr, 0x43, (ushort)-speed);
}
/// <summary>
/// 停止
/// </summary>
public void MoveStop(byte addr)
{
master.WriteSingleRegister(addr, 0x40, 0);
}
/// <summary>
/// 移动到指定位置
/// </summary>
public void MoveGo(byte addr, ushort speed, int targetPos)
{
int setPos = targetPos * 240 / 95;
SetPosition(addr, speed, (ushort)setPos);
}
private void SetPosition(byte addr, ushort speed, ushort value, int bRelative = 0)
{
ushort[] wSpd = new ushort[4];
wSpd[0] = speed; // 速度
wSpd[1] = (ushort)bRelative;// 是否为相对位置, 0: 相对, 1: 绝对
wSpd[2] = (ushort)(value >> 16);
wSpd[3] = value;
master.WriteMultipleRegisters(addr, 0x44, wSpd);
}
/// <summary>
/// 读取寄存器 位置
/// </summary>
public double ReadStatus(byte addr)
{
ushort[] pos = master.ReadHoldingRegisters(addr, 0x24, 2);
long Pos_Pus = (long)(pos[0] << 16) | pos[1];
double Pos_mm = Pos_Pus * 95.0 / 240;
return Pos_mm;
}
/// <summary>
/// 读取寄存器状态 位置
/// </summary>
public RTSTATUS ReadState(byte addr)
{
ushort[] statusU = master.ReadHoldingRegisters(addr, 0x20, 25);
RTSTATUS status = new RTSTATUS()
{
nPWM = (short)statusU[0], // PWM
nAmp = statusU[1], // 电机电流 电流值的1/10 单位mA
nPhaseFreq = (short)statusU[2], // 换向频率
nFinishSta = statusU[3], // 完成状态
nPhasePosHi = statusU[4], // 脉冲数高半字
nPhasePosLo = statusU[5], // 脉冲数低半字
nLeftTimeHi = statusU[6], // 完成时间高半字
nLeftTimeLo = statusU[7], // 完成时间低半字
nIN1Voltage = (short)statusU[8], // AI1电压 电压值的1/10 单位mV
nIN2Voltage = (short)statusU[9], // AI2电压 电压值的1/10 单位mV
nIN3Voltage = (short)statusU[10], // AI2电压 电压值的1/10 单位mV
nDiffVoltage = (short)statusU[11], // 差分电压
bSQ1Level =statusU[12], // SQ1电平 右 0(到限位)/ 1(未到限位)
bSQ2Level = statusU[13], // SQ2电平 左 0(到限位)/ 1(未到限位)
nInPWM = statusU[14], // 输入PWM
nInFreq = (short)statusU[15], // 输入频率
nInPulseHi = statusU[16], // 输入脉冲高半字
nInPulseLo = statusU[17], // 输入脉冲低半字
nLockSta = statusU[18], // 堵转状态
nErrorSta = statusU[19], // 错误状态
nMotorSpd = statusU[20], // 电机转速
bSpdDiv10 = statusU[21], // 转速是除以10的
bSpdMulti = statusU[22], // 转速量程乘以10
nTemperature = (short)statusU[23], // 温度
nPowerVoltage = statusU[24], // 电源电压
};
return status;
}
}
}