mirror of
https://github.com/RobTillaart/Arduino.git
synced 2024-09-19 16:46:11 -04:00
0.1.2 WaterMix
This commit is contained in:
parent
4b4a52c7f3
commit
2038ff53d5
@ -6,6 +6,13 @@ The format is based on [Keep a Changelog](http://keepachangelog.com/)
|
||||
and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
|
||||
|
||||
## [0.1.2] - 2023-09-08
|
||||
- add base class **LiquidMix** (moved functions up)
|
||||
- made **WaterMix::density()** public
|
||||
- update readme.md
|
||||
- fix keywords.txt
|
||||
|
||||
|
||||
## [0.1.1] - 2023-08-30
|
||||
- add **void addExact(float volume, float temperature)** (works only for water).
|
||||
- add **float mass()** (works only for water).
|
||||
@ -15,7 +22,6 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
||||
- fix keywords.txt
|
||||
- minor edits
|
||||
|
||||
|
||||
## [0.1.0] - 2023-08-29
|
||||
- initial version
|
||||
|
||||
|
@ -18,48 +18,72 @@ Arduino library for mixing water with different temperatures.
|
||||
|
||||
**Warning: Experimental**
|
||||
|
||||
Experimental library for elementary math of mixing water with different temperatures.
|
||||
Experimental library for elementary math of mixing certain amounts of water or other
|
||||
(same) liquids with different temperatures.
|
||||
|
||||
The library provides math for mixing a volume of water with temperature T1
|
||||
with a another volume with temperature temperature T2.
|
||||
In fact the library will work for any single liquid (TODO: liquidMix class),
|
||||
although some functions are **water specific**.
|
||||
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.
|
||||
|
||||
This library is useful e.g. by doing "water math" for aquaria or cooking.
|
||||
|
||||
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 library uses a generic volume parameter instead of gallons or liters as
|
||||
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**.
|
||||
|
||||
The temperature unit can also be chosen by the user and can be Kelvin, Celsius,
|
||||
Fahrenheit or other.
|
||||
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 with real water.
|
||||
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".
|
||||
the density is identical for both volumes of waters.
|
||||
|
||||
Of course this is incorrect, therefore it is expected to have a difference
|
||||
Of course this assumption is incorrect, therefore there will be a difference
|
||||
between the theoretical values and doing the mixing in practice.
|
||||
However the delta's are expected to be small, less than 1% in many cases.
|
||||
Given the accuracy of volume measurement and temperature measurement,
|
||||
this delta is often acceptable.
|
||||
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 should use the **addExact()** function
|
||||
as this compensates for the density of the water at a given temperature.
|
||||
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
|
||||
@ -75,68 +99,77 @@ as this compensates for the density of the water at a given temperature.
|
||||
#include "WaterMix.h"
|
||||
```
|
||||
|
||||
#### Constructor
|
||||
#### LiquidMix (base class)
|
||||
|
||||
- **WaterMix()** constructor, starts with no water of 0°
|
||||
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 water of 0°.
|
||||
|
||||
#### Math
|
||||
|
||||
- **void add(float volume, float temperature)** add an amount of water
|
||||
with temperature to the "WaterMix".
|
||||
- **void addExact(float volume, float temperature)** Water only!
|
||||
add an amount of water with temperature to the "WaterMix".
|
||||
The math is calculated including using the density of the water.
|
||||
This is slower as **add()** but more exact.
|
||||
Note the temperature must be in °C.
|
||||
- **void sub(float volume)** subtract a volume from the "WaterMix".
|
||||
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.
|
||||
|
||||
#### Getters
|
||||
|
||||
- **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!
|
||||
|
||||
#### Converters
|
||||
|
||||
- **float volume2mass(float volume, float temperature)** idem, Water only!
|
||||
Use volume == 1 to get the density at a certain temperature.
|
||||
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 just fast, the only that do the core math are add()
|
||||
and addExact().
|
||||
The WaterMix_exact.ino sketch provides some performance figures shown
|
||||
here.
|
||||
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.
|
||||
|
||||
| Function | time (us) | Notes |
|
||||
|:------------:|:-----------:|:--------|
|
||||
| add() | 72 |
|
||||
| addExact() | 576 | most accurate |
|
||||
Tested on UNO, 16 MHz.
|
||||
|
||||
Note it is possible to tune the linear 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 fast **add()**.
|
||||
| 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 not supported in the library.
|
||||
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.
|
||||
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.
|
||||
|
||||
|
||||
@ -204,37 +237,26 @@ Source: - https://www.engineeringtoolbox.com/cubical-expansion-coefficients-d_12
|
||||
|
||||
- update documentation
|
||||
- library can be used for water and salinity and other linear related things.
|
||||
- investigate linear expansion
|
||||
- VCE as parameter.
|
||||
|
||||
|
||||
#### Should
|
||||
|
||||
- create base class **LiquidMix** and derive a specific **WaterMix** from it.
|
||||
- code is quite identical, easy to split/strip water specific functions
|
||||
- **WaterMix** can include specific heat, density, VCE etc.
|
||||
- 0.2.0
|
||||
- **WaterMixF()** Fahrenheit, as derived class too.
|
||||
- **WaterMixK()** Kelvin?
|
||||
- investigate linear expansion
|
||||
- VCE as parameter.
|
||||
- do not make the library too complex (see could below).
|
||||
- extend unit tests
|
||||
- investigate the caching of the mass of the water.
|
||||
- add Exact only, 4 bytes..
|
||||
|
||||
|
||||
#### Could
|
||||
|
||||
- cool(time) == depends on many factors
|
||||
- add **void cool(time)** == depends on many factors
|
||||
- need to configure curve constant (only option).
|
||||
- must use defined liquid and temp scale.
|
||||
- catch temperature below zero?
|
||||
- must use defined liquid and temp scale.
|
||||
- user responsibility for now.
|
||||
- **void AddEnergy(float joule)** to raise temperature (joule)
|
||||
- must use defined liquid and temp scale.
|
||||
- specific heat needed. (Water only?)
|
||||
- specific heat needed. (WaterMix only?)
|
||||
- replace div and mul with operators \* and \/
|
||||
- use double iso float?
|
||||
- investigate injection of density function to make LiquidMix generic?
|
||||
|
||||
|
||||
#### Wont (or on special request)
|
||||
@ -244,6 +266,16 @@ Source: - https://www.engineeringtoolbox.com/cubical-expansion-coefficients-d_12
|
||||
- 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
|
||||
|
@ -3,33 +3,35 @@
|
||||
// FILE: WaterMix.h
|
||||
// AUTHOR: Rob Tillaart
|
||||
// PURPOSE: Arduino library for mixing water with different temperatures.
|
||||
// VERSION: 0.1.1
|
||||
// VERSION: 0.1.2
|
||||
// URL: https://github.com/RobTillaart/WaterMix
|
||||
|
||||
|
||||
#include "Arduino.h"
|
||||
|
||||
|
||||
#define WATERMIX_LIB_VERSION (F("0.1.1"))
|
||||
#define WATERMIX_LIB_VERSION (F("0.1.2"))
|
||||
|
||||
|
||||
class WaterMix
|
||||
////////////////////////////////////////////
|
||||
//
|
||||
// LIQUIDMIX
|
||||
//
|
||||
class LiquidMix
|
||||
{
|
||||
public:
|
||||
WaterMix()
|
||||
LiquidMix()
|
||||
{
|
||||
_volume = 0;
|
||||
_temperature = 0;
|
||||
}
|
||||
|
||||
|
||||
void begin(float volume = 0, float temperature = 0)
|
||||
{
|
||||
_volume = volume;
|
||||
_temperature = temperature;
|
||||
}
|
||||
|
||||
|
||||
void add(float volume, float temperature)
|
||||
{
|
||||
if (volume <= 0) return; // false ?
|
||||
@ -38,31 +40,11 @@ public:
|
||||
_volume = vol;
|
||||
}
|
||||
|
||||
|
||||
void addExact(float volume, float temperature)
|
||||
void add(LiquidMix &lm)
|
||||
{
|
||||
if (volume <= 0) return; // false
|
||||
float mass0 = _volume * _density(_temperature);
|
||||
float mass1 = volume * _density(temperature);
|
||||
float totalMass = mass0 + mass1;
|
||||
|
||||
_temperature = (mass0 * _temperature + mass1 * temperature) / totalMass;
|
||||
_volume = totalMass / _density(_temperature);
|
||||
add(lm.volume(), lm.temperature());
|
||||
}
|
||||
|
||||
|
||||
void add(WaterMix &wm)
|
||||
{
|
||||
add(wm.volume(), wm.temperature());
|
||||
}
|
||||
|
||||
|
||||
void addExact(WaterMix &wm)
|
||||
{
|
||||
addExact(wm.volume(), wm.temperature());
|
||||
}
|
||||
|
||||
|
||||
void sub(float volume)
|
||||
{
|
||||
_volume -= volume;
|
||||
@ -70,58 +52,90 @@ public:
|
||||
// temperature does not change.
|
||||
}
|
||||
|
||||
|
||||
void div(float nr)
|
||||
{
|
||||
_volume /= nr;
|
||||
// temperature does not change.
|
||||
}
|
||||
|
||||
|
||||
void mul(float nr)
|
||||
{
|
||||
_volume *= nr;
|
||||
// temperature does not change.
|
||||
}
|
||||
|
||||
|
||||
float volume()
|
||||
{
|
||||
return _volume;
|
||||
}
|
||||
|
||||
|
||||
float temperature()
|
||||
{
|
||||
return _temperature;
|
||||
}
|
||||
|
||||
|
||||
float mass()
|
||||
protected:
|
||||
float _volume;
|
||||
float _temperature;
|
||||
};
|
||||
|
||||
|
||||
////////////////////////////////////////////
|
||||
//
|
||||
// WATERMIX
|
||||
//
|
||||
class WaterMix : public LiquidMix
|
||||
{
|
||||
public:
|
||||
WaterMix() : LiquidMix()
|
||||
{
|
||||
return _volume * _density(_temperature);
|
||||
}
|
||||
|
||||
void add(float volume, float temperature)
|
||||
{
|
||||
LiquidMix::add(volume, temperature);
|
||||
}
|
||||
|
||||
void addExact(float volume, float temperature)
|
||||
{
|
||||
if (volume <= 0) return; // false
|
||||
float mass0 = _volume * density(_temperature);
|
||||
float mass1 = volume * density(temperature);
|
||||
float totalMass = mass0 + mass1;
|
||||
|
||||
_temperature = (mass0 * _temperature + mass1 * temperature) / totalMass;
|
||||
_volume = totalMass / density(_temperature);
|
||||
}
|
||||
|
||||
void add(WaterMix &wm)
|
||||
{
|
||||
LiquidMix::add(wm.volume(), wm.temperature());
|
||||
}
|
||||
|
||||
void addExact(WaterMix &wm)
|
||||
{
|
||||
addExact(wm.volume(), wm.temperature());
|
||||
}
|
||||
|
||||
float mass()
|
||||
{
|
||||
return _volume * density(_temperature);
|
||||
}
|
||||
|
||||
float volume2mass(float volume, float temperature)
|
||||
{
|
||||
return volume * _density(temperature);
|
||||
return volume * density(temperature);
|
||||
}
|
||||
|
||||
|
||||
float mass2volume(float mass, float temperature)
|
||||
{
|
||||
return mass / _density(temperature);
|
||||
return mass / density(temperature);
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
float _volume;
|
||||
float _temperature;
|
||||
|
||||
|
||||
// _density is in fact multiMap code
|
||||
float _density(float temperature)
|
||||
// density is in fact multiMap code
|
||||
float density(float temperature)
|
||||
{
|
||||
// strip table size?
|
||||
uint8_t size = 22;
|
||||
@ -134,7 +148,6 @@ private:
|
||||
0.9618900, 0.9583500
|
||||
};
|
||||
|
||||
|
||||
// take care the temperature is within range
|
||||
// temperature = constrain(temperature, _in[0], _in[size-1]);
|
||||
if (temperature <= _in[0]) return _out[0];
|
||||
|
@ -1,6 +1,7 @@
|
||||
# Syntax Colouring Map For WaterMix
|
||||
|
||||
# Data types (KEYWORD1)
|
||||
LiquidMix KEYWORD1
|
||||
WaterMix KEYWORD1
|
||||
|
||||
|
||||
@ -19,6 +20,7 @@ mass KEYWORD2
|
||||
|
||||
volume2mass KEYWORD2
|
||||
mass2volume KEYWORD2
|
||||
density KEYWORD2
|
||||
|
||||
|
||||
# Constants (LITERAL1)
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "WaterMix",
|
||||
"keywords": "water, mix, liters, temperature",
|
||||
"keywords": "water, mix, liters, temperature, LiquidMix, density",
|
||||
"description": "Arduino library for mixing water with different temperatures.",
|
||||
"authors":
|
||||
[
|
||||
@ -15,7 +15,7 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/RobTillaart/WaterMix.git"
|
||||
},
|
||||
"version": "0.1.1",
|
||||
"version": "0.1.2",
|
||||
"license": "MIT",
|
||||
"frameworks": "*",
|
||||
"platforms": "*",
|
||||
|
@ -1,5 +1,5 @@
|
||||
name=WaterMix
|
||||
version=0.1.1
|
||||
version=0.1.2
|
||||
author=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
maintainer=Rob Tillaart <rob.tillaart@gmail.com>
|
||||
sentence=Arduino library for mixing water with different temperatures.
|
||||
|
Loading…
Reference in New Issue
Block a user