example_hand_motion_detection_main.c
Go to the documentation of this file.
1 // Copyright (c) Acconeer AB, 2024
2 // All rights reserved
3 // This file is subject to the terms and conditions defined in the file
4 // 'LICENSES/license_acconeer.txt', (BSD 3-Clause License) which is part
5 // of this source code package.
6
7 #include <stdbool.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10
11 #include "acc_config.h"
12 #include "acc_hal_definitions_a121.h"
13 #include "acc_hal_integration_a121.h"
14 #include "acc_integration.h"
15 #include "acc_processing.h"
16 #include "acc_rss_a121.h"
17 #include "acc_sensor.h"
18 #include "acc_version.h"
19 #include "example_hand_motion_detection.h"
20 #include "example_hand_motion_detection_main.h"
21
22 #define SENSOR_ID (1U)
23 #define SENSOR_TIMEOUT_MS (1000U)
24
25 /**
26 * @brief Frees any allocated resources
27 */
28 static void cleanup(acc_sensor_t *sensor, void *buffer, hand_motion_detection_config_t *config, hand_motion_detection_handle_t *handle);
29
30 /**
31 * @brief Performs sensor calibration (with retry)
32 */
33 static bool do_sensor_calibration(acc_sensor_t *sensor, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size);
34
35 /**
36 * @brief Handle sensor indications
37 */
38 static bool handle_indications(hand_motion_detection_handle_t *handle,
39 hand_motion_detection_result_t *result,
40 acc_sensor_t *sensor,
41 acc_cal_result_t *cal_result,
42 void *buffer,
43 uint32_t buffer_size,
44 bool *data_reliable);
45
46 /**
47 * @brief Print a processor result in a human-readable format
48 */
49 static void print_hand_motion_detection_result(const hand_motion_detection_result_t *result);
50
51 static bool enter_hibernate(acc_sensor_t *sensor);
52
53 static bool exit_hibernate(acc_sensor_t *sensor);
54
55 int acconeer_main(int argc, char *argv[])
56 {
57 (void)argc;
58 (void)argv;
59 acc_sensor_t *sensor = NULL;
60 acc_cal_result_t cal_result;
61 void *buffer = NULL;
62 uint32_t buffer_size = 0;
63
64 hand_motion_detection_config_t *hand_motion_detection_config = NULL;
65 hand_motion_detection_handle_t *hand_motion_detection_handle = NULL;
66 hand_motion_detection_result_t hand_motion_detection_result = {0};
67
68 printf("Acconeer software version %s\n", acc_version_get());
69
70 const acc_hal_a121_t *hal = acc_hal_rss_integration_get_implementation();
71
72 if (!acc_rss_hal_register(hal))
73 {
74 return EXIT_FAILURE;
75 }
76
77 hand_motion_detection_config = hand_motion_detection_config_create();
78
79 if (hand_motion_detection_config == NULL)
80 {
81 printf("hand_motion_detection_config_create() failed\n");
82 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
83 return EXIT_FAILURE;
84 }
85
86 hand_motion_detection_set_config(HAND_MOTION_DETECTION_PRESET_FAUCET, hand_motion_detection_config);
87
88 hand_motion_detection_handle = hand_motion_detection_handle_create(hand_motion_detection_config, SENSOR_ID);
89 if (hand_motion_detection_handle == NULL)
90 {
91 printf("hand_motion_detection_handle_create() failed\n");
92 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
93 return EXIT_FAILURE;
94 }
95
96 hand_motion_detection_config_log(hand_motion_detection_handle);
97
98 if (!hand_motion_detection_get_buffer_size(hand_motion_detection_handle, &buffer_size))
99 {
100 printf("acc_rss_get_buffer_size() failed\n");
101 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
102 return EXIT_FAILURE;
103 }
104
105 buffer = acc_integration_mem_alloc(buffer_size);
106 if (buffer == NULL)
107 {
108 printf("buffer allocation failed\n");
109 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
110 return EXIT_FAILURE;
111 }
112
113 acc_hal_integration_sensor_supply_on(SENSOR_ID);
114 acc_hal_integration_sensor_enable(SENSOR_ID);
115
116 sensor = acc_sensor_create(SENSOR_ID);
117 if (sensor == NULL)
118 {
119 printf("acc_sensor_create() failed\n");
120 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
121 return EXIT_FAILURE;
122 }
123
124 if (!do_sensor_calibration(sensor, &cal_result, buffer, buffer_size))
125 {
126 printf("do_sensor_calibration() failed\n");
127 acc_sensor_status(sensor);
128 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
129 return EXIT_FAILURE;
130 }
131
132 while (true)
133 {
134 if (!hand_motion_detection_prepare(hand_motion_detection_handle, sensor, &cal_result, buffer, buffer_size, false))
135 {
136 printf("hand_motion_detection_prepare() failed\n");
137 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
138 return EXIT_FAILURE;
139 }
140
141 if (!acc_sensor_measure(sensor))
142 {
143 printf("acc_sensor_measure failed\n");
144 acc_sensor_status(sensor);
145 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
146 return EXIT_FAILURE;
147 }
148
149 if (!acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS))
150 {
151 printf("Sensor interrupt timeout\n");
152 acc_sensor_status(sensor);
153 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
154 return EXIT_FAILURE;
155 }
156
157 if (!acc_sensor_read(sensor, buffer, buffer_size))
158 {
159 printf("acc_sensor_read failed\n");
160 acc_sensor_status(sensor);
161 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
162 return EXIT_FAILURE;
163 }
164
165 if (!enter_hibernate(sensor))
166 {
167 printf("enter_hibernate failed\n");
168 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
169 return EXIT_FAILURE;
170 }
171
172 hand_motion_detection_process(hand_motion_detection_handle, buffer, &hand_motion_detection_result);
173
174 bool data_reliable;
175
176 if (!handle_indications(hand_motion_detection_handle,
177 &hand_motion_detection_result,
178 sensor,
179 &cal_result,
180 buffer,
181 buffer_size,
182 &data_reliable))
183 {
184 printf("handle_indications() failed\n");
185 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
186 return EXIT_FAILURE;
187 }
188
189 if (data_reliable)
190 {
191 print_hand_motion_detection_result(&hand_motion_detection_result);
192 }
193
194 acc_integration_sleep_until_periodic_wakeup();
195
196 if (!exit_hibernate(sensor))
197 {
198 printf("exit_hibernate failed\n");
199 return EXIT_FAILURE;
200 }
201 }
202
203 cleanup(sensor, buffer, hand_motion_detection_config, hand_motion_detection_handle);
204
205 printf("Application finished OK\n");
206
207 return EXIT_SUCCESS;
208 }
209
210 static void cleanup(acc_sensor_t *sensor, void *buffer, hand_motion_detection_config_t *config, hand_motion_detection_handle_t *handle)
211 {
212 acc_hal_integration_sensor_disable(SENSOR_ID);
213 acc_hal_integration_sensor_supply_off(SENSOR_ID);
214
215 if (sensor != NULL)
216 {
217 acc_sensor_destroy(sensor);
218 }
219
220 if (buffer != NULL)
221 {
222 acc_integration_mem_free(buffer);
223 }
224
225 if (config != NULL)
226 {
227 hand_motion_detection_config_destroy(config);
228 }
229
230 if (handle != NULL)
231 {
232 hand_motion_detection_handle_destroy(handle);
233 }
234 }
235
236 static bool do_sensor_calibration(acc_sensor_t *sensor, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
237 {
238 bool status = false;
239 bool cal_complete = false;
240 const uint16_t calibration_retries = 1U;
241
242 // Random disturbances may cause the calibration to fail. At failure, retry at least once.
243 for (uint16_t i = 0; !status && (i <= calibration_retries); i++)
244 {
245 // Reset sensor before calibration by disabling/enabling it
246 acc_hal_integration_sensor_disable(SENSOR_ID);
247 acc_hal_integration_sensor_enable(SENSOR_ID);
248
249 do
250 {
251 status = acc_sensor_calibrate(sensor, &cal_complete, cal_result, buffer, buffer_size);
252
253 if (status && !cal_complete)
254 {
255 status = acc_hal_integration_wait_for_sensor_interrupt(SENSOR_ID, SENSOR_TIMEOUT_MS);
256 }
257 } while (status && !cal_complete);
258 }
259
260 if (status)
261 {
262 // Reset sensor after calibration by disabling/enabling it
263 acc_hal_integration_sensor_disable(SENSOR_ID);
264 acc_hal_integration_sensor_enable(SENSOR_ID);
265 }
266
267 return status;
268 }
269
270 static bool handle_indications(hand_motion_detection_handle_t *handle,
271 hand_motion_detection_result_t *result,
272 acc_sensor_t *sensor,
273 acc_cal_result_t *cal_result,
274 void *buffer,
275 uint32_t buffer_size,
276 bool *data_reliable)
277 {
278 bool status = true;
279
280 *data_reliable = true;
281
282 if (result->proc_result.data_saturated)
283 {
284 *data_reliable = false;
285
286 printf("Data saturated. Try to reduce the sensor gain.\n");
287 }
288
289 if (result->proc_result.frame_delayed)
290 {
291 printf("Frame delayed. Could not read data fast enough.\n");
292 printf("Try lowering the frame rate or call 'acc_sensor_read' more frequently.\n");
293 }
294
295 if (result->proc_result.calibration_needed)
296 {
297 printf("The current calibration is not valid for the current temperature.\n");
298 printf("Re-calibrating sensor...\n");
299
300 if (!exit_hibernate(sensor))
301 {
302 printf("exit_hibernate failed\n");
303 status = false;
304 }
305
306 if (status)
307 {
308 if (!do_sensor_calibration(sensor, cal_result, buffer, buffer_size))
309 {
310 printf("do_sensor_calibration() failed\n");
311 acc_sensor_status(sensor);
312 status = false;
313 }
314 else
315 {
316 printf("Sensor recalibration done!\n");
317 }
318 }
319
320 if (status)
321 {
322 if (!hand_motion_detection_prepare(handle, sensor, cal_result, buffer, buffer_size, true))
323 {
324 printf("hand_motion_detection_prepare() failed\n");
325 status = false;
326 }
327 }
328
329 if (status)
330 {
331 if (!enter_hibernate(sensor))
332 {
333 printf("enter_hibernate failed\n");
334 status = false;
335 }
336 }
337
338 *data_reliable = false;
339
340 printf("The sensor was successfully re-calibrated.\n");
341 }
342
343 return status;
344 }
345
346 static void print_hand_motion_detection_result(const hand_motion_detection_result_t *result)
347 {
348 printf("App mode: %s\n", result->app_mode == HAND_MOTION_DETECTION_APP_MODE_PRESENCE ? "presence" : "handmotion");
349
350 if (result->algo_result_available)
351 {
352 printf("Detection state: ");
353
354 switch (result->algo_result.detection_state)
355 {
356 case HAND_MOTION_DETECTION_STATE_NO_DETECTION:
357 printf("No detection\n");
358 break;
359 case HAND_MOTION_DETECTION_STATE_DETECTION:
360 printf("Detection\n");
361 break;
362 case HAND_MOTION_DETECTION_STATE_RETENTION:
363 printf("Retention\n");
364 break;
365 }
366 }
367 }
368
369 static bool enter_hibernate(acc_sensor_t *sensor)
370 {
371 bool status = true;
372
373 if (!acc_sensor_hibernate_on(sensor))
374 {
375 printf("acc_sensor_hibernate_on failed\n");
376 acc_sensor_status(sensor);
377 status = false;
378 }
379
380 acc_hal_integration_sensor_disable(SENSOR_ID);
381 return status;
382 }
383
384 static bool exit_hibernate(acc_sensor_t *sensor)
385 {
386 bool status = true;
387
388 acc_hal_integration_sensor_enable(SENSOR_ID);
389 if (!acc_sensor_hibernate_off(sensor))
390 {
391 printf("acc_sensor_hibernate_off failed\n");
392 acc_sensor_status(sensor);
393 status = false;
394 }
395
396 return status;
397 }
cleanup
static void cleanup(acc_sensor_t *sensor, void *buffer, hand_motion_detection_config_t *config, hand_motion_detection_handle_t *handle)
Frees any allocated resources.
Definition: example_hand_motion_detection_main.c:210
acc_hal_integration_sensor_supply_off
void acc_hal_integration_sensor_supply_off(acc_sensor_id_t sensor_id)
Power off sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:104
acc_rss_a121.h
cargo_result_t::calibration_needed
bool calibration_needed
Definition: example_cargo.h:112
acc_hal_integration_sensor_supply_on
void acc_hal_integration_sensor_supply_on(acc_sensor_id_t sensor_id)
Power on sensor supply.
Definition: acc_hal_integration_stm32cube_xm.c:99
hand_motion_detection_prepare
bool hand_motion_detection_prepare(hand_motion_detection_handle_t *handle, acc_sensor_t *sensor, const acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size, bool force_prepare)
Prepare hand motion.
Definition: example_hand_motion_detection.c:295
enter_hibernate
static bool enter_hibernate(acc_sensor_t *sensor)
Definition: example_hand_motion_detection_main.c:369
acc_sensor_read
bool acc_sensor_read(const acc_sensor_t *sensor, void *buffer, uint32_t buffer_size)
Read out radar data.
buffer
void * buffer
Definition: i2c_example_cargo.c:40
acc_version.h
hand_motion_detection_config_create
hand_motion_detection_config_t * hand_motion_detection_config_create(void)
Create a hand motion configuration.
Definition: example_hand_motion_detection.c:63
acc_cal_result_t
The result from a completed calibration.
Definition: acc_definitions_a121.h:30
hand_motion_detection_config_destroy
void hand_motion_detection_config_destroy(hand_motion_detection_config_t *config)
Destroy a hand motion configuration.
Definition: example_hand_motion_detection.c:81
HAND_MOTION_DETECTION_STATE_RETENTION
@ HAND_MOTION_DETECTION_STATE_RETENTION
Definition: example_hand_motion_detection.h:39
hand_motion_detection_handle_create
hand_motion_detection_handle_t * hand_motion_detection_handle_create(const hand_motion_detection_config_t *hand_motion_detection_config, acc_sensor_id_t sensor_id)
Create a hand_motion handle.
Definition: example_hand_motion_detection.c:137
acc_integration.h
hand_motion_detection_result_t
Result type.
Definition: example_hand_motion_detection.h:81
print_hand_motion_detection_result
static void print_hand_motion_detection_result(const hand_motion_detection_result_t *result)
Print a processor result in a human-readable format.
Definition: example_hand_motion_detection_main.c:346
config
cargo_config_t config
Definition: i2c_example_cargo.c:34
acc_hal_rss_integration_get_implementation
const acc_hal_a121_t * acc_hal_rss_integration_get_implementation(void)
Get hal implementation reference.
Definition: acc_hal_integration_stm32cube_xm.c:152
acc_integration_mem_alloc
void * acc_integration_mem_alloc(size_t size)
Allocate dynamic memory.
Definition: acc_integration_stm32.c:592
acc_hal_a121_t
Definition: acc_hal_definitions_a121.h:82
acc_rss_hal_register
bool acc_rss_hal_register(const acc_hal_a121_t *hal)
Register an integration.
acc_sensor.h
buffer_size
uint32_t buffer_size
Definition: i2c_example_cargo.c:41
sensor
acc_sensor_t * sensor
Definition: i2c_example_cargo.c:33
example_hand_motion_detection.h
acc_hal_integration_wait_for_sensor_interrupt
bool acc_hal_integration_wait_for_sensor_interrupt(acc_sensor_id_t sensor_id, uint32_t timeout_ms)
Wait for a sensor interrupt.
Definition: acc_hal_integration_stm32cube_xm.c:130
acconeer_main
int acconeer_main(int argc, char *argv[])
Assembly test example.
Definition: example_hand_motion_detection_main.c:55
acc_hal_integration_a121.h
handle
cargo_handle_t * handle
Definition: i2c_example_cargo.c:35
HAND_MOTION_DETECTION_APP_MODE_PRESENCE
@ HAND_MOTION_DETECTION_APP_MODE_PRESENCE
Definition: example_hand_motion_detection.h:31
acc_sensor_hibernate_off
bool acc_sensor_hibernate_off(const acc_sensor_t *sensor)
Restore sensor after exiting hibernation.
hand_motion_detection_process
void hand_motion_detection_process(hand_motion_detection_handle_t *handle, void *buffer, hand_motion_detection_result_t *hand_motion_detection_result)
Process Sparse IQ data.
Definition: example_hand_motion_detection.c:322
result
cargo_result_t result
Definition: i2c_example_cargo.c:43
acc_version_get
const char * acc_version_get(void)
Get the version of the Acconeer software.
printf
#define printf
Definition: printf.h:60
HAND_MOTION_DETECTION_PRESET_FAUCET
@ HAND_MOTION_DETECTION_PRESET_FAUCET
Definition: example_hand_motion_detection.h:26
acc_hal_integration_sensor_enable
void acc_hal_integration_sensor_enable(acc_sensor_id_t sensor_id)
Enable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:109
acc_hal_definitions_a121.h
acc_hal_integration_sensor_disable
void acc_hal_integration_sensor_disable(acc_sensor_id_t sensor_id)
Disable sensor.
Definition: acc_hal_integration_stm32cube_xm.c:119
HAND_MOTION_DETECTION_STATE_DETECTION
@ HAND_MOTION_DETECTION_STATE_DETECTION
Definition: example_hand_motion_detection.h:38
do_sensor_calibration
static bool do_sensor_calibration(acc_sensor_t *sensor, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Performs sensor calibration (with retry)
Definition: example_hand_motion_detection_main.c:236
hand_motion_detection_get_buffer_size
bool hand_motion_detection_get_buffer_size(hand_motion_detection_handle_t *handle, uint32_t *buffer_size)
Get buffer size needed.
Definition: example_hand_motion_detection.c:269
example_hand_motion_detection_main.h
acc_sensor_hibernate_on
bool acc_sensor_hibernate_on(acc_sensor_t *sensor)
Prepare sensor for entering hibernation.
exit_hibernate
static bool exit_hibernate(acc_sensor_t *sensor)
Definition: example_hand_motion_detection_main.c:384
handle_indications
static bool handle_indications(hand_motion_detection_handle_t *handle, hand_motion_detection_result_t *result, acc_sensor_t *sensor, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size, bool *data_reliable)
Handle sensor indications.
Definition: example_hand_motion_detection_main.c:270
SENSOR_ID
#define SENSOR_ID
Definition: example_hand_motion_detection_main.c:22
acc_sensor_status
void acc_sensor_status(const acc_sensor_t *sensor)
Check the status of the sensor.
HAND_MOTION_DETECTION_STATE_NO_DETECTION
@ HAND_MOTION_DETECTION_STATE_NO_DETECTION
Definition: example_hand_motion_detection.h:37
hand_motion_detection_handle_destroy
void hand_motion_detection_handle_destroy(hand_motion_detection_handle_t *handle)
Destroy a hand_motion handle.
Definition: example_hand_motion_detection.c:207
acc_integration_mem_free
void acc_integration_mem_free(void *ptr)
Free dynamic memory.
Definition: acc_integration_stm32.c:602
acc_integration_sleep_until_periodic_wakeup
void acc_integration_sleep_until_periodic_wakeup(void)
Put the system in sleep until the periodic timer triggers.
Definition: acc_integration_stm32.c:552
hand_motion_detection_set_config
void hand_motion_detection_set_config(hand_motion_detection_preset_t preset, hand_motion_detection_config_t *config)
Set config specified by the preset.
Definition: example_hand_motion_detection.c:94
acc_config.h
acc_sensor_calibrate
bool acc_sensor_calibrate(acc_sensor_t *sensor, bool *cal_complete, acc_cal_result_t *cal_result, void *buffer, uint32_t buffer_size)
Calibrate a sensor.
hand_motion_detection_handle
Definition: example_hand_motion_detection.c:23
acc_sensor_measure
bool acc_sensor_measure(acc_sensor_t *sensor)
Start a radar measurement with previously prepared configuration.
acc_processing.h
acc_sensor_t
struct acc_sensor acc_sensor_t
Definition: acc_sensor.h:31
hand_motion_detection_config_log
void hand_motion_detection_config_log(hand_motion_detection_handle_t *handle)
Print configuration.
Definition: example_hand_motion_detection.c:240
SENSOR_TIMEOUT_MS
#define SENSOR_TIMEOUT_MS
Definition: example_hand_motion_detection_main.c:23
acc_sensor_destroy
void acc_sensor_destroy(acc_sensor_t *sensor)
Destroy a sensor instance freeing any resources allocated.
acc_sensor_create
acc_sensor_t * acc_sensor_create(acc_sensor_id_t sensor_id)
Create a sensor instance.
hand_motion_detection_config_t
Configuration for hand_motion.
Definition: example_hand_motion_detection.h:62