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 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.
Prerequisites
- 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 :
- WEIGHT
- UNIT
- REQUEST_TEXT
- TARGET_WEIGHT
- TARGET_UNIT
- TARGET_TOLERANCE_LOW
- TARGET_TOLERANCE_HIGH
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:
- BAR – Type text/html used to display the weighing progress bar
- JSON – Type text/json
The content of each template is defined below:
BAR
<!DOCTYPE html> <html> <head> <title>ERP-Scale target weight bar</title> <script src="wz_jsgraphics.js" type="text/javascript"></script> </head> <body> <table CELLPADDING="0" CELLSPACING="0" width="100%" id="toptable"> <tr> <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> <td rowspan='3' align='right'><a href="http://www.pocketprograms.com" 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> </table> <script type="text/javascript"> var jg0 = new jsGraphics("layer0"); var jg1 = new jsGraphics("layer1"); var xmlhttp = new XMLHttpRequest(); xmlhttp.onreadystatechange=function() { try { if ((xmlhttp.readyState==4) && (xmlhttp.status==200)) { var jsondata=eval("("+xmlhttp.responseText+")"); updatebar(jsondata, jg0, jg1,30); }; } catch(err) { } }; 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; xmlhttp.open("GET", "?getweight&device=[%scale%]&template=json&dummy="+ (new Date()).getTime(),true); xmlhttp.send(null); } 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.clear(); jg0.setColor(gv_pat_red); jg0.fillRect(0,gv_shift,minStart,height+gv_shift); jg0.setColor(gv_pat_green); jg0.fillRect(minStart,gv_shift,maxStop-minStart,height+gv_shift); jg0.setColor(gv_pat_red); jg0.fillRect (maxStop,gv_shift,bufferStop-maxStop,height+gv_shift); jg0.setColor("black"); jg0.setStroke(1); jg0.drawRect(0,gv_shift,bufferStop,height+gv_shift); jg0.setStroke(3); jg0.setColor(gv_pat_blue); jg0.drawLine(targetPos-1,0,targetPos-1, height+gv_shift+gv_shift); jg0.setFont("arial","15px",Font.BOLD); var tgtTxt = gvTarget + " " + gvUnit; jg0.drawStringRect(tgtTxt,targetPos-50,40,100,"center"); jg0.paint(); jg1.clear(); jg1.paint(); } var lvWt; try { lvWt = Number(data.weight); } catch(err) { lvWt=0; } 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>"; } document.getElementById("actual").innerHTML=gvPrompt3; if ( gvTarget > 0) { var ht = height-20; var wd = width; jg1.clear(); var barEnd = Math.floor(gvWeight * gvStep); barEnd = Math.min(barEnd, width); jg1.setColor(gv_pat_grey); jg1.fillRect (0,11+gv_shift,barEnd,ht); jg1.paint(); } } } </script> </body> </html>
JSON
{ "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%]" }
Testing:
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:
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:
- In the SAP IMG, select the task “Define RFC Destination for SAP ODA”
- 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:
- SCALE_REQUEST_TEXT mapped to SCALE.REQUEST_TEXT
- SCALE_TARGET mapped to SCALE.TARGET_WEIGHT
- TARGET_UNIT mapped to SCALE.TARGET_UNIT
- SCALE_TOLERANCE_LOW mapped to SCALE.TARGET_TOLERANCE_LOW
- SCALE_TOLERANCE_HIGH mapped to SCALE.TARGET_TOLERANCE_HIGH
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:
- Z_ES_TOLERANCE_LOW
- Z_ES_TOLERANCE_HIGH
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.
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.
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:
See the attached Excel workbook for details of the PI characteristics.
The longtext of the PPPI_LAYOUT (0002) is as follows:
The text is below:
<?xml version="1.0"?> <LAYOUT> <FRAMESET ROWS="*,84px"> <FRAME SRC="#DOCUMENT#"></FRAME> <FRAME SRC="http://atom:8080/getweight?device=ind449&template=bar&command=WEIGHBAR" scrolling ="No" id="_SELECT_" marginwidth="0" marginheight="0"> </FRAME> </FRAMESET> </LAYOUT>