demo-epb  v1.0
Elektrische Parkbremse - slohmaier Dev Process Demo
actuator_driver.c
gehe zur Dokumentation dieser Datei
1 /**
2  * @file actuator_driver.c
3  * @brief Implementierung der EPB-Aktor-Ansteuerung.
4  *
5  * @arch SWA-003
6  * @reqs SWE-006 SWE-013 SWE-014 SWE-015
7  *
8  * ASIL: B.
9  */
10 #include "actuator_driver.h"
11 
12 typedef struct {
14  uint16_t over_ms; /* Milliseconds above current limit (counts in 1 kHz ISR) */
15 } ActuatorCtx;
16 
18 
19 static bool is_valid_id(ActuatorId id)
20 {
21  return (id == ACTUATOR_LEFT) || (id == ACTUATOR_RIGHT);
22 }
23 
25 {
26  for (uint8_t i = 0U; i < ACTUATOR_COUNT; ++i) {
28  s_ctx[i].status.pwm_percent = 0U;
29  s_ctx[i].status.current_ma = 0U;
32  s_ctx[i].status.overcurrent = false;
34  s_ctx[i].over_ms = 0U;
35  }
36  return EPB_OK;
37 }
38 
39 EpbStatus actuator_apply(ActuatorId id, uint8_t pwm_percent)
40 {
41  if (!is_valid_id(id)) {
42  return EPB_EINVAL;
43  }
44  if (pwm_percent > 100U) {
45  return EPB_EINVAL;
46  }
47  if (s_ctx[id].status.overcurrent) {
48  return EPB_EOVERCURRENT;
49  }
51  s_ctx[id].status.pwm_percent = pwm_percent;
52  s_ctx[id].status.peak_current_ma = 0U;
53  return EPB_OK;
54 }
55 
56 EpbStatus actuator_release(ActuatorId id, uint8_t pwm_percent)
57 {
58  if (!is_valid_id(id)) {
59  return EPB_EINVAL;
60  }
61  if (pwm_percent > 100U) {
62  return EPB_EINVAL;
63  }
64  if (s_ctx[id].status.overcurrent) {
65  return EPB_EOVERCURRENT;
66  }
68  s_ctx[id].status.pwm_percent = pwm_percent;
69  return EPB_OK;
70 }
71 
73 {
74  if (!is_valid_id(id)) {
75  return EPB_EINVAL;
76  }
78  s_ctx[id].status.pwm_percent = 0U;
79  return EPB_OK;
80 }
81 
83 {
84  if (!is_valid_id(id)) {
85  ActuatorStatus empty = {0};
86  empty.last_error = EPB_EINVAL;
87  return empty;
88  }
89  return s_ctx[id].status;
90 }
91 
92 void actuator_isr_1khz(ActuatorId id, uint16_t current_sample_ma)
93 {
94  if (!is_valid_id(id)) {
95  return;
96  }
97 
98  s_ctx[id].status.current_ma = current_sample_ma;
99  if (current_sample_ma > s_ctx[id].status.peak_current_ma) {
100  s_ctx[id].status.peak_current_ma = current_sample_ma;
101  }
102 
103  /* SWE-014: Overcurrent cutoff at > 8 A for > 100 ms */
104  if (current_sample_ma > ACT_OVERCURRENT_LIMIT_MA) {
105  if (s_ctx[id].over_ms < UINT16_MAX) {
106  ++s_ctx[id].over_ms;
107  }
108  if (s_ctx[id].over_ms >= ACT_OVERCURRENT_WINDOW_MS) {
110  s_ctx[id].status.pwm_percent = 0U;
111  s_ctx[id].status.overcurrent = true;
113  }
114  } else {
115  s_ctx[id].over_ms = 0U;
116  }
117 
118  /* SWE-015: Estimate clamping force from peak current (only on apply). */
119  if (s_ctx[id].status.direction == ACT_DIR_APPLY) {
120  const uint32_t force = ((uint32_t)s_ctx[id].status.peak_current_ma
121  * ACT_FORCE_PER_AMP_N) / 1000U;
123  (force > UINT16_MAX) ? UINT16_MAX : (uint16_t)force;
124  }
125 }
EpbStatus actuator_release(ActuatorId id, uint8_t pwm_percent)
static ActuatorCtx s_ctx[ACTUATOR_COUNT]
EpbStatus actuator_init(void)
ActuatorStatus actuator_get_status(ActuatorId id)
EpbStatus actuator_apply(ActuatorId id, uint8_t pwm_percent)
void actuator_isr_1khz(ActuatorId id, uint16_t current_sample_ma)
ISR hook for current sampling.
EpbStatus actuator_stop(ActuatorId id)
static bool is_valid_id(ActuatorId id)
Low-level control of the EPB actuators.
#define ACT_FORCE_PER_AMP_N
#define ACT_OVERCURRENT_WINDOW_MS
#define ACT_OVERCURRENT_LIMIT_MA
Current limit (spec) and time window for cutoff (spec).
@ ACT_DIR_STOP
@ ACT_DIR_RELEASE
@ ACT_DIR_APPLY
EpbStatus
Definition: epb_types.h:13
@ EPB_EINVAL
Definition: epb_types.h:15
@ EPB_EOVERCURRENT
Definition: epb_types.h:19
@ EPB_OK
Definition: epb_types.h:14
ActuatorId
Definition: epb_types.h:30
@ ACTUATOR_RIGHT
Definition: epb_types.h:32
@ ACTUATOR_COUNT
Definition: epb_types.h:33
@ ACTUATOR_LEFT
Definition: epb_types.h:31
uint16_t over_ms
ActuatorStatus status
uint16_t clamping_force_n
uint16_t peak_current_ma
ActuatorDirection direction
uint16_t current_ma
EpbStatus last_error