5
5
6
6
#include " esp-box.hpp"
7
7
8
+ #include " kalman_filter.hpp"
9
+
8
10
using namespace std ::chrono_literals;
9
11
10
12
static constexpr size_t MAX_CIRCLES = 100 ;
@@ -93,9 +95,24 @@ extern "C" void app_main(void) {
93
95
94
96
// add text in the center of the screen
95
97
lv_obj_t *label = lv_label_create (lv_screen_active ());
96
- lv_label_set_text (label, " Touch the screen!\n Press the home button to clear circles." );
97
- lv_obj_align (label, LV_ALIGN_CENTER, 0 , 0 );
98
- lv_obj_set_style_text_align (label, LV_TEXT_ALIGN_CENTER, 0 );
98
+ static std::string label_text =
99
+ " \n\n\n\n\n Touch the screen!\n Press the home button to clear circles." ;
100
+ lv_label_set_text (label, label_text.c_str ());
101
+ lv_obj_align (label, LV_ALIGN_TOP_LEFT, 0 , 0 );
102
+ lv_obj_set_style_text_align (label, LV_TEXT_ALIGN_LEFT, 0 );
103
+
104
+ /* Create style*/
105
+ static lv_style_t style_line;
106
+ lv_style_init (&style_line);
107
+ lv_style_set_line_width (&style_line, 8 );
108
+ lv_style_set_line_color (&style_line, lv_palette_main (LV_PALETTE_BLUE));
109
+ lv_style_set_line_rounded (&style_line, true );
110
+
111
+ // make a line for showing the direction of "down"
112
+ lv_obj_t *line = lv_line_create (lv_screen_active ());
113
+ static lv_point_precise_t line_points[] = {{0 , 0 }, {box.lcd_width (), box.lcd_height ()}};
114
+ lv_line_set_points (line, line_points, 2 );
115
+ lv_obj_add_style (line, &style_line, 0 );
99
116
100
117
// add a button in the top left which (when pressed) will rotate the display
101
118
// through 0, 90, 180, 270 degrees
@@ -135,6 +152,7 @@ extern "C" void app_main(void) {
135
152
},
136
153
.task_config = {
137
154
.name = " lv_task" ,
155
+ .stack_size_bytes = 6 * 1024 ,
138
156
}});
139
157
lv_task.start ();
140
158
@@ -151,19 +169,19 @@ extern "C" void app_main(void) {
151
169
152
170
// make a task to read out the IMU data and print it to console
153
171
espp::Task imu_task (
154
- {.callback = [&label](std::mutex &m, std::condition_variable &cv) -> bool {
172
+ {.callback = [&label, &line ](std::mutex &m, std::condition_variable &cv) -> bool {
155
173
// sleep first in case we don't get IMU data and need to exit early
156
174
{
157
175
std::unique_lock<std::mutex> lock (m);
158
- cv.wait_for (lock, 100ms );
176
+ cv.wait_for (lock, 10ms );
159
177
}
160
178
static auto &box = espp::EspBox::get ();
161
179
static auto imu = box.imu ();
162
180
163
- auto now = std::chrono::steady_clock::now ();
181
+ auto now = esp_timer_get_time (); // time in microseconds
164
182
static auto t0 = now;
165
183
auto t1 = now;
166
- float dt = std::chrono::duration< float > (t1 - t0). count ();
184
+ float dt = (t1 - t0) / 1'000'000 . 0f ; // convert us to s
167
185
t0 = t1;
168
186
169
187
std::error_code ec;
@@ -181,17 +199,51 @@ extern "C" void app_main(void) {
181
199
return false ;
182
200
}
183
201
184
- static espp::icm42607::ComplimentaryAngle angle{};
185
- angle = imu->complimentary_filter (dt, angle, accel, gyro);
202
+ float roll = 0 , pitch = 0 ;
203
+
204
+ // with only the accelerometer + gyroscope, we can't get yaw :(
205
+ static espp::KalmanFilter kalmanPitch;
206
+ static espp::KalmanFilter kalmanRoll;
207
+
208
+ // Compute pitch and roll from accelerometer
209
+ float accelPitch =
210
+ atan2 (accel.y , sqrt (accel.x * accel.x + accel.z * accel.z )) * 180 .0f / M_PI;
211
+ float accelRoll = atan2 (-accel.x , accel.z ) * 180 .0f / M_PI;
186
212
187
- std::string text = " Touch the screen!\n Press the home button to clear circles.\n " ;
213
+ // Apply Kalman filter
214
+ pitch = kalmanPitch.update (accelPitch, gyro.y , dt);
215
+ roll = kalmanRoll.update (accelRoll, gyro.x , dt);
216
+
217
+ std::string text = fmt::format (" {}\n\n\n\n " , label_text);
188
218
text += fmt::format (" Accel: {:02.2f} {:02.2f} {:02.2f}\n " , accel.x , accel.y , accel.z );
189
219
text += fmt::format (" Gyro: {:03.2f} {:03.2f} {:03.2f}\n " , gyro.x , gyro.y , gyro.z );
190
- text += fmt::format (" Angle: {:03.2f} {:03.2f}\n " , angle. roll , angle. pitch );
220
+ text += fmt::format (" Angle: {:03.2f} {:03.2f}\n " , roll, pitch);
191
221
text += fmt::format (" Temp: {:02.1f} C\n " , temp);
192
222
223
+ float rollRad = roll * M_PI / 180 .0f ;
224
+ float pitchRad = pitch * M_PI / 180 .0f ;
225
+
226
+ // use the pitch to to draw a line on the screen indiating the
227
+ // direction from the center of the screen to "down"
228
+ int x0 = box.lcd_width () / 2 ;
229
+ int y0 = box.lcd_height () / 2 ;
230
+ int x1 = x0 - 50 * cos (-pitchRad);
231
+ int y1 = y0 + 50 * sin (-pitchRad);
232
+
233
+ float vx = sin (pitchRad);
234
+ float vy = -cos (pitchRad) * sin (rollRad);
235
+ float vz = -cos (pitchRad) * cos (rollRad);
236
+
237
+ x1 = x0 - 50 * vy;
238
+ y1 = y0 - 50 * vx;
239
+
240
+ static lv_point_precise_t line_points[] = {{x0, y0 }, {x1, y1 }};
241
+ line_points[1 ].x = x1;
242
+ line_points[1 ].y = y1 ;
243
+
193
244
std::lock_guard<std::recursive_mutex> lock (lvgl_mutex);
194
245
lv_label_set_text (label, text.c_str ());
246
+ lv_line_set_points (line, line_points, 2 );
195
247
196
248
return false ;
197
249
},
0 commit comments