/WaterMix

Arduino library for mixing water of different temperatures.

Primary LanguageC++MIT LicenseMIT

Arduino CI Arduino-lint JSON check GitHub issues

License: MIT GitHub release PlatformIO Registry

WaterMix

Arduino library for mixing water with different temperatures.

Description

Warning: Experimental

Experimental library for elementary math of mixing certain amounts of water or other (same) liquids with different temperatures.

The library provides math add() for mixing a volume of a liquid with temperature T1 with another volume of the same liquid with temperature T2. The WaterMix class of the library has water specific functions. The library does not support mixing different liquids as that would need the density function for every liquid involved. Furthermore not all liquids mix well with each other.

The add() function can be called multiple times, e.g. to mix more than two amounts of liquids. One can also mix an other LiquidMix object (same liquids).

Besides the add() the library supports:

  • div() to "split the liquid in equal amounts" and a
  • mul() to multiply it (magically) and
  • sub() to remove part of the liquid.

This library is meant to be useful e.g. by doing "water math" for aquaria or cooking. Also the library is well suited for basic educational purposes.

Since version 0.1.2, the library has a base class, named LiquidMix which can do the basic math. The extended math like in WaterMix needs a density() function and cannot be done as the liquid is unknown.

For now the library is experimental and refactoring is expected. If you have requests, questions or ideas, let me know by opening an issue.

By adding the LiquidMix base class the library allows easy derived classes like the WaterMix.

Limitations

The LiquidMix uses a generic volume parameter instead of gallons or liters as this way any user selected unit can be used. However you must use the chosen units consistently as the library cannot handle different units simultaneously. To use different units for volume you can convert them with the library named VolumeConverter.

For the LiquidMix the temperature unit can also be chosen by the user and can be Kelvin, Celsius, Fahrenheit or other. However you must use the chosen units consistently as the library cannot handle different units simultaneously. Check Temperature library below for conversion.

The WaterMix class must use the Celsius scale as the density() function used is defined in degrees Celsius.

Accuracy

The working range for temperature is not tested e.g. with real water. It is expected to work quite well for water with a range from 5°C to 80°C. In the basic math the add() function assumes there is no expansion so the density is identical for both volumes of waters.

Of course this assumption is incorrect, therefore there will be a difference between the theoretical values and doing the mixing in practice. However these delta's are expected to be small, less than 1% in many cases. Given the accuracy of volume measurement and temperature measurement, this delta of 1% will often be acceptable.

If one wants a more exact answer, one could use WaterMix class. This class supports the addExact() function which compensates for the density of the water at a given temperature. This function is much slower but will provide a more exact answer.

Related

Interface

#include "WaterMix.h"

LiquidMix (base class)

To be used with any liquid.

  • LiquidMix() constructor, starts with no liquid of 0°
  • void begin(float volume = 0, float temperature = 0) sets initial values, default no liquid of 0°.
  • void add(float volume, float temperature) add an amount of liquid with temperature to the "LiquidMix".
  • void sub(float volume) subtract a volume from the "LiquidMix". Temperature won't change.
  • void div(float nr) divide the amount of liquid, same temperature.
  • void mul(float nr) multiply the amount of liquid, same temperature.
  • float volume() get the current volume.
  • float temperature() get the current temperature.

WaterMix

WaterMix is specific for water and has the following additional functions:

  • WaterMix() constructor, starts with no water of 0°
  • void addExact(float volume, float temperature) add an amount of water with temperature to the "WaterMix". The math uses the density of the water at the given temperature. This is slower as add() but more exact. Note the temperature must be in °C.
  • float mass() get the mass of the current volume. Water only!
  • float volume2mass(float volume, float temperature) idem, Water only! Use volume == 1 to get the density of water at the given temperature. Assumption is no pressure.
  • float mass2volume(float mass, float temperature) idem, Water only!

Performance

Most functions are minimal and fast, the ones that do the core math are add() and addExact(). The WaterMix_exact.ino sketch provides performance figures shown here. Note that the addExact() differs in runtime as it uses a linear lookup for the density so the numbers below are indicative.

Tested on UNO, 16 MHz.

Version Function time (us) Notes
0.1.1 add() 72
0.1.1 addExact() 576 most accurate

