Open Protocol using C# Socket Programming for Nutrunner

Introduction
In one of my project I had a chance to create an
Atlas Copco PowerFocus (3000/4000) Nutrunner Tools communication
using c# socket programing. The main aim of this article is due to when
i start the Nutrunner tool communication program it was like a blank
page. I don’t have an idea how to complete the task even i was been
googling for 2 or 3 days but can’t find a sample code to communicate
with Nutrunner tools using c#.Finally I got a solution using an Open
protocol.
Today I will explain you what is
1) Atlas Copco PowerFocus (3000/4000) Nutrunner Tools.
2) How to use Open protocol.
3) C# Socket communication program for Nutrunner tool communication.
First we start with.
1)Atlas Copco PowerFocus (3000/4000) Nutrunner Tools,
Power Focus 3000/3100 is the latest generation of control and monitoring
systems for advanced tightening technology. Power Focus 3000/3100 is a
complete solution for the modern assembly industry with high demands and
stringent quality and efficiency requirements. The concept offers full
modularity through combinations of hardware and software.
The PF 4000 is a new generation of control systems suitable for
Tensor S, ST, DS and ETX models. Unlike its predecessor, the PF 3100,
the PF 4000 is available in one model with two versions (Compact and
Graph) that can handle all torque levels. This favours your maintenance
budget, since fewer backup units are required.

Simply say Power Focus (3000/4000) is used to read the Torque data. It’s
a machine where we can set the Bach Size, Batch Count, Tightening
Status, Torque Status, Angle Status, Torque Min limit, Torque Max limit
and etc. We can get the final Torque data , compare the Limit value and
produce the final result.
2) How to use Open protocol.
Open Protocol is an interface for building applications for remote
control or data subscription of controllers. It is platform independent
and can be implemented on Linux, PLC, printers, and all Windows
platforms for example. The Open Protocol supports both serial and
Ethernet connection.

