Using ERP-Scale to add weighing bar to a PI-Sheet

You are here:

Using ERP-Scale’s built-in web server, a weighing meter (or progress bar) can be displayed in the PI-Sheet. This is ideal for use when dispensing materials.

  • Does not require an OPC server
  • Does not require SAP Plant Connectivity (PCo)
  • Works with any scale (with a PC interface)
The following steps are required to create a prototype PI-Sheet in your SAP system:
These instructions are supplied to demonstrate the functionality of ERP-Scale. They do not offer a full solution for dispensing or weighing of materials. They are supplied by Pocket Programs without any warranty.
The progress bar is used to indicate to the operator if the weight is within the target range, however there is no validation that the actual weight falls within allowed tolerances. This validation functionality must be added to the PI-Sheet before it is used in a productive environment.


  • Install the latest version of ERP-Scale (Version 4.0.1 build B13.A14 or later).
  • Connect the scale to the PC and define the communication settings (see ERP-Scale user manual)
  • Get a trial licence for ERP-Scale

Add data fields to the parsing settings in ERP-Scale

Data fields are used to write the target values from SAP ODA.
In ERP-Scale, create the following data fields on the Data parsing page :

  • UNIT

Also, create the following mapping of the data fields WEIGHT and UNIT on the HUPAST tab:

Activate ERP-Scale’s web server and define the HTML and JSON templates

The web server built into ERP-Scale is used to display the weighing progress bar in the PI-Sheet. First activate the web server using the ERP-Scale configuration utility:

To display the progress bar in the PI-Sheet, ERP-Scale requires two web templates:

  1. BAR – Type text/html used to display the weighing progress bar
  2. JSON – Type text/json

The content of each template is defined below:


This code has been updated to support SAP GUI release 7.30. It requires ERP-Scale PQS V4.0.1 build B14.H15 or later.
The target bar graphic is produced using the vector graphics library from Walter Zorn.
<!DOCTYPE html>
<title>ERP-Scale target weight bar</title>
<script src="wz_jsgraphics.js" type="text/javascript"></script>
<table  CELLPADDING="0" CELLSPACING="0" width="100%" id="toptable">
<td width="100px" ><font color="blue" face="verdana">Material:</font></td>
<td width="300px" style="float: left;"><font color="blue" face="verdana"><div id="material"></div></font></td>
<td width="400px" rowspan="3" align='top';">
 <div id="layer0" width="400px" height="50px" style="position: absolute; left: 400px; top: 20px; z-index: 0; opacity: .99;  "></div>
 <div id="layer1" width="400px" height="50px" style="position: absolute; left: 400px; top: 20px; z-index: 1; opacity: .99"></div>
