-
Notifications
You must be signed in to change notification settings - Fork 20
/
Copy patharduino_accelerometer_handler.cpp
119 lines (101 loc) · 3.71 KB
/
arduino_accelerometer_handler.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
/* Copyright 2019 The TensorFlow Authors. All Rights Reserved.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
==============================================================================*/
#include "accelerometer_handler.h"
#include <Arduino.h>
#include <Arduino_LSM9DS1.h>
#include "constants.h"
// A buffer holding the last 200 sets of 3-channel values
float save_data[600] = {0.0};
// Most recent position in the save_data buffer
int begin_index = 0;
// True if there is not yet enough data to run inference
bool pending_initial_data = true;
// How often we should save a measurement during downsampling
int sample_every_n;
// The number of measurements since we last saved one
int sample_skip_counter = 1;
TfLiteStatus SetupAccelerometer(tflite::ErrorReporter* error_reporter) {
// Wait until we know the serial port is ready
while (!Serial) {
}
// Switch on the IMU
if (!IMU.begin()) {
error_reporter->Report("Failed to initialize IMU");
return kTfLiteError;
}
// Determine how many measurements to keep in order to
// meet kTargetHz
float sample_rate = IMU.accelerationSampleRate();
sample_every_n = static_cast<int>(roundf(sample_rate / kTargetHz));
error_reporter->Report("Magic starts!");
return kTfLiteOk;
}
bool ReadAccelerometer(tflite::ErrorReporter* error_reporter, float* input,
int length, bool reset_buffer) {
// Clear the buffer if required, e.g. after a successful prediction
if (reset_buffer) {
memset(save_data, 0, 600 * sizeof(float));
begin_index = 0;
pending_initial_data = true;
}
// Keep track of whether we stored any new data
bool new_data = false;
// Loop through new samples and add to buffer
while (IMU.accelerationAvailable()) {
float x, y, z;
// Read each sample, removing it from the device's FIFO buffer
if (!IMU.readAcceleration(x, y, z)) {
error_reporter->Report("Failed to read data");
break;
}
// Throw away this sample unless it's the nth
if (sample_skip_counter != sample_every_n) {
sample_skip_counter += 1;
continue;
}
// Write samples to our buffer, converting to milli-Gs
// and flipping y and x order for compatibility with
// model (sensor orientation is different on Arduino
// Nano BLE Sense compared with SparkFun Edge)
save_data[begin_index++] = y * 1000;
save_data[begin_index++] = x * 1000;
save_data[begin_index++] = z * 1000;
// Since we took a sample, reset the skip counter
sample_skip_counter = 1;
// If we reached the end of the circle buffer, reset
if (begin_index >= 600) {
begin_index = 0;
}
new_data = true;
}
// Skip this round if data is not ready yet
if (!new_data) {
return false;
}
// Check if we are ready for prediction or still pending more initial data
if (pending_initial_data && begin_index >= 200) {
pending_initial_data = false;
}
// Return if we don't have enough data
if (pending_initial_data) {
return false;
}
// Copy the requested number of bytes to the provided input tensor
for (int i = 0; i < length; ++i) {
int ring_array_index = begin_index + i - length;
if (ring_array_index < 0) {
ring_array_index += 600;
}
input[i] = save_data[ring_array_index];
}
return true;
}