Skip to content

Commit

Permalink
feat: hw_voltage example added
Browse files Browse the repository at this point in the history
  • Loading branch information
mpusz committed Sep 17, 2024
1 parent 80880f1 commit 3ead7c2
Show file tree
Hide file tree
Showing 4 changed files with 171 additions and 0 deletions.
72 changes: 72 additions & 0 deletions docs/users_guide/examples/hw_voltage.md
Original file line number Diff line number Diff line change
@@ -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)
```
1 change: 1 addition & 0 deletions example/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
97 changes: 97 additions & 0 deletions example/hw_voltage.cpp
Original file line number Diff line number Diff line change
@@ -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 <mp-units/compat_macros.h>
#ifdef MP_UNITS_IMPORT_STD
import std;
#else
#include <optional>
#include <print>
#endif
#ifdef MP_UNITS_MODULES
import mp_units;
#else
#include <mp-units/format.h>
#include <mp-units/systems/isq.h>
#include <mp-units/systems/si.h>
#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<voltage_hw_t>::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<absolute<si::volt>(min_voltage)> {} hw_voltage_origin;

inline constexpr struct hw_voltage_unit final :
named_unit<"hwV", mag_ratio<voltage_range, voltage_hw_range> * si::volt, hw_voltage_origin> {} hw_voltage_unit;

using hw_voltage_quantity_point = quantity_point<hw_voltage_unit, hw_voltage_origin, voltage_hw_t>;
// clang-format on

// mapped HW register
volatile voltage_hw_t hw_voltage_value;

std::optional<hw_voltage_quantity_point> read_hw_voltage()
{
voltage_hw_t local_copy = hw_voltage_value;
if (local_copy == voltage_hw_error) return std::nullopt;
return absolute<hw_voltage_unit>(local_copy);
}

void print(QuantityPoint auto qp)
{
std::println("{:10} ({:5})", qp.quantity_from_zero(), value_cast<double, si::volt>(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);
}
1 change: 1 addition & 0 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 3ead7c2

Please sign in to comment.