INSPEKTO S70

Das INSPEKTO S70 ist ein vollausgestattetes Komplettsystem f�r die industrielle Sichtpr�fung, welches in weniger als einem Tag einsatzbereit ist.

1. Einleitung

Es kombiniert ein einzigartiges elektrooptisches System mit der bahnbrechenden Autonomous Machine Vision AI (AMV-AI�)- Technologie, um eine L�sung in der visuellen Qualit�tspr�fung zu liefern, welche extrem vielseitig und einfach zu implementieren ist, sich bei �nderungen in der Produktionslinie anpasst und keine Bildverarbeitungs Expertise vom Anwender ben�tigt. Ein automatisiertes visuelles Inspektionssystem, welches keinen Fehlerkatalog ben�tigt.

Mit dem System kann per digitalen IOs oder per TCP/IP kommuniziert werden. Eine Anbindung an eine SPS mittels PROFINET ist ebenso m�glich. F�r einfachere Pr�faufgaben, mit wenig unterschiedlichen zu klassifizierenden Objekten, reicht in der Regel die Kommunikation mittels digitalen IOs aus. 

Im folgenden wird haupts�chlich die Kommunikation mittels TCP/IP beschrieben, da die Kommunikation �ber die digitalen IOs selbsterkl�rend ist. Ein textuelles sowie ein grafisches Beispielprogramm mit den globalen Funktionen k�nnen am Ende des Artikels heruntergeladen werden. 

2. Versionshinweis

Inspekto SW Version: V5.0.2

horstFX Version: ab 2022.07

3. Einrichtung des Systems

Die Einrichtung des Inspekto Systems ist gut in den beigelegten Dokumenten von Inspekto beschrieben. Ebenso leitet die Software einen gut durch die Einrichtung. Zu Kommunikation mittels TCP/IP muss in der Inspekto Software bei Connectivity TCP server ausgew�hlt werden. Anschlie�end muss die IP Adresse der Kamera in den selben Bereich wie die des Roboters gebracht werden. D.h. die ersten 3 Ziffernbl�cke m�ssen gleich sein wie die bei dem Roboter und der letzte Zifferblock muss sich unterscheiden. Der Schaltschrank horstControl des Roboters wird mittels Netzwerkkabel mit der PLC Netzwerkbuchse des Inspekto-Systems verbunden.

 

Wie die IP-Adresse des Roboters eingestellt werden kann, ist in folgendem Artikel beschrieben: IP-Adresse �ndern

F�r die Einrichtung eines Inspektionsprofils leitet der Wizard der S70 Software einen gut durch den Prozess.

4. Kommunikation per TCP/IP

Die beiden Teilnehmer kommunizieren �ber Netzwerk Sockets miteinander. Detailliertere Informationen finden sich unter Sockets.

4.1. Herstellen der Verbindung

Die Verbindung zur Kamera kann mit folgender Funktion in horstFX hergestellt werden:

Der Port der Kamera ist 2052.

Die IP-Adresse muss der eingestellten IP-Adresse des Kamera-Systems entsprechen. 

// Communication
var IP_Cam = "192.168.2.10";    // IP adress camera
var Port_Cam = 2052;            // Port camera
var Socket = null;              // socket object
 
//Establish camera connection
connectCam();
 
try
{
    // Hauptprogramm
    // ...
    // ...
}
finally
{
    Socket.close();
}
 
// Establish connection to camera
function connectCam()
{
    showHint("Connect to camera");
    try
    {
        // Establish connection via socket
        Socket = new java.net.Socket();
        Socket.connect(new java.net.InetSocketAddress(IP_Cam, Port_Cam),  10000); // 10 s timeout while establishing connection
        // 10 sek timeout while reading message
        Socket.setSoTimeout(10000);
        showHint("Connection to camera established");
    }
    catch (e)
    {
        show_error("A connection with the Inspekto-System could not be established! The program is aborted due to safety reasons.");
        exitRobotScript();
    }  
}

horstFX versucht mit dem eingestellten Timeout von 10 Sekunden eine Verbindung mit dem System herzustellen. Sollte in der Zeit keine Verbindung hergestellt werden k�nnen, wird eine Informationsmeldung ausgegeben. 

Der eigentliche Programmcode des Programms befindet sich in dem try{} Block. Wird hierbei durch ein Fehler das Programm beendet, wird durch den finally{} Block sichergestellt, dass der Socket auch wieder geschlossen wird. 

