Skip to content

Commit

Permalink
Merge pull request #1 from esp-cpp/feature/cli
Browse files Browse the repository at this point in the history
Feature/cli
  • Loading branch information
finger563 authored Jun 23, 2023
2 parents ac39867 + 18497d6 commit c7687da
Show file tree
Hide file tree
Showing 5 changed files with 152 additions and 65 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ set(EXTRA_COMPONENT_DIRS

set(
COMPONENTS
"main esptool_py filters task monitor mt6701 bldc_motor bldc_driver bldc_haptics"
"main esptool_py cli filters task monitor mt6701 bldc_motor bldc_driver bldc_haptics"
CACHE STRING
"List of components to include"
)
Expand Down
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,15 @@ See the Getting Started Guide for full steps to configure and use ESP-IDF to bui

## Output

This code can be re-run (by modifying the code to change the selected
`DetentConfig` from one of the predefined configurations or by making your own)
to produce various behaviors. Additionally, at the end of each demo, it will
play a haptic buzz / click using the motor.
The haptics (detent configuration, click/buzz) can be configured dynamically at
run-time using the provided CLI, see screenshot below:

![CleanShot 2023-06-23 at 08 45 26](https://github.com/esp-cpp/bldc_test_stand/assets/213467/912aae32-a434-4969-8309-af42a4f5f4c7)

As you can see, the cli also allows you to start and stop the haptic engine
(default is off when the program starts) and allows you to query the position of
the motor based on the current detent config. The default detent config is the
unbounded_no_detents configuration.

For more information, see the documentation or the original PR:
https://github.com/esp-cpp/espp/pull/60
Expand Down
2 changes: 1 addition & 1 deletion components/espp
Submodule espp updated 127 files
194 changes: 135 additions & 59 deletions main/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "bldc_haptics.hpp"
#include "bldc_motor.hpp"
#include "butterworth_filter.hpp"
#include "cli.hpp"
#include "lowpass_filter.hpp"
#include "mt6701.hpp"
#include "task.hpp"
Expand All @@ -21,6 +22,8 @@ static constexpr int I2C_FREQ_HZ = (400 * 1000);
static constexpr int I2C_TIMEOUT_MS = (10);

extern "C" void app_main(void) {
espp::Cli::configure_stdin_stdout();

espp::Logger logger({.tag = "BLDC Test Stand", .level = espp::Logger::Verbosity::DEBUG});

logger.info("Bootup");
Expand Down Expand Up @@ -134,70 +137,143 @@ extern "C" void app_main(void) {
.output_min = -20.0, // angle pid works on velocity (rad/s)
.output_max = 20.0, // angle pid works on velocity (rad/s)
},
.log_level = espp::Logger::Verbosity::INFO});

auto print_detent_config = [&logger](const auto &detent_config) {
if (detent_config == espp::detail::UNBOUNDED_NO_DETENTS) {
logger.info("Setting detent config to UNBOUNDED_NO_DETENTS");
}
if (detent_config == espp::detail::BOUNDED_NO_DETENTS) {
logger.info("Setting detent config to BOUNDED_NO_DETENTS");
}
if (detent_config == espp::detail::MULTI_REV_NO_DETENTS) {
logger.info("Setting detent config to MULTI_REV_NO_DETENTS");
}
if (detent_config == espp::detail::ON_OFF_STRONG_DETENTS) {
logger.info("Setting detent config to ON_OFF_STRONG_DETENTS");
}
if (detent_config == espp::detail::COARSE_VALUES_STRONG_DETENTS) {
logger.info("Setting detent config to COARSE_VALUES_STRONG_DETENTS");
}
if (detent_config == espp::detail::FINE_VALUES_NO_DETENTS) {
logger.info("Setting detent config to FINE_VALUES_NO_DETENTS");
}
if (detent_config == espp::detail::FINE_VALUES_WITH_DETENTS) {
logger.info("Setting detent config to FINE_VALUES_WITH_DETENTS");
}
if (detent_config == espp::detail::MAGNETIC_DETENTS) {
logger.info("Setting detent config to MAGNETIC_DETENTS");
}
if (detent_config == espp::detail::RETURN_TO_CENTER_WITH_DETENTS) {
logger.info("Setting detent config to RETURN_TO_CENTER_WITH_DETENTS");
}
};
.log_level = espp::Logger::Verbosity::WARN});

using BldcHaptics = espp::BldcHaptics<BldcMotor>;

auto haptic_motor = BldcHaptics({.motor = motor,
.kp_factor = 2,
.kd_factor_min = 0.01,
.kd_factor_max = 0.04,
.log_level = espp::Logger::Verbosity::INFO});

// auto detent_config = espp::detail::UNBOUNDED_NO_DETENTS;
// auto detent_config = espp::detail::BOUNDED_NO_DETENTS;
// auto detent_config = espp::detail::MULTI_REV_NO_DETENTS;
// auto detent_config = espp::detail::ON_OFF_STRONG_DETENTS;
auto detent_config = espp::detail::COARSE_VALUES_STRONG_DETENTS;
// auto detent_config = espp::detail::FINE_VALUES_NO_DETENTS;
// auto detent_config = espp::detail::FINE_VALUES_WITH_DETENTS;
// auto detent_config = espp::detail::MAGNETIC_DETENTS;
// auto detent_config = espp::detail::RETURN_TO_CENTER_WITH_DETENTS;

logger.info("{}", detent_config);

haptic_motor.update_detent_config(detent_config);
// this will start the haptic motor thread which will run in the background.
// If we want to change the detent config we can call update_detent_config()
// and it will update the detent config in the background thread.
haptic_motor.start();
print_detent_config(detent_config);

