9/20/2013 8:10 PM  
Joined: 4/22/2010 Last visit: 3/1/2021 Posts: 5607 Rating: (674)

Hope this quote is about experience with other forum. Yes, a lot of questions get an answer read the manual, that's because the answer is oftenin it. If there is no direct answer in the manual, that means the question is going deeper as desribed in the manual, there are alway's some dedicated people here to try to find a solution for you. The experts on this forum and many others without this rank do a lot of work to help every one with a question. The only thing we ask is do a little by yourself and try to describe the problem as good as you can. By the way your question was detailed and clear, that''s why you get detailed answers. Regards, Marcjan 
Last edited by: Marcjan at: 9/20/2013 8:30 PMProblem solved? 

9/23/2013 8:20 AM  
Joined: 10/9/2012 Last visit: 12/11/2019 Posts: 46 Rating: (1) 
Right, here we are then, the final code. Tested with points in and outside of range. Found one bug, I declared #iDiv_Result as a byte, I am not sure what I was thinking of at the time but anyway, it coused some weird results during testing. Changed it to an integer and things are fine now. [code] L #DB_Num //Load variable in ACCU 1 T #iDB_Array //Transfer ACCU1 to TEMP var L #Level //Load variable in ACCU 1, move ACCU 1 to ACCU 2 RND //Convert the floatingpoint number in ACCU1 to an integer (32bit) L #Increment //Load variable in ACCU 1  25 is mm offset between array rows /I //Divide ACCU 2 by ACCU 1; store the result (quotient) in ACCU 1. T #iDiv_Result //Transfer the Quotient from ACCU1 to Temp Var CAD //Change Byte Sequence in ACCU 1 (32bit)(ABCD >> DCBA) CAW //Change Byte Sequence in ACCU 1L (16Bit) (ABCD >> ABDC) T #iDiv_Rest //25 divided by div_rest L #Increment L #iDiv_Rest /R T #rGradient //store gradient L #iDiv_Result L 4 *I // 4 bytes offset (REAL datatype Array) T #iArr_Index //Index, the array is REAL, 4 bytes per unit SLD 3 //Shiftleft accu1 by 3 bits  for byte borders in pointers LAR1 // load data to temporary mem Area One L #iDB_Array //Temp var containing block DB number OPN DB [#iDB_Array] L DBD [AR1,P#4.0] //dbd = data double word L DBD [AR1,P#0.0] // AR1 is temporary mem Area One, containg the 3bit shifted pointer R //delta Y axe (volume) L #rGradient //retrieve gradient /R // devide delta Y by Gradient L DBD [AR1,P#0.0] +R // add the offset to the calculated Yaxe position T #rValue //Final Calculated Value [/code] 
9/23/2013 8:52 AM  
Joined: 10/9/2012 Last visit: 12/11/2019 Posts: 46 Rating: (1) 
Hi Marcjan, Without cluttering up this thread too much I still wanted to respond to you. My remark was intended as a compliment to hlapak, not as a putdown to any forum experts here or on any other forums. In hindsight I could have formulated my remark nicer  but I was cought at a time where I am strugling with (email) support from various system vendors (I will spare you the gory details). Still, I take some pride in the fact that before posting on any forum I go through any related manual, look at example code and search any relevant forum before posting a question. I think that's enough said about this now, back to writing code. Henk 
This contribution was helpful to1 thankful Users 
9/26/2013 9:39 PM  
Joined: 11/25/2011 Last visit: 4/14/2020 Posts: 16 Rating: (1) 
Hi Henk, sorry for the late reply  I am at a commissioning. Regarding your question  you started it nice  having a DB with the index points (each 25mm) and the volume. If I were you, I would create a global DB and put a 1 dimension array of type struct, where the struct will be: 1 int for the index point, 1 real for the level, 1 real for the volume. You already know how to calculate the index  take a look upwards. Thus you will easily access the level and the volume and you won"t need that reverse calculation of the level what I wrote in the last code. Thus you can directly use the indirect addressing. If you have any bumps  let me know  I will be available after the 2nd of Oct. br izi