4.2. Zusammenstellung der Befehle

Eine Nachricht an die Kamera sowie von der Kamera besteht aus einem Header- sowie einem Daten-Teil welche eine bestimmte Struktur aufweisen m�ssen.

Roboter ? INSPEKTO

INSPEKTO ? Roboter

Jede gesendete Nachricht muss sich an die Struktur halten. Es muss der Komplette Header sowie der komplette Data-Part gesendet werden. Dabei muss auf die L�nge der einzelnen Teilbefehle geachtet werden. Hat ein Teilbefehl nicht die komplette L�nge, so muss dieser mit Leerzeichen aufgef�llt werden. Wird keine Information bei einem Teilbefehl gesendet, so muss "NA" passend aufgef�llt mit Leerzeichen gesendet werden.

Weitere Informationen dazu findet man in der INSPEKTO S70 - TCP_IP Integration ManualBei dieser Einrichtung wurde hierbei die V4 genutzt.

 

Mit folgender Funktion werden in horstFX die Teilbefehle auf die passende L�nge mit Leerzeichen aufgef�llt. 

// Fill the string up to specified length with blank spaces
function fillUpToLength()
{
    // header
    HeaderID = HeaderID.padEnd(6," ");
    TelegramID = TelegramID.padEnd(10," ");
    HeaderLength = HeaderLength.padEnd(4," ");
    DataLength = DataLength.padEnd(8," ");
    RunningNumber = RunningNumber.padEnd(6," ");
    DateAndTime = DateAndTime.padEnd(14," ");
    Destination = Destination.padEnd(32," ");
    Source = Source.padEnd(32," ");
    // Data
    OUT_INSPECTION_MODE = OUT_INSPECTION_MODE.padEnd(4," ");
    OUT_NEW_OBJECT_TRIGGER = OUT_NEW_OBJECT_TRIGGER.padStart(64," ");
    OUT_PROFILE_ID = OUT_PROFILE_ID.padEnd(6," ");
    OUT_BATCH_ID = OUT_BATCH_ID.padEnd(64," ");
}

Die komplette Nachricht wird aus den Teilbefehlen mittels folgender Funktion erstellt.

// Build the camera message
function buildMessage()
{
    var messageHeader = HeaderID + TelegramID + HeaderLength + DataLength + RunningNumber + DateAndTime + Destination + Source;
    var messageData = OUT_INSPECTION_MODE + OUT_NEW_OBJECT_TRIGGER + OUT_PROFILE_ID + OUT_BATCH_ID;
    var message = messageHeader + messageData;
     
    return message;
}

Die von dem Kamerasystem kommende Nachricht kann durch folgende Funktion auf das passende Format gebracht werden.

// Split message from camera
function splitInMessage(Response)
{
    // Header
    InHeaderID = Response.substring(0, 6);
    InTelegramID = Response.substring(6, 16);
    InHeader_Length = Response.substring(16, 20);
    InData_Length = Response.substring(20, 28);
    InRunning_Number = Response.substring(28, 34);
    InDate_And_Time = Response.substring(34, 48);
    InDestination = Response.substring(48, 80);
    InSource = Response.substring(80, 112);
 
    // Data
    IN_CUR_INSPECTION_MODE = Response.substring(112, 116);
    IN_CUR_OBJECT_ID = Response.substring(116, 180);
    IN_CUR_PROFILE_ID = Response.substring(180, 186);
    IN_CUR_BATCH_ID = Response.substring(186, 250);
    IN_OBJECT_INSPECTION_RESULT = Response.substring(250, 254);
    IN_ROI_DEFECT_LIST = Response.substring(254, 318);
    IN_SYSTEM_ERROR = Response.substring(318, 322);
    IN_SYSTEM_READY = Response.substring(322, 326);
     
    if (IN_SYSTEM_ERROR != "0000")
    {
        show_error("An error " + IN_SYSTEM_ERROR + " has occurred. For more information on the error code, refer to the Inspecto documentation.");
    }
 
    // This loop fixes the bug which occurs in the inspector software version V5.0.2
    while (IN_SYSTEM_READY != "0001")
    {
        fixBug();
 
        if (IN_SYSTEM_ERROR != "0000")
        {
            show_error("An error " + IN_SYSTEM_ERROR + "has occurred. For more information on the error code, refer to the Inspecto documentation.");
        }
    }
}