while (true) {
std::this_thread::sleep_for(500ms);
if (driver->is_faulted()) {
logger.error("Driver is faulted, cannot continue haptics");
break;
}
}
.log_level = espp::Logger::Verbosity::WARN});

// set the default detent config to be unbounded no detents so that if
haptic_motor.update_detent_config(espp::detail::UNBOUNDED_NO_DETENTS);

auto root_menu = std::make_unique<cli::Menu>("haptics", "Haptic configuration menu");
root_menu->Insert(
"start",
[&](std::ostream &out) {
out << "Starting motor!\n";
haptic_motor.start();
},
"Start the motor");
root_menu->Insert(
"stop",
[&](std::ostream &out) {
out << "Stopping motor!\n";
haptic_motor.stop();
},
"Stop the motor");
root_menu->Insert(
"position",
[&](std::ostream &out) {
out << "Current position: " << haptic_motor.get_position() << "\n";
},
"Print the current position of the haptic motor");
root_menu->Insert(
"unbounded_no_detents",
[&](std::ostream &out) {
out << "Setting to unbounded no detents!\n";
haptic_motor.update_detent_config(espp::detail::UNBOUNDED_NO_DETENTS);
},
"Set the haptic config to unbounded no detents");
root_menu->Insert(
"bounded_no_detents",
[&](std::ostream &out) {
out << "Setting to bounded no detents!\n";
haptic_motor.update_detent_config(espp::detail::BOUNDED_NO_DETENTS);
},
"Set the haptic config to bounded no detents");
root_menu->Insert(
"multi_rev_no_detents",
[&](std::ostream &out) {
out << "Setting to multi rev no detents!\n";
haptic_motor.update_detent_config(espp::detail::MULTI_REV_NO_DETENTS);
},
"Set the haptic config to multi rev no detents");
root_menu->Insert(
"on_off_strong_detents",
[&](std::ostream &out) {
out << "Setting to on off strong detents!\n";
haptic_motor.update_detent_config(espp::detail::ON_OFF_STRONG_DETENTS);
},
"Set the haptic config to on off strong detents");
root_menu->Insert(
"coarse_values_strong_detents",
[&](std::ostream &out) {
out << "Setting to coarse values strong detents!\n";
haptic_motor.update_detent_config(espp::detail::COARSE_VALUES_STRONG_DETENTS);
},
"Set the haptic config to coarse values strong detents");
root_menu->Insert(
"fine_values_no_detents",
[&](std::ostream &out) {
out << "Setting to fine values no detents!\n";
haptic_motor.update_detent_config(espp::detail::FINE_VALUES_NO_DETENTS);
},
"Set the haptic config to fine values no detents");
root_menu->Insert(
"fine_values_with_detents",
[&](std::ostream &out) {
out << "Setting to fine values with detents!\n";
haptic_motor.update_detent_config(espp::detail::FINE_VALUES_WITH_DETENTS);
},
"Set the haptic config to fine values with detents");
root_menu->Insert(
"magnetic_detents",
[&](std::ostream &out) {
out << "Setting to magnetic detents!\n";
haptic_motor.update_detent_config(espp::detail::MAGNETIC_DETENTS);
},
"Set the haptic config to magnetic detents");
root_menu->Insert(
"return_to_center_with_detents",
[&](std::ostream &out) {
out << "Setting to return to center with detents!\n";
haptic_motor.update_detent_config(espp::detail::RETURN_TO_CENTER_WITH_DETENTS);
},
"Set the haptic config to return to center with detents");
root_menu->Insert(
"click",
[&](std::ostream &out, float strength) {
strength = std::clamp(strength, 0.0f, 10.0f);
espp::detail::HapticConfig config{
.strength = strength,
.frequency = 0.0f, // TODO: unused
.duration = 1ms, // TODO: unused
};
haptic_motor.play_haptic(config);
},
"Play a haptic click / buzz with the given strength (suggested range 1.0 - 5.0)");
root_menu->Insert(
"color",
[](std::ostream &out) {
out << "Colors ON\n";
cli::SetColor();
},
"Enable colors in the cli");
root_menu->Insert(
"nocolor",
[](std::ostream &out) {
out << "Colors OFF\n";
cli::SetNoColor();
},
"Disable colors in the cli");

cli::Cli cli(std::move(root_menu));
// turn the colors on by default :)
cli::SetColor();
// add an exit action to stop the motor when the cli exits
cli.ExitAction([&](auto &out) {
out << "Exiting menu and disabling haptics!\n";
haptic_motor.stop();
out << "Goodbye and thanks for all the fish.\n";
});

espp::Cli input(cli);
input.SetInputHistorySize(10);
input.Start();

// if we've gotten here the cli has finished its session
}
6 changes: 6 additions & 0 deletions sdkconfig.defaults
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
CONFIG_IDF_TARGET="esp32s3"

# enable the console to be default output on the usb-serial-jtag port instead of uart
CONFIG_ESP_CONSOLE_USB_SERIAL_JTAG=y

CONFIG_COMPILER_OPTIMIZATION_PERF=y
# CONFIG_COMPILER_OPTIMIZATION_SIZE=y

Expand All @@ -23,3 +26,6 @@ CONFIG_ESP_DEFAULT_CPU_FREQ_MHZ=240
#
CONFIG_ESP_SYSTEM_EVENT_TASK_STACK_SIZE=4096
CONFIG_ESP_MAIN_TASK_STACK_SIZE=8192

# the cli library requires exceptions right now...
CONFIG_COMPILER_CXX_EXCEPTIONS=y

0 comments on commit c7687da

Please sign in to comment.