Go Down

Topic: Using analog in to measure 5 parallel sensors (Read 1 time) previous topic - next topic

pouschkin

Hello all,

New to Arduino and not very experienced with electronics in general so I´ll appreciate any input. I´m looking to build a central controlling unit for my camper-van (monitor battery charge, indicate water levels, maybe even to control the charging) and there are many obstacles to tackle to do so.

But taking it one step at a time, I´d like to be able to measure water levels in my clean and dirty water tanks. I know there´s a capacitive approach to this but I´m thinking of a simpler solution. I have 5 on/off float censors which I´ll mount on different levels in the side of the tank. So 5 sensors per tank meaning I have a resolution of 20% filling. Now, instead of wasting 5 digital IO pins I was thinking to set it up with parallel resistors and read this through Analog In pin, whenever one float sensor changes state, the resistance changes, AnalogRead changes.

However, I cannot figure out which resistor values to use. When all sensors are open, I need a reading of 0v (GND through pull-down?) and when all are closed, I need a reading of 5v with 4 steps in between creating linear values in between.

Thanks in advance!!

MarkT

Wire each to 5v via 10k resistors, and use a 4k7 pull down to ground.  Then you'll see

0 sensors:  0V
1 sensor:  1.6V approx
2 sensors: 2.4V approx
3 sensors: 2.9V approx
4 sensors: 3.3V approx
5 sensors: 3.5V approx

You won't get a linear voltage relationship with a resistor network unless you drive it with
a constant current source, you can only measure ratios of resistance and ratios
involve division which is not linear.
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

pouschkin

Thanks for the reply. If I'd wire them with different resistors, I should be able to mimic a linear relationship, right? For that I need to know the amps that the analog in would consume

MarkT

You'll only get more linearity by making the output voltage range smaller, such as using a 100 ohm pull-down,
giving 0.0V, 0.049V, 0.098V, 0.145V, 0.192, 0.238V (which is much less noise tolerant).
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

JohnRob

Hi,


I see three things you might want to consider:

1) Will only one switch be on at a time?  Or can two possibly be on at the same time?  Consider if the water is sloshing and the hysteresis of the switches.

2) Is there a condition when all the switches will be open?

3) I wouldn't think you care about linearity as long as you know what the actual values are for each switch.  The rest can be dealt with in software.

Good luck.

Please do not PM me with thread based messages.  If your thoughts are worth responding,  the group should benefit from your insight.

PaulMurrayCbr

#5
Jul 18, 2017, 05:32 am Last Edit: Jul 18, 2017, 05:36 am by PaulMurrayCbr
If you want to be able to tell, from the voltage, what *combination* of switches are down by wiring them up to different-valued resistors, then if there are five inputs then there are 32 possible combinations of switches. This means that your resistors will have to have better than 3% tolerance - and in practice, they would have to be better than that for the larger valued resistors.

The usual way to muliplex N digital inputs into a single input is by using a parallel-in/serial-out shift register.

A typical chip will have 7 or 8 input pins, an enable pin, and a clock and data pin. So you need three pins to operate it. You raise (or lower) the enable pin, then use the arduino "shiftIn" library function to read the state from the data and clock pins. This winds up in a byte value. You then use the C++ bit-fiddling operations to pull out the individual bits.

The cute thing is that these devices can be chained to read any number of digital inputs using only 3 pins to get the data into the arduino.

(edit) Oh - you have only 3 inputs. Well, that's probably doable, then. You'd still be better off learning to use a shift register, They are five bucks or less.

(edit 2) Hang on - you have a sequence of 5 float sensors? Well, that's even easier if you are happy to use an analog in. What MarkT said:
Quote
Wire each to 5v via 10k resistors, and use a 4k7 pull down to ground.
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

pouschkin

Thank you all for the feedback, super useful!

1) Will only one switch be on at a time?  Or can two possibly be on at the same time?  Consider if the water is sloshing and the hysteresis of the switches.

2) Is there a condition when all the switches will be open?

3) I wouldn't think you care about linearity as long as you know what the actual values are for each switch.  The rest can be dealt with in software.

Good luck.

Sensors will be mounted in the wall of the tank, they will close once they get submerged; so the higher the water level, the more sensors are switched. Always in the same order. All sensors are open when the tank is empty, they´re all closed when the tank is full. Sloshing is not an issue; I plan to check levels only when the van is stationary.

I guess linearity is not essential if the code can recognise the steps of the AnalogRead as per MarkT´s table.

Again, thanks all!

The usual way to muliplex N digital inputs into a single input is by using a parallel-in/serial-out shift register.
Even if I might not use it in this instance, I´ll still check them out, they sound like usefull little converters. Thanks for the tip!

PaulMurrayCbr

