Skip to content

Commit 822d177

Browse files
committed
feat(icm42670): Add ICM42607 / ICM42670 IMU component
* Add new component for IMU * Add IMU to esp-box component and test it in the example IMUs are nice, and exposing the IMU via the hardware component / bsp (esp-box in this case) is even better. Testing / showcasing the IMU in the bsp example is _even_ better. Build and run `esp-box/example` on ESP-BOX and ensure the IMU works by looking at the on-screen-display while moving the box around various orientations.
1 parent 01c6dd0 commit 822d177

File tree

6 files changed

+1022
-1
lines changed

6 files changed

+1022
-1
lines changed

components/esp-box/CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
idf_component_register(
22
INCLUDE_DIRS "include"
33
SRC_DIRS "src"
4-
REQUIRES driver base_component codec display display_drivers i2c input_drivers interrupt gt911 task tt21100
4+
REQUIRES driver base_component codec display display_drivers i2c input_drivers interrupt gt911 task tt21100 icm42607
55
REQUIRED_IDF_TARGETS "esp32s3"
66
)

components/esp-box/example/main/esp_box_example.cpp

+60
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,12 @@ extern "C" void app_main(void) {
8080
return;
8181
}
8282

83+
// initialize the IMU
84+
if (!box.initialize_imu()) {
85+
logger.error("Failed to initialize IMU!");
86+
return;
87+
}
88+
8389
// set the background color to black
8490
lv_obj_t *bg = lv_obj_create(lv_screen_active());
8591
lv_obj_set_size(bg, box.lcd_width(), box.lcd_height());
@@ -143,6 +149,60 @@ extern "C" void app_main(void) {
143149
// set the display brightness to be 75%
144150
box.brightness(75.0f);
145151

152+
// make a task to read out the IMU data and print it to console
153+
espp::Task imu_task(
154+
{.callback = [&label](std::mutex &m, std::condition_variable &cv) -> bool {
155+
// sleep first in case we don't get IMU data and need to exit early
156+
{
157+
std::unique_lock<std::mutex> lock(m);
158+
cv.wait_for(lock, 100ms);
159+
}
160+
static auto &box = espp::EspBox::get();
161+
static auto imu = box.imu();
162+
163+
auto now = std::chrono::steady_clock::now();
164+
static auto t0 = now;
165+
auto t1 = now;
166+
float dt = std::chrono::duration<float>(t1 - t0).count();
167+
t0 = t1;
168+
169+
std::error_code ec;
170+
// get accel
171+
auto accel = imu->get_accelerometer(ec);
172+
if (ec) {
173+
return false;
174+
}
175+
auto gyro = imu->get_gyroscope(ec);
176+
if (ec) {
177+
return false;
178+
}
179+
auto temp = imu->get_temperature(ec);
180+
if (ec) {
181+
return false;
182+
}
183+
184+
static espp::icm42607::ComplimentaryAngle angle{};
185+
angle = imu->complimentary_filter(dt, angle, accel, gyro);
186+
187+
std::string text = "Touch the screen!\nPress the home button to clear circles.\n";
188+
text += fmt::format("Accel: {:02.2f} {:02.2f} {:02.2f}\n", accel.x, accel.y, accel.z);
189+
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);
191+
text += fmt::format("Temp: {:02.1f} C\n", temp);
192+
193+
std::lock_guard<std::recursive_mutex> lock(lvgl_mutex);
194+
lv_label_set_text(label, text.c_str());
195+
196+
return false;
197+
},
198+
.task_config = {
199+
.name = "IMU",
200+
.stack_size_bytes = 6 * 1024,
201+
.priority = 10,
202+
.core_id = 0,
203+
}});
204+
imu_task.start();
205+
146206
// loop forever
147207
while (true) {
148208
std::this_thread::sleep_for(1s);

components/esp-box/include/esp-box.hpp

+24
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
#include "es8311.hpp"
2020
#include "gt911.hpp"
2121
#include "i2c.hpp"
22+
#include "icm42607.hpp"
2223
#include "interrupt.hpp"
2324
#include "st7789.hpp"
2425
#include "touchpad_input.hpp"
@@ -32,6 +33,9 @@ namespace espp {
3233
/// - Touchpad
3334
/// - Display
3435
/// - Audio
36+
/// - Interrupts
37+
/// - I2C
38+
/// - IMU (Inertial Measurement Unit)
3539
///
3640
/// The class is a singleton and can be accessed using the get() method.
3741
///
@@ -44,8 +48,13 @@ class EspBox : public BaseComponent {
4448

4549
/// Alias for the display driver used by the ESP-Box display
4650
using DisplayDriver = espp::St7789;
51+
52+
/// Alias for the touchpad data used by the ESP-Box touchpad
4753
using TouchpadData = espp::TouchpadData;
4854

55+
/// Alias the IMU used by the ESP-Box
56+
using Imu = espp::Icm42607<icm42607::Interface::I2C>;
57+
4958
/// The type of the box
5059
enum class BoxType {
5160
UNKNOWN, ///< unknown box
@@ -286,6 +295,18 @@ class EspBox : public BaseComponent {
286295
/// \param num_bytes The number of bytes to play
287296
void play_audio(const uint8_t *data, uint32_t num_bytes);
288297

298+
/////////////////////////////////////////////////////////////////////////////
299+
// IMU
300+
/////////////////////////////////////////////////////////////////////////////
301+
302+
/// Initialize the IMU
303+
/// \return true if the IMU was successfully initialized, false otherwise
304+
bool initialize_imu();
305+
306+
/// Get the IMU
307+
/// \return A shared pointer to the IMU
308+
std::shared_ptr<Imu> imu() const;
309+
289310
protected:
290311
EspBox();
291312
void detect();
@@ -440,6 +461,9 @@ class EspBox : public BaseComponent {
440461
i2s_std_config_t audio_std_cfg;
441462
i2s_event_callbacks_t audio_tx_callbacks_;
442463
std::atomic<bool> has_sound{false};
464+
465+
// IMU
466+
std::shared_ptr<Imu> imu_;
443467
}; // class EspBox
444468
} // namespace espp
445469

components/esp-box/src/imu.cpp

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
#include "esp-box.hpp"
2+
3+
using namespace espp;
4+
5+
bool EspBox::initialize_imu() {
6+
if (imu_) {
7+
logger_.warn("IMU already initialized, not initializing again!");
8+
return false;
9+
}
10+
11+
Imu::Config config{
12+
.device_address = Imu::DEFAULT_ADDRESS,
13+
.write = std::bind(&espp::I2c::write, &internal_i2c_, std::placeholders::_1,
14+
std::placeholders::_2, std::placeholders::_3),
15+
.read = std::bind(&espp::I2c::read, &internal_i2c_, std::placeholders::_1,
16+
std::placeholders::_2, std::placeholders::_3),
17+
.imu_config =
18+
{
19+
.accelerometer_range = Imu::AccelerometerRange::RANGE_2G,
20+
.accelerometer_odr = Imu::AccelerometerODR::ODR_400_HZ,
21+
.gyroscope_range = Imu::GyroscopeRange::RANGE_2000DPS,
22+
.gyroscope_odr = Imu::GyroscopeODR::ODR_400_HZ,
23+
},
24+
.auto_init = true,
25+
};
26+
27+
logger_.info("Initializing IMU with default configuration");
28+
imu_ = std::make_shared<Imu>(config);
29+
30+
return true;
31+
}
32+
33+
std::shared_ptr<EspBox::Imu> EspBox::imu() const { return imu_; }

components/icm42607/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
idf_component_register(
2+
INCLUDE_DIRS "include"
3+
REQUIRES "base_peripheral" "math"
4+
)

0 commit comments

Comments
 (0)