// Resistive tank sender converted to litres and gallons [here 18 element reed switch sender) // written C. Michael Feb 2018 // precision of sender in this example is around 2 galls; 10 litres. // with output to 3-digit voltmeter LED. // PWM ouput to voltmeter either needs RC damping or (as here) a small correction applied. /* voltage read in is val = V * res / (RES0+res) with V=5 volts: 5V val 0v | RES0 | res | "res" is leads to resistive sender 5V pinA3 GND */ long RES0 = 257L; // ohms - divider circuit - actual value used - similar size to RESVAL // Tank sender details => int NRES=18; // 0,..17 from top: ohms; mm level above sender bottom (average up/down) int RESVAL[] = {34, 42, 51, 60, 69, 78, 87, 97, 106, 114, 121, 129, 135, 143, 165, 187, 214, 244}; int LEV[] = {353, 334, 311, 291, 271, 249, 229, 206, 186, 165, 144, 121, 102, 78, 58, 37, 19, 4}; // Tank details Volume in litres corresponding to levels LEV[] int VOL[] = {458, 437, 412, 391, 369, 345, 324, 299, 277, 254, 232, 207, 186, 160, 139, 119, 96, 80}; //int DEPOFF = 70; // mm to bottom of tank from bottom of sender //long LTS_M= 1082L; // from tank geometry 1.082 litre per mm -> 1082 litre per metre int inPin = 3; // resistor join voltage connected to analog pin A3 int pwmPin = 9; // output pin supporting PWM int res = 0; // measured resistance of sender long prod; // use long (4-byte) integers to have precision [faster than floats] int val = 0; int nmin, nmint, i, imin; void setup() { pinMode(pwmPin, OUTPUT); Serial.begin(9600); // serial output option is for testing only } void loop() { val = analogRead(inPin); // read the input pin 1023 is 5v at A3 if ( val > 1020 ) { val = 900; } // in case of open circuit to sender prod = val * RES0; // long: since product spills over 2 byte int res = prod / ( 1023L - val ); Serial.print(" Measured R= "); Serial.print(res); imin = 0; nmin = abs(RESVAL[0]-res) ; for (i = 1; i < NRES; i++){ nmint = abs(RESVAL[i]-res); if ( nmint < nmin ) // search for nearest fit {nmin = nmint; imin = i; } } Serial.print(" Closest match res="); Serial.print(RESVAL[imin]); Serial.print(" level in mm= "); Serial.print(LEV[imin]); Serial.print(" litres="); Serial.println(VOL[imin]); // convert Volume to (readable: < 5V) voltage for display prod = 255L * VOL[imin]; // 5.00 volts is 255; choose VOL/100 as Volts //val = prod / 500L; // assume 5V nominal output level and RC smoothing of PWM val = prod / 506L + 3 ; // correct for PWM effects (no-3)*5.1/255 matches V if ( res-RESVAL[NRES-1] > 100 ) { val = 0; } // to show open circuit sender if ( res < 10 ) { val = 255; } // to show short circuit sender analogWrite(pwmPin, val); delay(4000); // 4 sec delay // alternate litres and gallons 0.22 gall = 1 litre prod = prod * 22L ; val = (prod + 25300L) / 50600L + 3 ; // round to nearest integer by adding 0.5 and correct PWM analogWrite(pwmPin, val); delay(4000); }