In der Inspekto Softwareversion V5.0.2 gibt es noch einen Bug. Bei dieser Version schickt die Kamera mehrere Nachrichten. Diese Nachrichten m�ssen solange eingelesen werden bis das System in die Variable "IN_SYSTEM_READY" den Wert 0001 schreibt und somit wieder bereit f�r neue Befehle ist. Dieser Bug wird durch den Aufruf folgender Funktion in obiger Funktion korrigiert.

// This function fixes the bug which occurs in the inspector software version V5.0.2
function fixBug()
{
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
}

Bei dem Senden eines Befehls an das Kamerasystem muss noch der aktuelle Zeitstempel mitgeschickt werden. Mittels folgender Funktionen erh�lt man dieses automatisch.

// Get the current date and time
function getCurrentTime()
{  
    return datetime = getDate(new Date) + getTime(new Date);
}
 
// get the current date
function getDate(DateTime)
{
        return DateTime.getFullYear() + (((DateTime.getMonth()+1) < 10)?"0":"") + (DateTime.getMonth()+1) + ((DateTime.getDate() < 10)?"0":"") + DateTime.getDate() ;
}
 
// get the current time
function getTime(TimeNow)
{   
    return ((TimeNow.getHours() < 10)?"0":"") + ((TimeNow.getHours()>12)?(TimeNow.getHours()-12):TimeNow.getHours()) + ((TimeNow.getMinutes() < 10)?"0":"") + TimeNow.getMinutes() + ((TimeNow.getSeconds() < 10)?"0":"") + TimeNow.getSeconds();
}

4.3. Senden der Befehle

Nachrichten an das Kamerasystem k�nnen �ber folgende Funktion gesendet werden.

// Write message via socket
function writeMessage(message) {
    var printWriter =
        new java.io.PrintWriter(
            new java.io.OutputStreamWriter(
                Socket.getOutputStream()));
    printWriter.print(message);
    printWriter.flush();
}

4.4. Einlesen der Kameranachrichten

Die Nachrichten des Kamerasystems k�nnen �ber folgende Funktion eingelesen werden. L�uft der Timeout (10 Sekunden) welcher in der Funktion connectCam() definiert wurde ab ohne dass die Kamera eine Nachricht schickt, wird eine Fehlermeldung ausgegeben und das Programm aus Sicherheitsgr�nden abgebrochen.

// Read message from Socket
function readMessage() {
    var bufferedReader =
        new java.io.BufferedReader(
            new java.io.InputStreamReader(
                Socket.getInputStream()));
    var charArrayType = Java.type("char[]");
    var buffer = new charArrayType(1000);
    try {
        var anzahlZeichen = bufferedReader.read(buffer, 0, 1000);  
        var message = new java.lang.String(buffer);
    } catch (e) {
        var message = "Timeout: Keine Nachricht erhalten";
        show_error("Timeout: No message was received from the camera. The program is aborted due to safety reasons.");
        Socket.close();
        exitRobotScript();
    }
    return message;
}

4.5. Setzen des Inspektionsmodus

Der Kamera k�nnen unterschiedliche Inspektionsmodi mitgeteilt werden. Diese k�nnen per TCP/IP Befehl gesetzt werden oder direkt �ber die Oberfl�che der Inspekto Software. Folgende Modi stehen zur Auswahl. In der INSPEKTO S70 - TCP_IP Integration Manual sind diese noch genauer beschrieben.

Da wir die Kamera in unserem Beispiel mittels TCP/IP �ber den Roboter triggern und die PartID automatisch von dem Inspekto System vergeben werden soll, nutzen wir Direct Trigger - Part ID generated by the system. Das hei�t wir nutzen hierf�r den Wert 0006 welchen wir der Kamera �bergeben.

Mittels folgender Funktion wird der Inspektionsmodus gesetzt.

// set insptection trigger mode
var InspectionMode = "0006";        // Direct Trigger - part ID generated by the system
setInspectionMode(InspectionMode);
 
// Set the inspection trigger mode
function setInspectionMode(InspectionMode)
{
    showHint("Setting inspection mode");
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = InspectionMode;
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
 
    sleep(2000);
}

4.6. Laden des Inspektionsprofils

Die Kamera kann �ber unterschiedliche Inspektionsprofile unterschiedliche Bauteile inspizieren. Mittels folgender Funktion k�nnen die unterschiedlichen Profile geladen werden.

// load inspection profile
var ProfileID = "000002";       // Profile 2
loadProfile(ProfileID);
 
// Load an inspection profile
function loadProfile(ProfileID)
{
    showHint("Loading profile ID")
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = ProfileID;
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
 
    sleep(2000);
}

4.7. Zuweisen einer Batch ID

Mittels folgender Funktion kann eine neue Batch ID zugewiesen werden.

// set a new batch ID
var BatchID = "TestBatchID";        // new batchID
setBatchID(BatchID);
 
// Set a batch ID
function setBatchID(BatchID)
{
    showHint("Setting batch ID")
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = BatchID;
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
}

4.8. Triggern der Kamera

Zum Triggern der Kamera muss dieser eine neue PartID �bermittelt werden. Diese muss sich bei jedem Trigger Befehl unterscheiden. Ansonsten wird von der Kamera kein neues Bild aufgenommen. Ist der Inspektionsmodus Direct Trigger - Part ID generated by the system ausgew�hlt, wird von dem Inspekto System dem Pr�fbild eine eigenst�ndige ID vergeben.

Mittels folgender Funktion wird die Kamera getriggert.

// set new object trigger
var PartID = "1";
setNewObjectTrigger(PartID);
show_info("Inspection Result: " + IN_OBJECT_INSPECTION_RESULT);
 
// Set a trigger
function setNewObjectTrigger(PartID)
{
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = PartID;
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
}

5. Textuelles Beispielprogramm

Folgendes Beispielprogramm ruft alle obigen genannten Funktionen auf. Der Inspektionsmodus wird gesetzt, ein Inspektionsprofil wird aufgerufen und die Kamera wird durch eine Schleife alle 2 Sekunden getriggert. Die Part ID wird hierbei einfach bei jedem Schleifendurchlauf nach oben gesetzt. Dieses Programm kann am Ende des Artikels als fertiges horstFX Programm heruntergeladen werden.

////////////////////////////////////////////// Variables //////////////////////////////////////////////
 
// Communication
var IP_Cam = "192.168.2.10";    // IP adress camera
var Port_Cam = 2052;            // Port camera
var Socket = null;              // socket object
 
// camera
var InspectionMode = "0006";    // Direct Trigger - part ID generated by the system
var ProfileID = "000002";       // Profile 2
var BatchID = "TestBatchID";    // new batchID
 
// Telegram breakdown
// Header Robot - Inspekto
var HeaderID = "";
var TelegramID = "";
var HeaderLength = "";
var DataLength = "";
var RunningNumber = "";
var DateAndTime = "";
var Destination = "";
var Source = "";
// Data Robot - Inspekto
var OUT_INSPECTION_MODE = "";
var OUT_NEW_OBJECT_TRIGGER = "";
var OUT_PROFILE_ID = "";
var OUT_BATCH_ID = "";
 
// Header Inspekto - Robot
var InHeaderID = "";
var InTelegramID = "";
var InHeader_Length = "";
var InData_Length = "";
var InRunning_Number = "";
var InDate_And_Time = "";
var InDestination = "";
var InSource = "";
// Data Inspekto - Robot
var IN_CUR_INSPECTION_MODE = "";
var IN_CUR_OBJECT_ID = "";
var IN_CUR_PROFILE_ID = "";
var IN_CUR_BATCH_ID = "";
var IN_OBJECT_INSPECTION_RESULT = "";
var IN_ROI_DEFECT_LIST = "";
var IN_SYSTEM_ERROR = "";
var IN_SYSTEM_READY = "";
 
////////////////////////////////////////////// Program  //////////////////////////////////////////////
 
//Establish camera connection
connectCam();
 
try
{
    // set insptection trigger mode
    setInspectionMode(InspectionMode);
 
    // load inspection profile
    loadProfile(ProfileID);
 
    // set a new batch ID
    //setBatchID(BatchID);
 
    var t = 1;
 
    while (true)
    {  
        var PartID = String(t);     // PartID needs to be different than the previus ID the system received
         
        // set new object trigger
        setNewObjectTrigger(PartID);
        show_info("Inspection Result: " + IN_OBJECT_INSPECTION_RESULT);
        // Result: 0001 - IO
        // Result: 0002 - NIO
        // Result: 0003 - Objekt erkannt, liegt aber nicht im geforderten Bereich. -> NIO
        // Result: 0255 - Kein Objekt erkannt -> NIO
 
        t = t+1;
        sleep(2000);
    }
 
} finally
{
    Socket.close();
}
 
