software:firmware
MakAir Firmware
pressure_valve.cpp
Go to the documentation of this file.
1 
8 #pragma once
9 
10 // INCLUDES ===================================================================
11 
12 // Associated header
13 #include "../includes/pressure_valve.h"
14 
15 // External libraries
16 #include <algorithm>
17 
18 // Internal libraries
19 #include "../includes/parameters.h"
20 
21 // INITIALISATION =============================================================
22 
25 
26 // FUNCTIONS ==================================================================
27 
29 
30 PressureValve::PressureValve(HardwareTimer* p_hardwareTimer,
31  uint16_t p_timerChannel,
32  uint16_t p_valvePin,
33  uint16_t p_openApertureAngle,
34  uint16_t p_closeApertureAngle) {
35  actuator = p_hardwareTimer;
36  timerChannel = p_timerChannel;
37  valvePin = p_valvePin;
38  openApertureAngle = p_openApertureAngle;
39  closeApertureAngle = p_closeApertureAngle;
40  minApertureAngle = min(p_closeApertureAngle, p_openApertureAngle);
41  maxApertureAngle = max(p_closeApertureAngle, p_openApertureAngle);
42  command = p_closeApertureAngle;
43  position = -1;
44  positionLinear = 0;
45 }
46 
48  actuator->setMode(timerChannel, TIMER_OUTPUT_COMPARE_PWM1, valvePin);
49  actuator->setCaptureCompare(timerChannel, 0, MICROSEC_COMPARE_FORMAT);
50 }
51 
53 
55 
56 void PressureValve::open(uint16_t p_command) { command = p_command; }
57 
58 void PressureValve::openSection(int32_t p_sectionMultiplyBy100) {
59  // Min-max to prevent overflow
60  int32_t cappedSectionMultiplyBy100 =
61  // cppcheck-suppress misra-c2012-12.3 ; cppcheck error
62  min(max(int32_t(0), p_sectionMultiplyBy100), int32_t(3318));
63 
64  int32_t tempCommand;
65  if (cappedSectionMultiplyBy100 < 1960) {
66  tempCommand = 98 - (318 * cappedSectionMultiplyBy100 / 10000);
67  } else {
68  tempCommand =
69  2626 - (36 * cappedSectionMultiplyBy100) / 10
70  + 168 * ((cappedSectionMultiplyBy100 * cappedSectionMultiplyBy100) / 100) / 1000
71  - 264
72  * (((cappedSectionMultiplyBy100 * cappedSectionMultiplyBy100) / 100)
73  * (cappedSectionMultiplyBy100) / 100)
74  / 100000;
75  }
76  // cppcheck-suppress misra-c2012-12.3
77  command = min(max(int32_t(minApertureAngle), tempCommand), int32_t(maxApertureAngle));
78 }
79 
80 // Linearization has been made experimentaly
81 uint16_t PressureValve::openLinear(uint16_t p_command) {
82  uint16_t cappedCommand =
83  // cppcheck-suppress misra-c2012-12.3 ; cppcheck error
84  min(max(uint16_t(minApertureAngle), p_command), uint16_t(maxApertureAngle));
85 
86  positionLinear = cappedCommand;
87  // The cappedCommand is in [ 0 ; 125 ], but the valve is only effective in [30; 100]
88  // So lets make it between 30 and 100
89  // A x10 multiplier is used here for better precision with integer calculations
90  // The value of intermediateValue will consequently be in [300 ; 1000]
91  uint32_t intermediateValue =
92  (((static_cast<uint32_t>(cappedCommand) * 75u) / 125u) + 30u) * 10u;
93 
94  /* An order 3 polynom is used to correct the non linearity of the valve.
95  To find this polynom, the following experimental protocol was used:
96  - Run the blower max speed during the full experience
97  - Plug inspiratory output on expiratory input
98  - For each openning value of the valve, wait 5s for stabilisation and measure Flow
99 
100  This gives a csv with:
101  openningValue[0;125], flow (mL/min)
102  0, 48137
103  10, 47780
104  ...
105  125, 127
106 
107  Then we calculated for each openning value the "linear target flow" with a basic linear
108  equation:
109  openningValue[0;125], flow (mL/min), targetFlow (mL/min)
110  0, 48137,48137
111  10, 47780, 44296
112  ...
113  125, 127, 0
114 
115  Then we manually found for each openning value, the openning value that should have been
116  used to reach the targetFlow: openningValue[0;125], flow (mL/min), targetFlow (mL/min),
117  correctedOpenningValue[0;125] 0, 48137,48137, 30 10, 47780, 44296, 55.2
118  ...
119  125, 127, 0, 100
120 
121  Then when made an order 3 regression between correctedOpenningValue and openningValue. This
122  is the relation below:
123  */
124  command = (uint16_t)(
125  (((76u * intermediateValue) / 10u)
126  - (((985u * intermediateValue) * intermediateValue) / 100000u)
127  + (((((44u * intermediateValue) * intermediateValue) / 1000u) * intermediateValue)
128  / 10000u)
129  - 1140u)
130  / 10u);
131 
132  // cppcheck-suppress misra-c2012-12.3 ; cppcheck error
133  command = min(max(uint16_t(minApertureAngle), command), uint16_t(maxApertureAngle));
134 
135  return command;
136 }
137 
138 // This is used to calculate a theorical expiratory flow
140  int32_t section;
141  if (command > 105u) {
142  section = 0;
143  } else if (command >= 50u) {
144  section = 5760u - (558u * command / 10u);
145  } else {
146  section = 4390u - (5u * command) - (47u * command * command / 100u);
147  }
148 
149  return max(int32_t(0), section);
150 }
151 
152 uint16_t valveAngle2MicroSeconds(uint16_t value) {
153  // Faulhaber motors works with PWM
154  return map(value, 0, 125, FAULHABER_OPENED, FAULHABER_CLOSED);
155 }
Controls a pressure valve.
uint16_t valvePin
Data pin for this valve.
uint16_t maxApertureAngle
Maximum valve aperture angle in degrees.
uint16_t closeApertureAngle
Close aperture angle in degrees.
void setup()
Initialize this valve.
PressureValve()
Default constructor.
uint16_t openApertureAngle
Open aperture angle in degrees.
uint16_t command
Value of the requested aperture.
void openSection(int32_t p_sectionMultiplyBy100)
Request opening of the Pressure Valve with a given section (in mm^2)
uint16_t minApertureAngle
Minimum valve aperture angle in degrees.
int32_t getSectionBigHoseX100()
void open()
Request opening of the Pressure Valve.
HardwareTimer * actuator
Hardware time for this valve.
uint16_t timerChannel
TIM channel for this valve.
uint16_t positionLinear
Current aperture linear.
void close()
Request closing of the Pressure Valve.
uint16_t position
Current aperture.
uint16_t openLinear(uint16_t p_command)
Request opening of the Pressure Valve with a given angle with linearization.
#define FAULHABER_CLOSED
Definition: parameters.h:173
#define FAULHABER_OPENED
Definition: parameters.h:172
PressureValve inspiratoryValve
uint16_t valveAngle2MicroSeconds(uint16_t value)
Convert an angle in degrees to a value in microseconds for the valve controller.
PressureValve expiratoryValve