#7
Jul 19, 2017, 05:09 am Last Edit: Jul 19, 2017, 05:30 am by PaulMurrayCbr
Sensors will be mounted in the wall of the tank, they will close once they get submerged; so the higher the water level, the more sensors are switched.
So, you would treat the first closed switch (counting from the top) as being the fuel level, and accept that the fuel might slosh a bit. Or it might be easier to just count 'em.

To handle noisy data like this, I really like a simple software low-pass filter - which is not nearly as intimidating as it sounds. The key is to sample the input at some known, constant rate.

Code: [Select]

float fuelLevel; // a value from 0 to 5
const float fuelLevelDamping = .75; // 0 is no damping, 1 is infinite damping
const unsigned long fuelSampleIntervalMs =  1000L; // sample every second
unsigned long fuelSampleMs = millis();

void checkFuel() {
  // throttlw the rate at which we take samples
  if(millis() - fuelSampleMs < fuelSampleIntervalMs) return;
  fuelSampleMs = millis(); // or fuelSampleMs += fuelSampleIntervalMs;

  // take a sample
  int n = readNumberOfSensorsClosed(); // a value between 0 and 5

  // perform low-pass filtering
  fuelLevel = fuelLevel * fuelLevelDamping
          + n * (1 - fuelLevelDamping);

}


Each sensor read makes the fuelLevel value migrate slowly towards that value. If the fuel sloshes about, the noise will tend to get ignored. The fuelLevel - in theory - will never be exactly 0 or exactly 5. So you need to round it.
Code: [Select]

roundedFuelLevel = (int) (fuelLevel + .5);
// or
roundedFuelLevel = (int) (fuelLevel * (5.999 / 5.0));


For extra accuracy, determine the frequency at which fuel sloshes in the tank (in ms), and make the sample interval to be not a simple harmonic of that value. I always like multiplying things by the golden ratio 1.616 .
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

MarkT

Firstly you've transmuted 'water' into 'fuel', and quote from #6: "Sloshing is not an issue; I plan to check levels only when the van is stationary"...
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

TomGeorge

#9
Jul 19, 2017, 01:49 pm Last Edit: Jul 19, 2017, 01:50 pm by TomGeorge
Wire each to 5v via 10k resistors, and use a 4k7 pull down to ground.  Then you'll see

0 sensors:  0V
1 sensor:  1.6V approx
2 sensors: 2.4V approx
3 sensors: 2.9V approx
4 sensors: 3.3V approx
5 sensors: 3.5V approx

You won't get a linear voltage relationship with a resistor network unless you drive it with
a constant current source, you can only measure ratios of resistance and ratios
involve division which is not linear.
Will be the easiest, all you need to do is
display EMPTY when input is < .5V
display 20% when input is > .5 and < 2.0
display 40% when input is >2.0 and < 2.6
display 60% when input is >2.6 and < 3.0
display 80% when input is > 3.0 and <3.4
display 100% or FULL when input is > 3.4

That is with 5V, not a const current source.
Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

TomGeorge

#10
Jul 19, 2017, 02:43 pm Last Edit: Jul 19, 2017, 02:44 pm by TomGeorge
Hi,
MarkT idea with revised resistor values to give some spacing between readings.


Tom... :)
Everything runs on smoke, let the smoke out, it stops running....

pouschkin

Wow guys, thanks again for the feedback. Indeed, I don't think i need dampening but it's still an interesting point. TomGeorge, that approach gives a better distribution and probably is the closest to a linear distribution. Btw, what program did you use to make that schematics? Myself, I use TinyCAD.

Cheers!

TomGeorge

Hi,
I use  ExpressPCB.

https://www.expresspcb.com/expresssch/

Free download, no overheads or stupid adverts or extra junk apps.

Tom.. :)
Everything runs on smoke, let the smoke out, it stops running....

PaulMurrayCbr

So, we need ratios 0:5, 1:4, 2:3, 3:2, 4:1, 5:0 in out voltage divider. In terms of the pull-down R1, the CONDUCTANCE of the pull-up NETWORK needs to be 0,1/4,2/3, 1.5,4,∞ to get these ratios. IOW: 0/12, 3/12, 8/12, 18/12, 48/12, ∞/12

Because we just add conductances when resistors are put in parallel, this means that the sequence of conductances (in terms of R1) needs to be 3/12, 5/12, 10/12, 30/12, and ∞/12 for R2 to R6.

With a 4.7k pull-down resistor, this gives us 18.8, 11.3, 5.6, 1.2 kohms, and a short to Aref.

Which is pretty damn close to reply #10, with the exception that I'm suggesting that R5 be 1k2 rather than 2k2, and that R6 can just be a short. Oh, and use Aref rather than +5 - it's usually the same thing, anyway.
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

Go Up