I use a level sensor to measure liquid level in a non linear tank and I need to convert the measured level in mm to volume in liters.
The look up table of the tank looks like below:
The values in between 0-9, 10-19 etc will be calculated using linear interpolation.
Any suggestions or programing examples on how to implement the aforementioned algorithm are welcomed.
I think the values in the table should be entered into a two dimentional array and then I need to make a search for an appropriate value.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
TYPEudtSoundingTable:STRUCT
  Level:ARRAY[0..10]OFREAL;
  Volume:ARRAY[0..10]OFREAL;END_STRUCTEND_TYPE
As for the code, I use a modified binary search.
As parameters, I pass my level array and the actual level of the tank and the function will return the upper and lower indexes between which my value is.
FUNCTIONFindClosest1DVAR_INPUTÂ Â key:REAL;END_VARVAR_IN_OUTÂ Â arr:ARRAY[*]OFREAL;END_VARVAR_OUTPUTÂ Â out1:INT;Â Â out2:INT;END_VARVARÂ Â size:DINT;Â Â i:INT;Â Â j:INT;Â Â middle:INT;END_VAR
//Binarysearchsize:=UPPER_BOUND(arr,1);IFkey<=arr[0]THENÂ Â out1:=0;Â Â out2:=0;Â Â RETURN;END_IFIFkey>=arr[size]THENÂ Â out1:=TO_INT(size);Â Â out2:=TO_INT(size);Â Â RETURN;END_IFi:=0;j:=TO_INT(size);middle:=0;WHILE(i<j)DOÂ Â Â Â middle:=(i+j)/2;Â Â IFkey=arr[middle]THENÂ Â Â Â out1:=middle;Â Â Â Â out2:=middle;Â Â Â Â RETURN;Â Â END_IFÂ Â Â Â IFkey<arr[middle]THENÂ Â Â Â Â Â Â Â IF(middle>0)AND(key>arr[middle - 1])THENÂ Â Â Â Â Â Â Â Â Â Â Â IFkey<0THENÂ Â Â Â Â Â Â Â out1:=middle-1;Â Â Â Â Â Â Â Â out2:=middle;Â Â Â Â Â Â ELSEÂ Â Â Â Â Â Â Â out1:=middle;Â Â Â Â Â Â Â Â out2:=middle-1;Â Â Â Â Â Â END_IFÂ Â Â Â Â Â RETURN;Â Â Â Â END_IFÂ Â Â Â Â Â Â Â j:=middle;Â Â Â Â Â Â Â Â ELSEÂ Â Â Â Â Â Â Â IF(middle<size)AND(key<arr[middle + 1])THENÂ Â Â Â Â Â out1:=middle;Â Â Â Â Â Â out2:=middle+1;Â Â Â Â Â Â RETURN;Â Â Â Â END_IFÂ Â Â Â Â i:=middle+1;Â Â Â Â Â Â END_IFEND_WHILE
And after, I do a Linear Interpolation.
FUNCTIONLinearInterpolation:REALVAR_INPUT
  X:REAL;
  X1:REAL;
  Y1:REAL;
  x2:REAL;
  Y2:REAL;END_VARVAREND_VAR
IFY1<>Y2THENÂ Â LinearInterpolation:=Y1+(X-X1)*((Y2-Y1)/(X2-X1));ELSEÂ Â LinearInterpolation:=Y1;END_IF
Bellow is an example on how I use them:
PROGRAMProgVAR  Tank1:udtSoundingTable:=(Level:=[0,1,2,3,4,5,6,7,8,9,10],Volume:=[12.3,15.8,19,21.3,25.9,29,32.3,34,36,38,40]);  ActualLevel:REAL;//Modifythis  Volume:REAL;  x1:INT;  x2:INT;END_VAR
I use a level sensor to measure liquid level in a non linear tank and I need to convert the measured level in mm to volume in liters.
The look up table of the tank looks like below:
mm : lt
0 : 53
10 : 78
20 : 99
.
.
1990:13423
2000: 13478
The values in between 0-9, 10-19 etc will be calculated using linear interpolation.
Any suggestions or programing examples on how to implement the aforementioned algorithm are welcomed.
I think the values in the table should be entered into a two dimentional array and then I need to make a search for an appropriate value.
I prefer to have a struct like this:
As for the code, I use a modified binary search.
As parameters, I pass my level array and the actual level of the tank and the function will return the upper and lower indexes between which my value is.
And after, I do a Linear Interpolation.
Bellow is an example on how I use them: