Skip to content

Commit

Permalink
Merge branch 'main' into RET-1025_handle_motor_driver_errors
Browse files Browse the repository at this point in the history
  • Loading branch information
pmoegenburg committed Jan 16, 2024
2 parents 9652cb5 + 05b075d commit ecffbdb
Show file tree
Hide file tree
Showing 21 changed files with 178 additions and 32 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/release_bundle.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ on:
branches:
- '*'
tags:
- '*'
- 'v*'
workflow_dispatch:

env:
Expand Down
2 changes: 1 addition & 1 deletion cmake/FindBoost.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ Cache Variables
include(FetchContent)
string(REPLACE "." "_" "_boost_archive_version_component" "${Boost_FIND_VERSION}")
set(boost_localinstall_root ${CMAKE_SOURCE_DIR}/stm32-tools/boost-${_boost_archive_version_component})
set(boost_archive_root "https://boostorg.jfrog.io/artifactory/main/release")
set(boost_archive_root "https://archives.boost.io/release")
set(boost_archive_url "${boost_archive_root}/${Boost_FIND_VERSION}/source/boost_${_boost_archive_version_component}.zip")
FetchContent_Declare(Boost
PREFIX "${boost_localinstall_root}"
Expand Down
2 changes: 1 addition & 1 deletion cmake/boost-cmake/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ project(Boost-CMake)

option(BOOST_DISABLE_TESTS "Do not build test targets, even if building standalone" OFF)

set(BOOST_URL "https://boostorg.jfrog.io/artifactory/main/release/1.71.0/source/boost_1_71_0.tar.bz2" CACHE STRING "Boost download URL")
set(BOOST_URL "https://archives.boost.io/release/1.71.0/source/boost_1_71_0.tar.bz2" CACHE STRING "Boost download URL")
set(BOOST_URL_SHA256 "d73a8da01e8bf8c7eda40b4c84915071a8c8a0df4a6734537ddde4a8580524ee" CACHE STRING "Boost download URL SHA256 checksum")

include(FetchContent)
Expand Down
5 changes: 3 additions & 2 deletions gripper/firmware/interfaces_grip_motor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

constexpr uint32_t PWM_MAX = 60;
constexpr uint32_t PWM_MIN = 7;
auto constexpr pwm_freq = double(GRIPPER_JAW_PWM_FREQ_HZ);

struct motor_hardware::UsageEEpromConfig brushed_usage_config {
std::array<UsageRequestSet, 3> {
Expand Down Expand Up @@ -74,7 +75,7 @@ struct motor_hardware::BrushedHardwareConfig brushed_motor_conf {
.port = ESTOP_IN_PORT,
.pin = ESTOP_IN_PIN,
.active_setting = GPIO_PIN_RESET},
.encoder_interrupt_freq = double(GRIPPER_JAW_PWM_FREQ_HZ),
.encoder_interrupt_freq = pwm_freq,

/* the expected behavior with these pid values is that the motor runs at
* full power until it's about 2mm away and then it slows down on that
Expand Down Expand Up @@ -137,7 +138,7 @@ static lms::LinearMotionSystemConfig<lms::GearBoxConfig> gear_config{
.encoder_pulses_per_rev = 512};

static error_tolerance_config::BrushedMotorErrorTolerance error_conf(
gear_config);
gear_config, pwm_freq);

static brushed_motor::BrushedMotor grip_motor(gear_config,
brushed_motor_hardware_iface,
Expand Down
3 changes: 2 additions & 1 deletion gripper/simulator/interfaces.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ static auto gear_conf = lms::LinearMotionSystemConfig<lms::GearBoxConfig>{
.microstep = 0,
.encoder_pulses_per_rev = 512};

static error_tolerance_config::BrushedMotorErrorTolerance error_conf(gear_conf);
static error_tolerance_config::BrushedMotorErrorTolerance error_conf(gear_conf,
32000);

static auto grip_motor = brushed_motor::BrushedMotor(
gear_conf, brushed_motor_hardware_iface, brushed_motor_driver_iface,
Expand Down
3 changes: 3 additions & 0 deletions include/bootloader/core/ids.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ typedef enum {
can_messageid_set_gripper_error_tolerance = 0x47,
can_messageid_gripper_jaw_state_request = 0x48,
can_messageid_gripper_jaw_state_response = 0x49,
can_messageid_set_gripper_jaw_holdoff_request = 0x401,
can_messageid_gripper_jaw_holdoff_request = 0x402,
can_messageid_gripper_jaw_holdoff_response = 0x403,
can_messageid_acknowledgement = 0x50,
can_messageid_read_presence_sensing_voltage_request = 0x600,
can_messageid_read_presence_sensing_voltage_response = 0x601,
Expand Down
3 changes: 3 additions & 0 deletions include/can/core/ids.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ enum class MessageId {
set_gripper_error_tolerance = 0x47,
gripper_jaw_state_request = 0x48,
gripper_jaw_state_response = 0x49,
set_gripper_jaw_holdoff_request = 0x401,
gripper_jaw_holdoff_request = 0x402,
gripper_jaw_holdoff_response = 0x403,
acknowledgement = 0x50,
read_presence_sensing_voltage_request = 0x600,
read_presence_sensing_voltage_response = 0x601,
Expand Down
3 changes: 2 additions & 1 deletion include/can/core/message_handlers/motion.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,8 @@ class BrushedMotionHandler {
std::variant<std::monostate, DisableMotorRequest, EnableMotorRequest,
ReadLimitSwitchRequest, MotorPositionRequest,
SetGripperErrorToleranceRequest, GetMotorUsageRequest,
GripperJawStateRequest>;
GripperJawStateRequest, SetGripperJawHoldoffRequest,
GripperJawHoldoffRequest>;

BrushedMotionHandler(BrushedMotionTaskClient &motion_client)
: motion_client{motion_client} {}
Expand Down
42 changes: 40 additions & 2 deletions include/can/core/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1557,6 +1557,44 @@ struct GripperJawStateResponse
-> bool = default;
};

struct SetGripperJawHoldoffRequest
: BaseMessage<MessageId::set_gripper_jaw_holdoff_request> {
uint32_t message_index;
uint32_t holdoff_ms;

template <bit_utils::ByteIterator Input, typename Limit>
static auto parse(Input body, Limit limit) -> SetGripperJawHoldoffRequest {
uint32_t holdoff_ms = 0;
uint32_t msg_ind = 0;

body = bit_utils::bytes_to_int(body, limit, msg_ind);
body = bit_utils::bytes_to_int(body, limit, holdoff_ms);
return SetGripperJawHoldoffRequest{.message_index = msg_ind,
.holdoff_ms = holdoff_ms};
}
auto operator==(const SetGripperJawHoldoffRequest& other) const
-> bool = default;
};

using GripperJawHoldoffRequest = Empty<MessageId::gripper_jaw_holdoff_request>;

struct GripperJawHoldoffResponse
: BaseMessage<MessageId::gripper_jaw_holdoff_response> {
uint32_t message_index;
uint32_t holdoff_ms;

template <bit_utils::ByteIterator Output, typename Limit>
auto serialize(Output body, Limit limit) const -> uint8_t {
auto iter = bit_utils::int_to_bytes(message_index, body, limit);
iter = bit_utils::int_to_bytes(static_cast<uint32_t>(holdoff_ms), iter,
limit);
return iter - body;
}

auto operator==(const GripperJawHoldoffResponse& other) const
-> bool = default;
};

/**
* A variant of all message types we might send..
*/
Expand All @@ -1572,8 +1610,8 @@ using ResponseMessageType = std::variant<
BindSensorOutputResponse, GripperInfoResponse, TipActionResponse,
PeripheralStatusResponse, BrushedMotorConfResponse,
UpdateMotorPositionEstimationResponse, BaselineSensorResponse,
PushTipPresenceNotification, GetMotorUsageResponse,
ReadMotorDriverErrorStatusResponse, GripperJawStateResponse,
PushTipPresenceNotification, GetMotorUsageResponse, GripperJawStateResponse,
GripperJawHoldoffResponse, ReadMotorDriverErrorStatusResponse,
MotorDriverInErrorState>;

} // namespace can::messages
4 changes: 3 additions & 1 deletion include/gripper/core/can_task.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ using BrushedMotionDispatchTarget = can::dispatch::DispatchParseTarget<
can::messages::DisableMotorRequest, can::messages::EnableMotorRequest,
can::messages::ReadLimitSwitchRequest, can::messages::MotorPositionRequest,
can::messages::SetGripperErrorToleranceRequest,
can::messages::GetMotorUsageRequest, can::messages::GripperJawStateRequest>;
can::messages::GetMotorUsageRequest, can::messages::GripperJawStateRequest,
can::messages::SetGripperJawHoldoffRequest,
can::messages::GripperJawHoldoffRequest>;
using BrushedMoveGroupDispatchTarget = can::dispatch::DispatchParseTarget<
can::message_handlers::move_group::BrushedMoveGroupHandler<
g_tasks::QueueClient>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,17 @@ class MotionController {
S15Q16_RADIX));
}

void set_idle_holdoff(
const can::messages::SetGripperJawHoldoffRequest& can_msg) {
error_config.update_idle_holdoff_ticks(
fixed_point_to_float(can_msg.holdoff_ms, S15Q16_RADIX));
}

auto get_idle_holdoff_ms() -> uint32_t {
return convert_to_fixed_point(error_config.get_holdoff_ms(),
S15Q16_RADIX);
}

template <usage_storage_task::TaskClient UsageClient>
void send_usage_data(uint32_t message_index, UsageClient& usage_client) {
usage_messages::GetUsageRequest req = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,11 +25,6 @@ using namespace motor_messages;
*
*/

static constexpr uint32_t HOLDOFF_TICKS =
32; // hold off for 1 ms (with a 32k Hz timer)
// using the logic analyzer it takes about 0.2-0.3 ms for the output
// to stablize after changing directions of the PWM

template <template <class> class QueueImpl,
move_status_reporter_task::BrushedTaskClient StatusClient>
requires MessageQueue<QueueImpl<BrushedMove>, BrushedMove>
Expand Down Expand Up @@ -209,7 +204,7 @@ class BrushedMotorInterruptHandler {
}
cancel_and_clear_moves(can::ids::ErrorCode::stop_requested,
can::ids::ErrorSeverity::warning);
} else if (tick < HOLDOFF_TICKS) {
} else if (tick < error_conf.idle_holdoff_ticks) {
tick++;
} else if (_has_active_move) {
execute_active_move();
Expand All @@ -223,7 +218,7 @@ class BrushedMotorInterruptHandler {
* the encoder is idle */
return !(buffered_move.stop_condition ==
MoveStopCondition::limit_switch ||
tick < HOLDOFF_TICKS);
tick < error_conf.idle_holdoff_ticks);
}

void set_enc_idle_state(bool val) {
Expand Down Expand Up @@ -419,6 +414,10 @@ class BrushedMotorInterruptHandler {

auto has_active_move() -> bool { return _has_active_move.load(); }

[[nodiscard]] auto get_idle_holdoff_ticks() const -> uint32_t {
return error_conf.idle_holdoff_ticks;
}

std::atomic<bool> is_idle = true;
uint32_t tick = 0;
uint32_t timeout_ticks = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,24 @@ namespace error_tolerance_config {
static constexpr double ACCEPTABLE_DISTANCE_TOLERANCE_MM = 2;
static constexpr double UNWANTED_MOVEMENT_DISTANCE_MM = 2;

// hold off for 1 ms (with a 32k Hz timer)
// using the logic analyzer it takes about 0.2-0.3 ms for the output
// to stablize after changing directions of the PWM
static constexpr double IDLE_HOLDOFF_MS = 1;

class BrushedMotorErrorTolerance {
public:
BrushedMotorErrorTolerance(
lms::LinearMotionSystemConfig<lms::GearBoxConfig>& gearbox_config)
: gear_conf(gearbox_config) {
lms::LinearMotionSystemConfig<lms::GearBoxConfig>& gearbox_config,
double pwm_timer_freq)
: gear_conf(gearbox_config), timer_freq(pwm_timer_freq) {
acceptable_position_error =
int32_t(gear_conf.get_encoder_pulses_per_mm() *
ACCEPTABLE_DISTANCE_TOLERANCE_MM);
unwanted_movement_threshold =
int32_t(gear_conf.get_encoder_pulses_per_mm() *
UNWANTED_MOVEMENT_DISTANCE_MM);
idle_holdoff_ticks = uint32_t(timer_freq / 1000 * IDLE_HOLDOFF_MS);
}

void update_tolerance(double pos_error, double unwanted_movement) {
Expand All @@ -27,9 +34,20 @@ class BrushedMotorErrorTolerance {
unwanted_movement_threshold =
int32_t(gear_conf.get_encoder_pulses_per_mm() * unwanted_movement);
}

void update_idle_holdoff_ticks(double holdoff_ms) {
idle_holdoff_ticks = uint32_t(timer_freq / 1000 * holdoff_ms);
}

[[nodiscard]] auto get_holdoff_ms() const -> double {
return double(idle_holdoff_ticks * 1000 / timer_freq);
}

lms::LinearMotionSystemConfig<lms::GearBoxConfig>& gear_conf;
double timer_freq;
int32_t acceptable_position_error = 0;
int32_t unwanted_movement_threshold = 0;
uint32_t idle_holdoff_ticks = 0;
};

} // namespace error_tolerance_config
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,19 @@ class MotionControllerMessageHandler {
can_client.send_can_message(can::ids::NodeId::host, msg);
}

void handle(const can::messages::SetGripperJawHoldoffRequest& m) {
controller.set_idle_holdoff(m);
can_client.send_can_message(can::ids::NodeId::host,
can::messages::ack_from_request(m));
}

void handle(const can::messages::GripperJawHoldoffRequest& m) {
auto holdoff = controller.get_idle_holdoff_ms();
can::messages::GripperJawHoldoffResponse msg{
.message_index = m.message_index, .holdoff_ms = holdoff};
can_client.send_can_message(can::ids::NodeId::host, msg);
}

brushed_motion_controller::MotionController<MEConfig>& controller;
CanClient& can_client;
UsageClient& usage_client;
Expand Down
4 changes: 3 additions & 1 deletion include/motor-control/core/tasks/messages.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,9 @@ using BrushedMotionControllerTaskMessage = std::variant<
can::messages::AddBrushedLinearMoveRequest, can::messages::StopRequest,
can::messages::ReadLimitSwitchRequest, can::messages::MotorPositionRequest,
can::messages::SetGripperErrorToleranceRequest,
can::messages::GetMotorUsageRequest, can::messages::GripperJawStateRequest>;
can::messages::GetMotorUsageRequest, can::messages::GripperJawStateRequest,
can::messages::SetGripperJawHoldoffRequest,
can::messages::GripperJawHoldoffRequest>;

using BrushedMoveGroupTaskMessage = std::variant<
std::monostate, can::messages::ClearAllMoveGroupsRequest,
Expand Down
1 change: 1 addition & 0 deletions include/motor-control/firmware/motor_control_hardware.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ uint16_t motor_hardware_encoder_pulse_count(void* encoder_handle);
uint16_t motor_hardware_encoder_pulse_count_with_overflow(void* encoder_handle, int8_t *overflows);
void motor_hardware_reset_encoder_count(void* encoder_handle, uint16_t reset_value);
uint16_t motor_hardware_get_stopwatch_pulses(void* stopwatch_handle, uint8_t clear);
void motor_hardware_delay(uint32_t delay);
#ifdef __cplusplus
} // extern "C"
#endif // __cplusplus
Expand Down
12 changes: 12 additions & 0 deletions include/motor-control/tests/mock_brushed_motor_components.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,6 +183,18 @@ struct MockBrushedMotionController {
fixed_point_to_float(can_msg.max_unwanted_movement_mm,
S15Q16_RADIX));
}

void set_idle_holdoff(
const can::messages::SetGripperJawHoldoffRequest& can_msg) {
error_config.update_idle_holdoff_ticks(
fixed_point_to_float(can_msg.holdoff_ms, S15Q16_RADIX));
}

[[nodiscard]] auto get_idle_holdoff_ms() const -> uint32_t {
return convert_to_fixed_point(error_config.get_holdoff_ms(),
S15Q16_RADIX);
}

BrushedMotorErrorTolerance& error_config;
};