Note it is possible to improve the performance of the lookup of the density by reducing the amount of interpolation points in the tables (at your own risk). This will reduce the accuracy however still be better than the faster add().

Performance of addExact() can be improved by caching the mass of the water. As this is needed for every next addExact(). As the volume can be manipulated by div() et al, there must be additional code and/or a "dirty" flag. To be investigated.

Finally the lookup can be improved by a binary search, however previous experience indicate that this only improves above a certain number of elements (~20).

Volumetric Coefficient of Expansion

The VCE is related to density and not supported in the library. Math needs to be understood / investigated. (0.1.1 supports an addExact() for water only, temperature in °C)

The VCE is useful as background information as the theoretical volumes calculated in this library will differ from reality due to the VCE effect. This difference depends on the liquid used and the delta temperature.

Water

The VCE of water depends on the temperature.

Source: - https://www.engineeringtoolbox.com/water-density-specific-weight-d_595.html

Temp °C density % wrt 4°C V.C.E (*10-4) Notes
0.1 0,9998495 0,0125 -0.68 note negative value
1 0,9999017 0,0073 -0.50 note negative value
4 0,9999749 0,0000 0.003
10 0,9997000 0,0275 0.88
15 0,9991026 0,0873 1.51
20 0,9982067 0,1771 2.07
25 0,9970470 0,2937 2.57
30 0,9956488 0,4345 3.03
35 0,9940326 0,5978 3.45
40 0,9922152 0,7821 3.84
45 0,9902100 0,9861 4.20
50 0,9880400 1,2079 4.54
55 0,9856900 1,4492 4.86
60 0,9832000 1,7062 5.16
65 0,9805500 1,9810 5.44
70 0,9777600 2,2720 5.71
75 0,9748400 2,5784 5.97
80 0,9717900 2,9003 6.21
85 0,9686100 3,2381 6.44
90 0,9653100 3,5911 6.66
95 0,9618900 3,9594 6.87
100 0,9583500 4,3434 7.03

Other liquids

Unknown if these liquids are expanding linear or not.

Source: - https://www.engineeringtoolbox.com/cubical-expansion-coefficients-d_1262.html (extended table)

Liquid V.C.E. per °C V.C.E. per °F
Acetone 0.00143 0.00794
Alcohol, ethyl (ethanol) 0.00109 0.000606
Alcohol, methyl (methanol,CH3OH) 0.00149 0.000828
Calcium Chloride, 5.8% 0.00025 0.00014
Engine oil 0.0007 0.00039
Ethylene glycol 0.00057 0.000312
Gasoline 0.00095 0.000528
Glycerine (glycerol) 0.00050 0.000278
Oil (unused engine oil) 0.00070 0.000389
Olive oil 0.00070 0.000389
Paraffin oil 0.000764 0.000424
Petroleum 0.0010 0.00056
Potassium chloride, 24.3% 0.00035 0.000194
Sodium 0.00027 0.00015
Sodium chloride, 20.6% 0.00041 0.000228

Future

Must

  • update documentation
    • library can be used for water and salinity and other linear related things.

Should

  • investigate linear expansion
    • VCE as parameter.
  • do not make the library too complex (see could below).
  • extend unit tests

Could

  • add void cool(time) == depends on many factors
    • need to configure curve constant (only option).
    • must use defined liquid and temp scale.
  • void AddEnergy(float joule) to raise temperature (joule)
    • must use defined liquid and temp scale.
    • specific heat needed. (WaterMix only?)
  • replace div and mul with operators * and /
  • investigate injection of density function to make LiquidMix generic?

Wont (or on special request)

  • add "unit string" + Printable interface? -idem Temp scale?
  • energy functions to calculate how hot an amount of water should be to reach a certain temperature.
    • Think Aquaria or cooking.
  • investigate how to mix different liquids?
    • gives too much params
  • use double instead of float?
    • weight and temperature are not that accurate (assumption)
  • investigate the caching of the mass of the water.
    • addExact() only, 4 bytes only for WaterMix class
    • it is so far no performance issue.
  • catch temperature below zero?
    • must use defined liquid and temp scale.
    • user responsibility for now.

Support

If you appreciate my libraries, you can support the development and maintenance. Improve the quality of the libraries by providing issues and Pull Requests, or donate through PayPal or GitHub sponsors.

Thank you,