Skip to content

Commit ea272e6

Browse files
authored
feat(drv2605): Add support for calibration and other modes / controls (#456)
* feat(drv2605): Add support for calibration and other modes / controls * update readme and finalize impl some more * readme: update
1 parent 590d028 commit ea272e6

File tree

3 files changed

+618
-65
lines changed

3 files changed

+618
-65
lines changed

components/drv2605/example/README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ eccentric rotating mass (ERM) haptic motors.
66

77
![image](https://user-images.githubusercontent.com/213467/225453151-eeba4c4f-7070-4e87-9aa6-741f8a2400ca.png)
88

9+
<!-- markdown-toc start - Don't edit this section. Run M-x markdown-toc-refresh-toc -->
10+
**Table of Contents**
11+
12+
- [Drv2605 Example](#drv2605-example)
13+
- [How to use example](#how-to-use-example)
14+
- [Hardware Required](#hardware-required)
15+
- [Build and Flash](#build-and-flash)
16+
- [Output](#output)
17+
18+
<!-- markdown-toc end -->
19+
920
## How to use example
1021

1122
### Hardware Required
@@ -17,6 +28,8 @@ The sample has code for both ERM and LRA, but make sure to update the call to
1728
`drv2605.select_library(...)` depending on which type of motor you have (ERM is
1829
1-5, LRA is 6).
1930

31+
This sample also shows how to configure and run motor calibration.
32+
2033
### Build and Flash
2134

2235
Build the project and flash it to the board, then run monitor tool to view serial output:
@@ -31,3 +44,7 @@ idf.py -p PORT flash monitor
3144

3245
See the Getting Started Guide for full steps to configure and use ESP-IDF to build projects.
3346

47+
### Output
48+
49+
![CleanShot 2025-06-12 at 11 16 22](https://github.com/user-attachments/assets/cc996d12-fa8e-4c20-8267-b3f1b912c1fe)
50+

components/drv2605/example/main/drv2605_example.cpp

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,49 +13,64 @@ extern "C" void app_main(void) {
1313
static espp::Logger logger({.tag = "drv2605 example", .level = espp::Logger::Verbosity::INFO});
1414
// This example shows using the i2c haptic motor driver (drv2605)
1515
{
16-
logger.info("Running i2c adc example!");
16+
logger.info("Starting!");
1717
//! [drv2605 example]
1818
// make the I2C that we'll use to communicate
1919
espp::I2c i2c({
2020
.port = I2C_NUM_1,
2121
.sda_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SDA_GPIO,
2222
.scl_io_num = (gpio_num_t)CONFIG_EXAMPLE_I2C_SCL_GPIO,
2323
});
24+
25+
using Driver = espp::Drv2605;
26+
2427
// make the actual drv2605 class
25-
espp::Drv2605 drv2605(espp::Drv2605::Config{
26-
.device_address = espp::Drv2605::DEFAULT_ADDRESS,
28+
Driver drv2605(Driver::Config{
29+
.device_address = Driver::DEFAULT_ADDRESS,
2730
.write = std::bind(&espp::I2c::write, &i2c, std::placeholders::_1, std::placeholders::_2,
2831
std::placeholders::_3),
2932
.read_register =
3033
std::bind(&espp::I2c::read_at_register, &i2c, std::placeholders::_1,
3134
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4),
32-
.motor_type = espp::Drv2605::MotorType::LRA});
35+
.motor_type = Driver::MotorType::LRA,
36+
.log_level = espp::Logger::Verbosity::INFO,
37+
});
3338
std::error_code ec;
3439
// we're using an ERM motor, so select an ERM library (1-5).
3540
// drv2605.select_library(1, ec);
3641
// we're using an LRA motor, so select an LRA library (6).
37-
drv2605.select_library(espp::Drv2605::Library::LRA, ec);
42+
drv2605.select_library(Driver::Library::LRA, ec);
3843
if (ec) {
3944
logger.error("select library failed: {}", ec.message());
4045
}
46+
47+
// do the calibration for the LRA motor
48+
Driver::LraCalibrationSettings lra_calibration_settings{};
49+
lra_calibration_settings.rated_voltage = 255;
50+
lra_calibration_settings.overdrive_clamp = 255;
51+
lra_calibration_settings.drive_time = Driver::lra_freq_to_drive_time(200.0f);
52+
Driver::CalibratedData calibrated_data;
53+
if (!drv2605.calibrate(lra_calibration_settings, calibrated_data, ec)) {
54+
logger.error("calibration failed: {}", ec.message());
55+
return;
56+
}
57+
logger.info("calibration complete: {}", calibrated_data);
58+
4159
// make the task which will cycle through all the waveforms
4260
auto task_fn = [&drv2605](std::mutex &m, std::condition_variable &cv) {
43-
static auto start = std::chrono::high_resolution_clock::now();
44-
auto now = std::chrono::high_resolution_clock::now();
45-
auto elapsed = std::chrono::duration<float>(now - start).count();
4661
static uint8_t waveform = 0;
4762
std::error_code ec;
4863
drv2605.stop(ec);
4964
if (ec) {
5065
logger.error("stop failed: {}", ec.message());
5166
return false;
5267
}
53-
drv2605.set_waveform(0, (espp::Drv2605::Waveform)waveform, ec);
68+
drv2605.set_waveform(0, (Driver::Waveform)waveform, ec);
5469
if (ec) {
5570
logger.error("set waveform failed: {}", ec.message());
5671
return false;
5772
}
58-
drv2605.set_waveform(1, espp::Drv2605::Waveform::END, ec);
73+
drv2605.set_waveform(1, Driver::Waveform::END, ec);
5974
if (ec) {
6075
logger.error("set waveform failed: {}", ec.message());
6176
return false;
@@ -66,10 +81,10 @@ extern "C" void app_main(void) {
6681
return false;
6782
}
6883
waveform++;
69-
if (waveform > (uint8_t)espp::Drv2605::Waveform::MAX) {
84+
if (waveform > (uint8_t)Driver::Waveform::MAX) {
7085
waveform = 0;
7186
}
72-
logger.info("{:.3f}, {}", elapsed, waveform);
87+
logger.info("{}", waveform);
7388
// NOTE: sleeping in this way allows the sleep to exit early when the
7489
// task is being stopped / destroyed
7590
{

0 commit comments

Comments
 (0)