This contribution was helpful to1 thankful Users 
9/27/2013 6:50 AM  
Joined: 10/9/2012 Last visit: 12/11/2019 Posts: 46 Rating: (1) 
Hi Izi, thanks for your reply, I've got it all sorted and tested though. It dawned to me when I created the control logic that I needed a reverse lookup as well (from Volume to level), so I bit the bullit and (as you rightly sugested at the start) made a two dimentional array; Index[x,0] = height and Index[x,1] = Volume. The function I wrote has now got four inputs: 1) DB Number 2) PV 3) Boolean switch indicating lookup from Column x.0 (level) or Index x.1 (volume) 4) Previous Array index containing the succesfull lookup And three outputs: 1) Calculated value 2) first Array Index containing the data It took me a few days to get right but its working nicely now. I could add more code to check my input variables for validity (if you give a non2 dimentional array DB number weird things will happen) I could also add more optimised code for searching the Array  although saving the last Index and using that index (minus 2) as a starting point seems to work really really well. Anyway, onwards and upwards for me at the moment, trying to get my system ready for FAT testing. good luck with comissioning Izi Henk Edit: I cleaned up my sourcecode a bit so its a bit more presentable. I know there are a few things that can be done more efficiently but the main aim is to make the code as readable as possible. [code] L #DB_Num //Load variable in ACCU 1 T #iDB_Array //Transfer ACCU1 to TEMP var L 0 T #iOffSet T #iArr_Index //***************************************DETERMINE IF THE BLOCK IS COMPARING PV WITH ARRAY INDEX 0 OR 1********************************************* A #Dimention_0_OR_1 //RLO = 0 WHEN BIT IS FALSE JCN off0 // RLO TRUE, JUMP TO CODE TO WORK WITH INDEX 0, INSTEAD OF INDEX 1 L 4 // if true we need to offset the pointer T #iOffSet //***************************************OPEN DATABLOCK AND DETERMINE ARRAY LENGTH****************************************************************** off0: OPN DB [#iDB_Array] L DBLG //db length in bytes L 8 // 4 bytes, times 2 dimentions /I T #iArrayLength //******************************************DETERMINE IF PREVIOUS INDEX IS A VALID STARTING POINT FOR THIS SCAN (FOR EFFICIENCY)********* //***********************************************CHECK 1, #iIndexPrev < actual array size?****************************************************** L #iIndexPre // check if previous index is (not) less than #iArrayLength >=I // set RLO to false if the provided index is greater than the actual array length JCN res0 // on false jump to res0, that code will RESET INDEX TO 0 //***********************************************CHECK 2, #iIndexPrev > 3?*************************************************************** L 3 >=I // set the RLO to true if ACCU2 >= ACCU1, false otherwise JCN res0 // RLO = 0 >>> ACCU 2 is less than 2 (prolly 0) jump to the loop (#iArr_Index will be 0) //ACCU 2 is greater or equal to 3, proceed with code, check if the PV has not dropped out of range, start from beginning of array if so //***********************************************CHECK 3, ARRAY VALUE[INDEX] >= PV? *************************************************************** I // subtract 3 from the array index, if the PV went lower this will allow the loop to take 2 steps back and catch up again T #iArr_Index // save the array index value, safe to do now without risking underflow/going neggative L 8 // skipping through the array happens in 8 byte "hops" *I L #iOffSet // Either 0 or 4 when set to 4 it will effectively change the pointer call to [AR1,P#12.0] +I SLD 3 //Shiftleft accu1 by 3 bits  for byte borders in pointers LAR1 L DBD [AR1,P#8.0] //fetch the data record that lies two hops before the index given to the block, to compare with level reading L #PV >=R //if accu2 [array data] is greater than the PV, this means the PV took a big jump down, start from JCN jmp1 //RLO = 1 = BAD >> accu2 [array data] is greater than PV, bad  do not jump to loop code, reset #iArr_Index instead //********************CHECK FAILED  #iArr_Index HAS TO BE RESET BACK TO 0*************************************************************************** res0: L 0 //jumped to by code that checks if index is out of bounds T #iArr_Index L #iArrayLength // LOAD THE ARRAY LENGTH TO ACCU1 SO THE LOOP CAN USE IT AS THE COUNT DOWN COUNTER JU lop1 //********************ALL CHECKS DONE***************************************************************** jmp1: L #iArrayLength // LOAD THE ARRAY LENGTH INTO ACCU L #iIndexPre // SUBTRACT START INDEX, ARRAY LENGTH  STARTINDEX  to prevent index overflow I //***********************************************MAIN LOOP, FIND THE ARRAY POINTS SURROUNDING THE PV*************************** lop1: T #iLoopCounter L #iArr_Index L 8 // skipping through the array happens in 8 byte "hops" *I L #iOffSet // Either 0 or 4, when set to 4 it will effectively change the pointer call to [AR1,P#12.0] +I SLD 3 //Shiftleft accu1 by 3 bits  for byte borders in pointers LAR1 // load data to temporary mem Area One L DBD [AR1,P#8.0] L #PV >=R //accu2 (array point) is greater than measured level JC hit1 //Jump if RLO = 1 //********************************************DATA POINT NOT YET REACHED, INCREASE INDEX COUNTERS AND RELOOP******************* L #iArr_Index L 1 +I T #iArr_Index L #iLoopCounter LOOP lop1 // auto decrease accu1 (#iLoopCounter) //********************************************END OF LOOP*********************************************************************** //*******************************************IF NO VALID DATA WAS FOUND, PROGRAM TO USE LAST 2 VALUES AND EXTRAPOLATE **************** //*******************************************DATA SUCCESFULLY FOUND, CALCULATE LINIAR GRAPH INTERSECTION AND YAXE POINT************* hit1: L #iArr_Index // first reset any possible offset that might have been applied to LAR1 L 8 // skipping through the array happens in 8 byte "hops" *I SLD 3 //Shiftleft accu1 by 3 bits  for byte borders in pointers LAR1 //*******************************************CALCULATE DELTA X AND DELTA Y************* L DBD [AR1,P#8.0] // hit1 is a jump label called in the loop L DBD [AR1,P#0.0] R T #rDeltaX // delta x L DBD [AR1,P#12.0] //dbd = data double word L DBD [AR1,P#4.0] //AR1 is temporary mem Area One, containg the 3bit shifted pointer R //delta Y axe (volume) T #rDeltAY //*******************************************DELTA X AND DELTA Y CALCULATED************************ //*******************************************DETERMINE IF PROGRAM NEEDS DIMENTION 0 OR 1 OF THE ARRAY******************************* A #Dimention_0_OR_1 //RLO = 0 WHEN BIT IS FALSE JC DIM1 // RLO TRUE, JUMP TO CODE TO WORK WITH INDEX 1, INSTEAD OF INDEX 0 //*******************************************ARRAY DIMENTION 0 ******************************* L #PV // load in the pv L DBD [AR1,P#0.0] // subtract the x value of (0,0) on our graph from the pv >> array point [0] R // this is the point on x axces of our linear graph L #rDeltaX // retrieve span of x axe TAK // toggle accu1 and two, e.g. swap their contents, in preperation for division operation /R // Calculate Gradient (deltax / (pv  offset)) T #rGradient L #rDeltAY TAK /R L DBD [AR1,P#4.0] +R //add the offset to the calculated Yaxe position JU END //*******************************************ARRAY DIMENTION 1 ******************************* DIM1: L #PV // load in the pv L DBD [AR1,P#4.0] // subtract the x value of (0,0) on our graph from the pv >> array point [0] R // this is the point on x axces of our linear graph L #rDeltAY // retrieve span of x axe TAK // toggle accu1 and two, e.g. swap their contents, in preperation for division operation /R // Calculate Gradient (deltax / (pv  offset)) T #rGradient L #rDeltaX L #rGradient /R L DBD [AR1,P#0.0] +R //*******************************************ARRAY DIMENTION LOGIC DONE ******************************* END: T #rValue //Final Calculated Value L #iArr_Index T #iIndex //*******************************************FOR DEBUGGING/CHECKING, TOTAL AMOUNT OF LOOPS CODE WENT THROUGH********************** // L #iArrayLength // L #iLoopCounter // I // T #iTotalLoops [/code] 
Last edited by: HenkAnalfabeet at: 9/30/2013 7:11 AMadded STL source code 

9/13/2015 11:42 AM  
Joined: 9/3/2014 Last visit: 3/13/2019 Posts: 4992 Rating: (121) 
New question published by Aashish is split to a separate thread with the subject Writing program for reading 20 analog value in 30 seconds. Best regards 
Follow us on