Expand Down
6 changes: 6 additions & 0 deletions motor-control/firmware/motor_control_hardware.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
#include "FreeRTOS.h"
#include "platform_specific_hal_conf.h"
#include "stm32g4xx_hal_tim.h"
#include "stm32g4xx_hal.h"
#include "task.h"

HAL_StatusTypeDef custom_stop_pwm_it(TIM_HandleTypeDef* htim,
Expand Down Expand Up @@ -131,3 +132,8 @@ uint16_t motor_hardware_get_stopwatch_pulses(void* stopwatch_handle, uint8_t cle
return count;
}

void motor_hardware_delay(uint32_t delay) {
HAL_Delay(delay);
}


2 changes: 2 additions & 0 deletions motor-control/firmware/stepper_motor/motor_hardware.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@ void MotorHardware::activate_motor() {
void MotorHardware::deactivate_motor() {
if (pins.ebrake.has_value()) {
gpio::set(pins.ebrake.value());
motor_hardware_delay(10);
}
motor_hardware_delay(10);
gpio::reset(pins.enable);
}
void MotorHardware::start_timer_interrupt() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ auto _gear_config = lms::LinearMotionSystemConfig<lms::GearBoxConfig>{
.microstep = 0,
.encoder_pulses_per_rev = 512};
auto _error_config =
error_tolerance_config::BrushedMotorErrorTolerance{_gear_config};
error_tolerance_config::BrushedMotorErrorTolerance{_gear_config, 32000};

SCENARIO("testing error tolerance handling") {
GIVEN("a motion controller and motor interrupt handler") {
Expand Down Expand Up @@ -45,4 +45,26 @@ SCENARIO("testing error tolerance handling") {
}
}
}
}

SCENARIO("testing brushed motor holdoff value") {
GIVEN("a motion controller and motor interrupt handler") {
test_mocks::MockBrushedMotionController controller(_error_config);
CHECK(_error_config.get_holdoff_ms() == 1.0);
WHEN("a set idle holdoff request is handled") {
auto msg = can::messages::SetGripperJawHoldoffRequest{
.message_index = 0,
.holdoff_ms = 1310720, // 20 ms
};
controller.set_idle_holdoff(msg);
THEN("idle holdoff value should be updated in error config") {
CHECK(_error_config.get_holdoff_ms() == 20.0);
CHECK(_error_config.idle_holdoff_ticks == 640);

THEN("controller should get the correct holdoff ms value") {
CHECK(controller.get_idle_holdoff_ms() == 1310720);
}
}
}
}
}
Loading

0 comments on commit ecffbdb

Please sign in to comment.