-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy patharduino_accelerometer_handler.cpp
141 lines (120 loc) · 4.57 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
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/* 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.
==============================================================================*/
#if defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE)
#define ARDUINO_EXCLUDE_CODE
#endif // defined(ARDUINO) && !defined(ARDUINO_ARDUINO_NANO33BLE)
#ifndef ARDUINO_EXCLUDE_CODE
#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) {
// Switch on the IMU
if (!IMU.begin()) {
TF_LITE_REPORT_ERROR(error_reporter, "Failed to initialize IMU");
return kTfLiteError;
}
// Make sure we are pulling measurements into a FIFO.
// If you see an error on this line, make sure you have at least v1.1.0 of the
// Arduino_LSM9DS1 library installed.
IMU.setContinuousMode();
// 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));
TF_LITE_REPORT_ERROR(error_reporter, "Magic starts!");
return kTfLiteOk;
}
bool ReadAccelerometer(tflite::ErrorReporter* error_reporter, float* input,
int length) {
// 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)) {
TF_LITE_REPORT_ERROR(error_reporter, "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 rotating the axis
// order for compatibility with model (sensor orientation is different on
// Arduino Nano BLE Sense compared with SparkFun Edge).
// The expected orientation of the Arduino on the wand is with the USB port
// facing down the shaft towards the user's hand, with the reset button
// pointing at the user's face:
//
// ____
// | |<- Arduino board
// | |
// | () | <- Reset button
// | |
// -TT- <- USB port
// ||
// ||<- Wand
// ....
// ||
// ||
// ()
//
const float norm_x = -z;
const float norm_y = y;
const float norm_z = x;
save_data[begin_index++] = norm_x * 1000;
save_data[begin_index++] = norm_y * 1000;
save_data[begin_index++] = norm_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;
}
#endif // ARDUINO_EXCLUDE_CODE