Modbus protocol: Modbus is a serial communication protocol published by Modicon Corporation (now Schneider Electric) in 1979 for the use of programmable logic controller (PLC) communication. Modbus has become the industry standard (De facto) for communication protocols in the industrial field, and is now a common connection method between industrial electronic devices.
Routine introduction
This routine introduces how to use C# to develop the upper computer to connect to the Modbus protocol sensor, receive sensor data and communicate with the sensor;
Before viewing this routine, please read the relevant sensor manual to understand the protocol used by the sensor and the basic functions of the sensor
Routine directory
The routine project directory is as follows
Dll:The dependent files of the project, please import these dlls into your project before running the project.
Form1:There is only one Form window in the routine, all logic codes are in the Form window file, and there are no other files
Turn on the device
The WT901C485 object represents the WT901C485 device in the program, and you can communicate with the device through it; when opening the device, you need to specify the serial port number and baud rate of the sensor, and then call the WT901C485.Open() method
/// <summary>
/// oprn device
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void openButton_Click(object sender, EventArgs e)
{
// Get the serial port number and baud rate of the connection
string portName;
int baudrate;
byte modbusId;
try
{
portName = (string)portComboBox.SelectedItem;
baudrate = (int)baudComboBox.SelectedItem;
modbusId = byte.Parse(ModbustextBox.Text.Replace("0x",""), System.Globalization.NumberStyles.HexNumber);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
// Do not open repeatedly
if (WT901C485.IsOpen())
{
return;
}
// open device
try
{
WT901C485.SetPortName(portName);
WT901C485.SetBaudrate(baudrate);
WT901C485.SetModbusId(modbusId);
WT901C485.Open();
// Implement logging data events
WT901C485.OnRecord += WT901C485_OnRecord;
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Turn off the device
Just call the WT901C485.Close() method to close the device
/// <summary>
/// turn off the device
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void closeButton_Click(object sender, EventArgs e)
{
try
{
// Turn off the device if it is already on
if (WT901C485.IsOpen())
{
WT901C485.OnRecord -= WT901C485_OnRecord;
WT901C485.Close();
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
Receive sensor data
Get data
The WT901C485 object will automatically calculate the sensor data and save it on itself. The data of the sensor can be obtained through the WT901C485.GetDeviceDavta() method. WT901C485.GetDeviceData() needs to pass in a key to get sensor data. Please check the key that needs to be used in the routine, the key is stored in the WitSensorKey class
/// <summary>
/// Get device data
/// </summary>
private string GetDeviceData(WT901C485 WT901C485)
{
StringBuilder builder = new StringBuilder();
builder.Append(WT901C485.GetDeviceName()).Append("\n");
// acceleration
builder.Append("AccX").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AccX)).Append("g \t");
builder.Append("AccY").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AccY)).Append("g \t");
builder.Append("AccZ").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AccZ)).Append("g \n");
// angular velocity
builder.Append("GyroX").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AsX)).Append("°/s \t");
builder.Append("GyroY").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AsY)).Append("°/s \t");
builder.Append("GyroZ").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AsZ)).Append("°/s \n");
// angle
builder.Append("AngleX").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AngleX)).Append("° \t");
builder.Append("AngleY").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AngleY)).Append("° \t");
builder.Append("AngleZ").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.AngleZ)).Append("° \n");
// magnetic field
builder.Append("MagX").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.HX)).Append("uT \t");
builder.Append("MagY").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.HY)).Append("uT \t");
builder.Append("MagZ").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.HZ)).Append("uT \n");
// latitude and longitude
builder.Append("Lon").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Lon)).Append("′ \t");
builder.Append("Lat").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Lat)).Append("′ \n");
// The port number
builder.Append("D0").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.D0)).Append ("\t");
builder.Append("D1").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.D1)).Append("\t");
builder.Append("D2").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.D2)).Append("\t");
builder.Append("D3").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.D3)).Append("\n");
//Quaternion
builder.Append("Q0").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q0)).Append("\t");
builder.Append("Q1").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q1)).Append("\t");
builder.Append("Q2").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q2)).Append("\t");
builder.Append("Q3").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q3)).Append("\n");
//barometric pressure
builder.Append("P").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q1)).Append("Pa \t");
builder.Append("H").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.Q2)).Append("m \t");
// temperature
builder.Append("T").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.T)).Append("℃ \n");
// GPS
builder.Append("GPSHeight").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.GPSHeight)).Append(" m \t");
builder.Append("GPSYaw").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.GPSYaw)).Append("° \t");
builder.Append("GPSV").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.GPSV)).Append("km/h \n");
// positioning accuracy
builder.Append("PDOP").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.PDOP)).Append("\t");
builder.Append("VDOP").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.VDOP)).Append("\t");
builder.Append("HDOP").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.HDOP)).Append("\n");
// version number
builder.Append("VersionNumber").Append(":").Append(WT901C485.GetDeviceData(WitSensorKey.VersionNumber)).Append("\n");
return builder.ToString();
}
Record data
The data of the sensor can be obtained through the WT901C485 object, but usually the host computer needs to record the data of the sensor. WT901C485 has an OnRecord event that will notify you when the data should be recorded, and the OnRecord event can be realized when the device is turned on; and then through the cooperation of WT901C485.GetDeviceData( ) method to record the data
// Some code
/// <summary>
/// turn on the device
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void openButton_Click(object sender, EventArgs e)
{
// Get the serial port number and baud rate of the connection
string portName;
int baudrate;
byte modbusId;
try
{
portName = (string)portComboBox.SelectedItem;
baudrate = (int)baudComboBox.SelectedItem;
modbusId = byte.Parse(ModbustextBox.Text.Replace("0x",""), System.Globalization.NumberStyles.HexNumber);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
// Do not open repeatedly
if (WT901C485.IsOpen())
{
return;
}
// turn on the device
try
{
WT901C485.SetPortName(portName);
WT901C485.SetBaudrate(baudrate);
WT901C485.SetModbusId(modbusId);
WT901C485.Open();
// Implement logging data events
WT901C485.OnRecord += WT901C485_OnRecord;
Thread.Sleep(1000);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
return;
}
}
/// <summary>
/// This is called when the sensor data is refreshed, you can log the data here
/// </summary>
/// <param name="WT901C485"></param>
private void WT901C485_OnRecord(WT901C485 WT901C485)
{
string text = GetDeviceData(WT901C485);
Debug.WriteLine(text);
}
Set sensor
The sensor can be operated by the method of WT901C485
WT901C485.StartFieldCalibration() Send start field calibration command
WT901C485.EndFieldCalibration() Send end field calibration command
WT901C485.SendProtocolData() Send other commands
Set address
Set the address of the sensor by calling the WT901C485.SetModbusId() method
// /// <summary>
/// Set the device address to 50
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void SetAddrBtn_Click(object sender, EventArgs e)
{
if (WT901C485.IsOpen() == false)
{
return;
}
try
{
// Unlock registers and send commands
WT901C485.UnlockReg();
byte modbusId = byte.Parse(ModbustextBox.Text.Replace("0x", ""), System.Globalization.NumberStyles.HexNumber);
WT901C485.SetModbusId(modbusId);
// The following two lines are equivalent to the above, it is recommended to use the above
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x69, 0xB588));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 69, B5, 88, 22, A1 });
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x1A, 0x0050));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 1A, 00, 50, A1, B0 });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Accelerometer Calibration
Applied calibration of the sensor by calling the WT901C485.AppliedCalibration() method
/// <summary>
/// Accelerometer Calibration
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void appliedCalibrationButton_Click(object sender, EventArgs e)
{
if (WT901C485.IsOpen() == false)
{
return;
}
try
{
// Unlock registers and send commands
WT901C485.UnlockReg();
WT901C485.AppliedCalibration();
// The following two lines are equivalent to the above, it is recommended to use the above
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x69, 0xB588));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 69, B5, 88, 22, A1 });
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x01, 0x0001));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 01, 00, 01, 32, 4B });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
Magnetic Field Calibration
Perform magnetic field calibration on the sensor by calling the WT901C485.StartFieldCalibration() method and WT901C485.EndFieldCalibration() method
/// <summary>
/// Start Magnetic Field Calibration
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void startFieldCalibrationButton_Click(object sender, EventArgs e)
{
if (WT901C485.IsOpen() == false)
{
return;
}
try
{
// Unlock registers and send commands
WT901C485.UnlockReg();
WT901C485.StartFieldCalibration();
// The following two lines are equivalent to the above, it is recommended to use the above
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x69, 0xB588));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 69, B5, 88, 22, A1 });
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x01, 0x0007));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 01, 00, 07, 94, 49 });
MessageBox.Show("Start magnetic field calibration, please turn around the three axes of the sensor XYZ, and click【End Magnetic Field Calibration】");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
///End magnetic field calibration
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void endFieldCalibrationButton_Click(object sender, EventArgs e)
{
if (WT901C485.IsOpen() == false)
{
return;
}
try
{
// Unlock registers and send commands
WT901C485.UnlockReg();
WT901C485.EndFieldCalibration();
// The following two lines are equivalent to the above, it is recommended to use the above
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x69, 0xB588));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 69, B5, 88, 22, A1 });
//WT901C485.SendProtocolData(Modbus16Utils.GetWrite(T901C485.GetModbusId(), 0x01, 0x0000));
//WT901C485.SendProtocolData(new byte[] { 50, 06, 00, 01, 00, 00, D5, 8B });
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
More
For other operations, please refer to the sensor manual
Read sensor register
You can read the registers of the sensor through WT901C485.SendReadReg(), or use WT901C485.SendProtocolData()method
After sending the read command, the register value will be saved in WT901C485, you need to get the register data through WT901C485.GetDeviceData()
/// <summary>
/// Read 03 register
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void readReg03Button_Click(object sender, EventArgs e)
{
if (WT901C485.IsOpen() == false)
{
return;
}
try
{
// waiting time
int waitTime = 150;
// Send a read command and wait for the sensor to return data. If it is not read, you can extend the waitTime, or read it several times
WT901C485.SendReadReg(0x03, waitTime);
// The following two lines are equivalent to the above. It is recommended to use the above
//WT901C485.SendProtocolData(Modbus16Utils.GetRead(WT901C485.GetModbusId(), 0x03, 0x01), waitTime);
//WT901C485.SendProtocolData(new byte[] { 50, 03, 00, 03, 00, 01, 79, 8B }, waitTime);
string reg03Value = WT901C485.GetDeviceData("03");
MessageBox.Show($"Register 03 value is : {reg03Value}");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
/// <summary>
/// Read 03 register
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void readReg03Button_Click(object sender, EventArgs e)
{
if (JY901.IsOpen() == false)
{
return;
}
try
{
// waiting time
int waitTime = 150;
// Send a read command and wait for the sensor to return data. If it is not read, you can extend the waitTime, or read it several times
JY901.SendReadReg(0x03, waitTime);
// The following line is equivalent to the above. It is recommended to use the above
//JY901.SendProtocolData(new byte[] { 0xff, 0xaa, 0x27, 0x03, 0x00 }, waitTime);
string reg03Value = JY901.GetDeviceData("03");
MessageBox.Show($"Register 03 value is : {reg03Value}");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
WT901C485 API
method
illustrate
Parameter introduction
return value
void SetPortName(string portName)
Set the serial port to open
portName:Serial number
void
void SetBaudrate(int baudRate)
Specify the baud rate to open
baudRate:baud rate
void
void Open()
turn on the device
none
void
bool IsOpen()
Is the device turned on
none
Return whether to open open: true close: false
void Close()
turn off the device
none
void
void SendData(byte[] data, out byte[] returnData, bool isWaitReturn, int waitTime , int repetition)
send data
data: the data to be sent
returnData: the data returned by the sensor
isWaitReturn: Whether the sensor needs to return data
waitTime: wait for the sensor to return data time, unit ms, default 100ms
repetition: the number of times to repeat sending
void
void SendProtocolData(byte[] data)
send protocol data
data:data waiting to be sent
void
void SendProtocolData(byte[] data, int waitTime)
Send data with protocol, and specify the waiting time