////////////////////////////////////////////// Functions //////////////////////////////////////////////
 
// Set the inspection trigger mode
function setInspectionMode(InspectionMode)
{
    showHint("Setting inspection mode");
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = InspectionMode;
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
 
    sleep(2000);
}
 
// Load an inspection profile
function loadProfile(ProfileID)
{
    showHint("Loading profile ID")
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = ProfileID;
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
 
    sleep(2000);
}
 
// Set a trigger
function setNewObjectTrigger(PartID)
{
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = PartID;
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = "NA";
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
}
 
// Set a batch ID
function setBatchID(BatchID)
{
    showHint("Setting batch ID")
 
    // Telegram breakdown
    // Header
    HeaderID = "S70_01";
    TelegramID = "01INSPEKTO";
    HeaderLength = "0112";
    DataLength = "000138";
    RunningNumber = "000001";
    DateAndTime = getCurrentTime();
    Destination = "INSPEKTO";
    Source = "PLC";
    // Data
    OUT_INSPECTION_MODE = "NA";
    OUT_NEW_OBJECT_TRIGGER = "NA";
    OUT_PROFILE_ID = "NA";
    OUT_BATCH_ID = BatchID;
 
    // Fill the string up to specified length with blank spaces
    fillUpToLength();
     
    // Build message
    var Message = buildMessage();
 
    // Write camera message
    writeMessage(Message);
 
    // Read camera message
    var Msg_Cam = readMessage();
 
    // Split camera message
    splitInMessage(Msg_Cam);
}
 
// Fill the string up to specified length with blank spaces
function fillUpToLength()
{
    // header
    HeaderID = HeaderID.padEnd(6," ");
    TelegramID = TelegramID.padEnd(10," ");
    HeaderLength = HeaderLength.padEnd(4," ");
    DataLength = DataLength.padEnd(8," ");
    RunningNumber = RunningNumber.padEnd(6," ");
    DateAndTime = DateAndTime.padEnd(14," ");
    Destination = Destination.padEnd(32," ");
    Source = Source.padEnd(32," ");
    // Data
    OUT_INSPECTION_MODE = OUT_INSPECTION_MODE.padEnd(4," ");
    OUT_NEW_OBJECT_TRIGGER = OUT_NEW_OBJECT_TRIGGER.padStart(64," ");
    OUT_PROFILE_ID = OUT_PROFILE_ID.padEnd(6," ");
    OUT_BATCH_ID = OUT_BATCH_ID.padEnd(64," ");
}
 
// Build the camera message
function buildMessage()
{
    var messageHeader = HeaderID + TelegramID + HeaderLength + DataLength + RunningNumber + DateAndTime + Destination + Source;
    var messageData = OUT_INSPECTION_MODE + OUT_NEW_OBJECT_TRIGGER + OUT_PROFILE_ID + OUT_BATCH_ID;
    var message = messageHeader + messageData;
     
    return message;
}
 
// Split message from camera
function splitInMessage(Response)
{
    // Header
    InHeaderID = Response.substring(0, 6);
    InTelegramID = Response.substring(6, 16);
    InHeader_Length = Response.substring(16, 20);
    InData_Length = Response.substring(20, 28);
    InRunning_Number = Response.substring(28, 34);
    InDate_And_Time = Response.substring(34, 48);
    InDestination = Response.substring(48, 80);
    InSource = Response.substring(80, 112);
 
    // Data
    IN_CUR_INSPECTION_MODE = Response.substring(112, 116);
    IN_CUR_OBJECT_ID = Response.substring(116, 180);
    IN_CUR_PROFILE_ID = Response.substring(180, 186);
    IN_CUR_BATCH_ID = Response.substring(186, 250);
    IN_OBJECT_INSPECTION_RESULT = Response.substring(250, 254);
    IN_ROI_DEFECT_LIST = Response.substring(254, 318);
    IN_SYSTEM_ERROR = Response.substring(318, 322);
    IN_SYSTEM_READY = Response.substring(322, 326);
     
    if