diff --git a/docs/users_guide/examples/hw_voltage.md b/docs/users_guide/examples/hw_voltage.md new file mode 100644 index 00000000..92925732 --- /dev/null +++ b/docs/users_guide/examples/hw_voltage.md @@ -0,0 +1,72 @@ +--- +tags: + - Affine Space + - Embedded + - Text Formatting +--- + +# `hw_voltage` + +!!! example "[Try it on Compiler Explorer](https://godbolt.org/z/jjod7hvsd)" + +As it was stated in [The Affine Space](../framework_basics/the_affine_space.md) chapter, +every measurement can (and probably should) be modelled as a `quantity_point`. This is +a perfect example of such a use case. + +This example implements a simplified scenario of measuring voltage read from hardware through +a mapped 16-bits register. The actual voltage range of [-10 V, 10 V] is mapped to [-32767, 32767] +on hardware. Translation of the value requires not only scaling of the value but also applying +of an offset. + +First we include all the dependencies: + +```cpp title="hw_voltage.cpp" linenums="1" +--8<-- "example/hw_voltage.cpp:28:43" +``` + +Next, we specify the real measurement voltage range to be in the range of [-10, 10]: + +```cpp title="hw_voltage.cpp" linenums="17" +--8<-- "example/hw_voltage.cpp:45:48" +``` + +and provide a storage type and special values for the hardware representation: + +```cpp title="hw_voltage.cpp" linenums="21" +--8<-- "example/hw_voltage.cpp:50:56" +``` + +Finally, we define a quantity point origin, an offset unit that scales the value and uses this +origin to offset the zero of the sale, and a dedicated quantity point alias using those: + +```cpp title="hw_voltage.cpp" linenums="28" +--8<-- "example/hw_voltage.cpp:60:66" +``` + +Now, when everything is ready, we can simulate mapping of our hardware register, and provide +a helper function that will read the value and construct a quantity point from the obtained copy: + +```cpp title="hw_voltage.cpp" linenums="35" +--8<-- "example/hw_voltage.cpp:69:77" +``` + +We also provide a simple print helper for our quantity points: + +```cpp title="hw_voltage.cpp" linenums="44" +--8<-- "example/hw_voltage.cpp:79:82" +``` + +In the main function we simulate setting of 3 values by our hardware. Each of them is read +and printed in the voltage unit used on the hardware as well as in the standard SI unit: + +```cpp title="hw_voltage.cpp" linenums="48" +--8<-- "example/hw_voltage.cpp:84:" +``` + +The above program results with the following text output: + +```text + 0 hwV (-10 V) + 32767 hwV ( 0 V) + 65534 hwV ( 10 V) +``` diff --git a/example/CMakeLists.txt b/example/CMakeLists.txt index de84b9a8..7c329d4e 100644 --- a/example/CMakeLists.txt +++ b/example/CMakeLists.txt @@ -57,6 +57,7 @@ add_example(currency) add_example(foot_pound_second) add_example(glide_computer glide_computer_lib) add_example(hello_units) +add_example(hw_voltage) add_example(measurement) add_example(si_constants) add_example(spectroscopy_units) diff --git a/example/hw_voltage.cpp b/example/hw_voltage.cpp new file mode 100644 index 00000000..8eef1085 --- /dev/null +++ b/example/hw_voltage.cpp @@ -0,0 +1,97 @@ +// The MIT License (MIT) +// +// Copyright (c) 2018 Mateusz Pusz +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// !!! Before you commit any changes to this file please make sure to check if it !!! +// !!! renders correctly in the documentation "Examples" section. !!! +// !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +#include +#ifdef MP_UNITS_IMPORT_STD +import std; +#else +#include +#include +#endif +#ifdef MP_UNITS_MODULES +import mp_units; +#else +#include +#include +#include +#endif + +using namespace mp_units; + +// real voltage range +inline constexpr int min_voltage = -10; +inline constexpr int max_voltage = 10; +inline constexpr int voltage_range = max_voltage - min_voltage; + +// hardware encoding of voltage +using voltage_hw_t = std::uint16_t; +inline constexpr voltage_hw_t voltage_hw_error = std::numeric_limits::max(); +inline constexpr voltage_hw_t voltage_hw_min = 0; +inline constexpr voltage_hw_t voltage_hw_max = voltage_hw_error - 1; +inline constexpr voltage_hw_t voltage_hw_range = voltage_hw_max - voltage_hw_min; +inline constexpr voltage_hw_t voltage_hw_zero = voltage_hw_range / 2; + + +// clang-format off +inline constexpr struct hw_voltage_origin final : + relative_point_origin(min_voltage)> {} hw_voltage_origin; + +inline constexpr struct hw_voltage_unit final : + named_unit<"hwV", mag_ratio * si::volt, hw_voltage_origin> {} hw_voltage_unit; + +using hw_voltage_quantity_point = quantity_point; +// clang-format on + +// mapped HW register +volatile voltage_hw_t hw_voltage_value; + +std::optional read_hw_voltage() +{ + voltage_hw_t local_copy = hw_voltage_value; + if (local_copy == voltage_hw_error) return std::nullopt; + return absolute(local_copy); +} + +void print(QuantityPoint auto qp) +{ + std::println("{:10} ({:5})", qp.quantity_from_zero(), value_cast(qp).quantity_from_zero()); +} + +int main() +{ + // simulate reading of 3 values from the hardware + hw_voltage_value = voltage_hw_min; + quantity_point qp1 = read_hw_voltage().value(); + hw_voltage_value = voltage_hw_zero; + quantity_point qp2 = read_hw_voltage().value(); + hw_voltage_value = voltage_hw_max; + quantity_point qp3 = read_hw_voltage().value(); + + print(qp1); + print(qp2); + print(qp3); +} diff --git a/mkdocs.yml b/mkdocs.yml index da83c3c8..d54a807e 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -175,6 +175,7 @@ nav: - hello_units: users_guide/examples/hello_units.md - avg_speed: users_guide/examples/avg_speed.md - si_constants: users_guide/examples/si_constants.md + - hw_voltage: users_guide/examples/hw_voltage.md - Appendix: - Glossary: appendix/glossary.md - References: appendix/references.md