Open Protocol supports Power Focus, and PowerMACS controllers.
Communication
The Open Protocol can be run using Ethernet or serial communication. The
Open Protocol is a full duplex protocol, which means that data can be
sent and received at the same time. Every communication partner must be
able to operate a send and receive facility simultaneously.
Ethernet protocol
The integrator connects to the controller, and the controller accepts
the connection. The controller is the server, and the integrator
application is the client. The protocol used is TCP/IP. The default port
used for the communication is 4545.
Serial ASCII protocol
All messages sent from the integrator to the controller must be stamped
with a 4 ASCII character tag before the STX character: BEL (ASCII 0x07
bell) HT (ASCII 0x09 horizontal tab) BEL (ASCII 0x07) HT (ASCII 0x09).
All messages must be encapsulated between STX (ASCII 0x02 Start of Text) and ETX (ASCII 0x03 End of Text).
Message structure
All information sent over the communication links is ASCII format. A
message consists of three parts; header, data field and message end.
For example here we see how to start a communication. For Communication
start we need to use the MID 0001
Communication messages
MID 0001 Communication start
This message enables the communication. The controller does not respond to any other command before this.
Message sent by: Integrator
Answers:
MID 0002 Communication start acknowledge or
MID 0004 Command error, Client already connected.
If the Communication is accepted the we can receive the result as MID 0002 if not we receive the MID 0004.
For more details about Open Protocol, please review the attached open Protocol PDF document.
3) C# Socket communication program for Nutrunner tool communication
1) Connect
2) Communicate
3) Data send and receive
4) Disconnect.
The detailed code will be listed below.
Background
The main aim was to develop a simple easy to use .Net communication
program for Atlas Copco Power Focus (3000/4000) – Nutrunner Tool.
Using the code
The code is very simple and has comments on all functions. The main aim
is to make the program very simple and easy to use all the functions has
been well commented in project.
1) First we start with namespace declarations.
using System.Net;
using System.IO;
using System.Net.Sockets;
2) Variable Declarations
Socket server;// Declare your Socket
IPEndPoint ip; // Declare your IPEndpoint
3) Connect (to connect the Nutrunner tool for communication).
For connection we need the Nutrunner tool IP Address.Here my tools IP
Address was “10.126.224.186” and the default port for comuncication is
“4545” corss check with your hardware eng for the port used on your
tools.Here we use the Socket communication program for connection.
After the connection is ok we need to send the Communication Start
signal to the nutrunner tools “ MID 0001” – (“00200001000000000000#)
Server.Send()
String szData = "00200001000000000000#";//Nutrunner Communication Start
byte[] byData = Encoding.Default.GetBytes(szData);//convert the string as Byte
int sent = server.Send(byData, SocketFlags.None);
server.Receive()
byte[] bytesFrom = new byte[1025];
int iRx = server.Receive(bytesFrom);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
String resultchk = dataFromClient.Substring(4, 4).ToString();
If we receive MID 0002 as result then the communication start is
successful .If we receive MID 0004 as result then there is an error in a
communication start.
The detail connect functions
private void button1_Click(object sender, EventArgs e)
{
try
{
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
String ipaddress = “10.126.224.186”;
ip = new IPEndPoint(IPAddress.Parse(ipaddress), 4545);
server.Connect(ip);
label2.BackColor = System.Drawing.Color.GreenYellow;
label2.Text = "Connected";
connectServer();
}
catch (Exception ex)
{
}
}
private void connectServer()
{
try
{
if (server.Connected == false)
{
label2.BackColor = System.Drawing.Color.Red;
server = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
String ipaddress = textips.Text.Trim();
ip = new IPEndPoint(IPAddress.Parse(ipaddress), 4545);
server.Connect(ip);
label2.BackColor = System.Drawing.Color.GreenYellow;
label2.Text = "Connected";
}
if (server.Connected == true)
{
String szData = "00200001000000000000#";//Nutrunner Communication Start
byte[] byData = Encoding.Default.GetBytes(szData);//System.Text.Encoding.ASCII.GetBytes(szData);
int sent = server.Send(byData, SocketFlags.None);
byte[] bytesFrom = new byte[1025];
// string bytesSent = server.Send(
int iRx = server.Receive(bytesFrom);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
String resultchk = dataFromClient.Substring(4, 4).ToString();
////String szData = "00200060000000000000#";//Nutrunner Communication Start
////byte[] byData = Encoding.Default.GetBytes(szData);//System.Text.Encoding.ASCII.GetBytes(szData);
////int sent = server.Send(byData, SocketFlags.None);
timer1.Enabled = true;
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message.ToString());
}
}
4) Torque Data Receive.
Here in my program I have used a Timer control for Torque data receive.
In timer we frequently check for the connection. If connection fails we reconnect to the nutrunner tools.
To receive the Torque data we use the message id MID 0060.
For Torque data receive we send the MID 0060 to the Nutrunner tool.
MID 0060 Last tightening result data subscribe
Set the subscription for the result tightenings. The result of this
command will be the transmission of the tightening result after the
tightening is performed (push function). The MID revision in the header
is used to subscribe to different revisions of MID 0061 Last tightening
result data upload reply.
Message sent by: Integrator
Answer: MID 0005 Command accepted or MID 0004 Command error, Last
tightening subscription already exists or MID revision not supported
Send data to get Torque result:
String szData = "00200060000000000000#";//Torque data Request Send
byte[] byData = Encoding.Default.GetBytes(szData);
int sent = server.Send(byData, SocketFlags.None);
Receive Torque result
byte[] bytesFrom = new byte[1025];
int iRx = server.Receive(bytesFrom);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
String resultchk = dataFromClient.Substring(4, 4).ToString();
We receive the MID 0061 as result with Torque data.
We will receive the result data something like this.
"023100610010 010001020103airbag7 04KPOL3456JKLO897
05000600307000008000009010011112000840
130014001400120015000739160000017099991800000
1900000202001-06-02:09:54:09212001-05-29:12:34:3322123345675 NUL"
Format the result string and get the Torque final result.
For example I have used the substring and get the final torque result here
txtfinaltorque.Text = dataFromClient.Substring(132, 6).ToString();
The detailed Timer code.
private void timer1_Tick(object sender, EventArgs e)
{
try
{
if (server.Connected == false)
{
label2.BackColor = System.Drawing.Color.Red;
label2.Text = "Not Connected";
server.Disconnect(true);
server.Close();
server.Dispose();
connectServer();
}
String szData = "00200060000000000000#";//Nutrunner Communication Start
byte[] byData = Encoding.Default.GetBytes(szData);//System.Text.Encoding.ASCII.GetBytes(szData);
int sent = server.Send(byData, SocketFlags.None);
byte[] bytesFrom = new byte[1025];
// string bytesSent = server.Send(
int iRx = server.Receive(bytesFrom);
string dataFromClient = System.Text.Encoding.ASCII.GetString(bytesFrom);
String resultchk = dataFromClient.Substring(4, 4).ToString();
if (resultchk == "0061")
{
label2.BackColor = Color.Violet;
label2.Text = "Torque Data Readed ";
textBox1.Text = dataFromClient.ToString();
txtcellid.Text = dataFromClient.Substring(22, 4).ToString();
txtchannelid.Text = dataFromClient.Substring(28, 2).ToString();
txtjobid.Text = dataFromClient.Substring(86, 2).ToString();
txtControlorName.Text = dataFromClient.Substring(32, 25).ToString();
txtBatchSize.Text = dataFromClient.Substring(95, 4).ToString();
txtBatchCount.Text = dataFromClient.Substring(101, 4).ToString();
txttighteningstatus.Text = dataFromClient.Substring(107, 1).ToString();
if (txttighteningstatus.Text.Trim() == "0")
{
txttighteningstatusok.Text = "NOK";
}
else
{
txttighteningstatusok.Text = "OK";
}
txttorquestatus.Text = dataFromClient.Substring(110, 1).ToString();
if (txttorquestatus.Text.Trim() == "0")
{
txttorquestatusok.Text = "Low";
}
else if (txttorquestatus.Text.Trim() == "1")
{
txttorquestatusok.Text = "OK";
}
else
{
txttorquestatusok.Text = "High";
}
txtanglestatus.Text = dataFromClient.Substring(113, 1).ToString();
txttorqueminlimit.Text = dataFromClient.Substring(116, 6).ToString();
txttorquemax.Text = dataFromClient.Substring(124, 6).ToString();
txtfinaltorque.Text = dataFromClient.Substring(132, 6).ToString();
txttorque.Text = dataFromClient.Substring(142, 2).ToString() + "." + dataFromClient.Substring(144, 2).ToString();//dataFromClient.Substring(140,6).ToString()
txtTighteningID.Text = dataFromClient.Substring(221, 10).ToString();
String szData3 = "00200062000000000000#";//Nutrunner Communication Start
byte[] byData3 = Encoding.Default.GetBytes(szData3);//System.Text.Encoding.ASCII.GetBytes(szData);
int sent3 = server.Send(byData3, SocketFlags.None);
}
}
catch (Exception ex)
{
}
}
5) Disconnect the Connection.
Check for the connection if its connected then disconnect the communication the detail code below.
private void button2_Click(object sender, EventArgs e)
{
if (server.Connected == true)
{
label2.BackColor = System.Drawing.Color.Red;
label2.Text = "Not Connected";
server.Disconnect(true);
server.Close();
server.Dispose();
clears();
}
}
Points of Interest
I love to work and play with the HMI (Human Interface Program).I
have worked with several HML programs using c#.net like PLC,Sensor
Programing and Nutrunner tool communication Program. While working with
this program i didn’t get the proper guides to achieve the result
finally I got it. I want the end users who read this article should be
benefited by this program.
History
Initial release NutrunnerFirstProgram- 2013/07/03..