<td rowspan='3' align='right'><a href="" target="_blank"><img src="PP_Logo_Text.png"></a></td></tr>
<tr><td  width="100px"><font color="blue" face="verdana">Target:</font></td>
<td width="300px"><font color="blue" face="verdana"><div id="target"></div></font></td></tr>
<tr><td  width="100px"><font color="blue" face="verdana">Actual:</font></td>
<td width="400px"><div id="actual"></div></td></tr>
<script type="text/javascript">
var jg0 = new jsGraphics("layer0");
var jg1 = new jsGraphics("layer1");
var xmlhttp = new XMLHttpRequest();
xmlhttp.onreadystatechange=function() {
  if ((xmlhttp.readyState==4) && (xmlhttp.status==200)) {
    var jsondata=eval("("+xmlhttp.responseText+")");
    updatebar(jsondata, jg0, jg1,30);
var jct = 0;
var  gv_pat_green = "#4AA02C";
var  gv_pat_grey = "#FDD017";
var  gv_pat_red = "red";
var gv_pat_blue = "#2B60DE";
var gv_shift = 3;
var gvTxt ="";
var gvMin = 0;
var gvMax = 0;
var gvTolHigh = 0;
var gvTolLow = 0;
var gvDTolHigh = 0.05;  // Default upper tolerance
var gvDTolLow = 0.05;   // Default lower tolerance
var gvTarget = 0;
var gvUnit = "";
var gvPrompt1 = "";
var gvPrompt2 = "";
var gvPrompt3 = "";
var gvStep = 0;
var gvWeight=0;
var lvPercent = 0;
var int=self.setInterval(function(){update()},1000);
function update()
        jct=jct+1;"GET", "?getweight&device=[%scale%]&template=json&dummy="+ (new Date()).getTime(),true);
function updatebar(data,jg0,jg1,height)
       var chf = false;
       var chb = false;
       var width = document.getElementById("layer0").parentElement.clientWidth;
       var widthTop = document.getElementById("toptable").clientWidth;
       if (widthTop > 1000) {width=widthTop-550;}

// Are min and max set?
       if ((Number(data.tmin) > 0) && (Number(data.tmin) != gvMin)) {
          gvMin = Number(data.tmin);
          chb = true;
       if ((Number(data.tmax) > 0) && (Number(data.tmax) != gvMax)) {
          gvMax = Number(data.tmax);
          chb = true;
// Are high and low tolerances set?
       if ((Number(data.thigh) > 0) && (Number(data.thigh) != gvTolHigh)) {
          gvTolHigh = Number(data.thigh);
          gvMax = Math.round((gvTarget * (1 + gvTolHigh))*1000)/1000;
          chb = true;

       if ((Number(data.tlow) > 0) && (Number(data.tlow) != gvTolLow)) {
          gvTolLow = Number(data.tlow);
          gvMin =Math.round((gvTarget * (1 - gvTolLow))*1000)/1000;
          chb = true;
// Get target weight
       if (Number(data.tweight) != gvTarget) {
           gvTarget = Number(data.tweight);
           chb = true;
           if (Number(data.tmin) == 0) {
               if (gvTolLow > 0) {
                  gvMin =Math.round((gvTarget * (1 - gvTolLow))*1000)/1000;
               else {
                  gvMin =Math.round((gvTarget * (1 - gvDTolLow))*1000)/1000;
           if (Number(data.tmax) == 0 ) {
               if (gvTolHigh > 0) {
                  gvMax = Math.round((gvTarget * (1 + gvTolHigh))*1000)/1000;
               else {
                  gvMax = Math.round((gvTarget * (1 + gvDTolHigh))*1000)/1000;
       if (data.tunit != gvUnit) {
           gvUnit = data.tunit;
          chb = true;
       if (data.text != gvTxt) {
          gvTxt = data.text;
          chb = true;
       if (chb) {
          gvPrompt1 = "<b>"+ gvTxt + "</b>";
          gvPrompt2 = "(" + gvMin +"-" + gvMax +") <b>" + gvTarget + " " + gvUnit + "</b>";
          gvPrompt3 = "<font color=red face='verdana'><b>*" + data.weight + " "+data.unit +"</b></font>";
          document.getElementById("actual").innerHTML = gvPrompt3;
          document.getElementById("material").innerHTML = gvPrompt1;  
          document.getElementById("target").innerHTML = gvPrompt2;  
          gvWeight = 0;
          var barMax = gvMax * 1.1;
          gvStep = width / barMax;
          var minStart = Math.floor(gvMin * gvStep);
          var targetPos = Math.floor(gvTarget * gvStep);
          var maxStop = Math.floor(gvMax * gvStep);
          var bufferStop = Math.floor(barMax * gvStep);
           jg0.fillRect (maxStop,gv_shift,bufferStop-maxStop,height+gv_shift);
           jg0.drawLine(targetPos-1,0,targetPos-1, height+gv_shift+gv_shift);
           var tgtTxt = gvTarget + " " + gvUnit;
        var lvWt;
           lvWt =  Number(data.weight);
        if (lvWt != gvWeight) {
        if (gvTarget == 0) {
          lvPercent = 0;
        else {
          lvPercent = Math.round(lvWt/gvTarget*1000)/10; 
        gvWeight = lvWt;
        if ((gvWeight == 0)||(lvWt < gvMin)||(lvWt > gvMax)) {
           gvPrompt3 = "<font color=red face='verdana'><b>"+lvWt+" "+data.unit+" ("+lvPercent+"%)"+"</b></font>";
        else {
           gvPrompt3 = "<font color=green face='verdana'><b>"+lvWt+" "+data.unit+" ("+lvPercent+"%)"+"</b></font>";
        if ( gvTarget > 0) {
           var ht = height-20;
           var wd = width;
           var barEnd = Math.floor(gvWeight * gvStep);
           barEnd =  Math.min(barEnd, width);
           jg1.fillRect (0,11+gv_shift,barEnd,ht);


"weight"  : "[%Weight%] ",
"unit"       : "[%Unit%]",
"text"       : "[%request_text%]",
"tweight"  : "[%target_weight%]",
"tunit"      : "[%target_unit%]",
"tmin"        : "[%target_min%]",
"tmax"       : "[%target_max%]",
"thigh"      : "[%target_tol_high%]",
"tlow"       : "[%target_tol_low%]"


At this stage you can test the ERP-Scale web server templates.

Using Internet Explorer (use IE as this is what the SAP GUI uses, do not use Chrome) to browse to:

You should see this web page displayed and the actual weight should show the weight from the scale:

Create an OPC Data Access server for ERP-Scale in SAP ODA

ERP-Scale uses an RFC destination to communicate with SAP ODA. To create the RFC destination in SAP, follow these steps:

  1. In the SAP IMG, select the task “Define RFC Destination for SAP ODA”

  2. Create a new TCP/IP connection:

Add Data Access Items for the target weight in SAP ODA

The PI-Sheet use ODA to communicate with ERP-Scale. Data access items are required to write the target values (weight, unit and tolerances) and read the actual weight and unit.

Use transaction COOPC1 to add new ODA data access items.

The data access item SCALE_ACTUAL_WEIGHT is used to read the actual weight from ERP-Scale. It is mapped to the data field WEIGHT as follows:

The data access item SCALE_ACTUAL_UNIT is used to read the current unit from ERP-Scale. It is mapped to the data field UNIT as follows:

Use cached data access for the SCALE_ACTUAL_UNIT

The following data access items are required to write the target values to ERP-Scale:

Create two new PI characteristics in SAP

In the prototype the PI-Characteristics Z_ES_TOLERANCE_LOW and Z_ES_TOLERANCE_HIGH are used to define the under and over tolerance (as a factor, e.g. 0.1 = 10%). The prototype PI-Sheet uses fixed values, however material specific tolerances could be determined using a function module.

Create the following PI-Characteristics using transaction O25C:


Create a General Process Instruction Category

The table that displays the material list in the PI-Sheet is defined as a Process Instruction Category (General) in SAP.

Use transaction O12C to create a new category:

See the attached Excel workbook for the required PI-Instructions. The low and high tolerances are defined in lines 130 and 140.

Change the characteristic values in the PPPI_EXPORT_DATA characteristics to match your ODA data access items.

Assign the Process instruction category to the control recipe destination

The newly created process instruction category must be assigned to the control recipe destination using transaction O10C.

Also consider if the Process Manufacturing Cockpit will require reactivation.

Add process instructions for the weighing bar to the master recipe

In the master recipe, add process instructions to display the progress bar. Use transaction C202:

Change the characteristic values in the PPPI_EXPORT_DATA characteristics to match your ODA data access items

See the attached Excel workbook for details of the PI characteristics.

The longtext of the PPPI_LAYOUT (0002) is as follows:

Check that the layout (especially line breaks) is as shown above

The text is below:

<?xml version="1.0"?>
scrolling ="No" id="_SELECT_"
marginwidth="0" marginheight="0">
Was this article helpful?
Dislike 0
Views: 2187
Still have questions? Create a support ticket