added retained calibration

This commit is contained in:
2026-01-11 12:03:47 +01:00
parent 55d35c41af
commit e9fe3496ac
8 changed files with 69 additions and 34 deletions

2
.vscode/launch.json vendored
View File

@@ -9,7 +9,7 @@
"showDevDebugOutput": "none", "showDevDebugOutput": "none",
"servertype": "external", "servertype": "external",
"gdbTarget": "localhost:3333", "gdbTarget": "localhost:3333",
"targetId": "nrf54l", "targetId": "stm32h5",
} }
] ]
} }

View File

@@ -4,10 +4,10 @@
}; };
chosen { chosen {
uros,status_led= &green_led_1;
uros,error_led = &red_led_1;
pid,counter = &counter5; pid,counter = &counter5;
pid,active_led = &green_led_1;
pid,offset_led = &yellow_led_1; pid,offset_led = &yellow_led_1;
pid,calibration_led = &red_led_1;
pid,rotenc = &as5600; pid,rotenc = &as5600;
pid,stepper = &stepper0; pid,stepper = &stepper0;
}; };
@@ -39,6 +39,15 @@
status = "okay"; status = "okay";
}; };
&timers5 {
status = "okay";
st,prescaler = <7>;
counter5: counter {
status = "okay";
};
};
&timers6 { &timers6 {
status = "okay"; status = "okay";
st,prescaler = <25>; st,prescaler = <25>;
@@ -48,11 +57,11 @@
}; };
}; };
&timers5 { &timers7 {
status = "okay"; status = "okay";
st,prescaler = <7>; st,prescaler = <25>;
counter5: counter { counter7: counter {
status = "okay"; status = "okay";
}; };
}; };

View File

@@ -35,8 +35,12 @@ CONFIG_STEPPER=y
CONFIG_STEPPER_ADI_TMC2209=y CONFIG_STEPPER_ADI_TMC2209=y
CONFIG_STEPPER_ADI_TMC=y CONFIG_STEPPER_ADI_TMC=y
# reboot
CONFIG_REBOOT=y
# builld # builld
CONFIG_NO_OPTIMIZATIONS=n CONFIG_NO_OPTIMIZATIONS=n
CONFIG_SIZE_OPTIMIZATIONS=n CONFIG_SIZE_OPTIMIZATIONS=n
CONFIG_SPEED_OPTIMIZATIONS=y CONFIG_SPEED_OPTIMIZATIONS=n
CONFIG_DEBUG_OPTIMIZATIONS=n CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y

View File

@@ -4,19 +4,19 @@
bool verify_are_devices_available(void) { bool verify_are_devices_available(void) {
bool devices_ready = true; bool devices_ready = true;
if (!device_is_ready(status_led.port)) { if (!device_is_ready(uros_connection_status_led.port)) {
printk("Status LED not ready\n"); printk("Microros connection status LED not ready\n");
devices_ready = false; devices_ready = false;
} }
if (!device_is_ready(work_led.port)) { if (!device_is_ready(pid_offset_led.port)) {
printk("LED0 not ready\n"); printk("PID offset LED not ready\n");
devices_ready = false; devices_ready = false;
} }
if (!device_is_ready(calibration_led.port)) { if (!device_is_ready(uros_error_led.port)) {
printk("Calibration LED not ready\n"); printk("Microros error LED not ready\n");
devices_ready = false; devices_ready = false;
} }

View File

@@ -12,9 +12,9 @@
#include <devicetree.h> #include <devicetree.h>
#endif #endif
static const struct gpio_dt_spec status_led = GPIO_DT_SPEC_GET(DT_CHOSEN(pid_active_led), gpios); static const struct gpio_dt_spec uros_connection_status_led = GPIO_DT_SPEC_GET(DT_CHOSEN(uros_status_led), gpios);
static const struct gpio_dt_spec work_led = GPIO_DT_SPEC_GET(DT_CHOSEN(pid_offset_led), gpios); static const struct gpio_dt_spec pid_offset_led = GPIO_DT_SPEC_GET(DT_CHOSEN(pid_offset_led), gpios);
static const struct gpio_dt_spec calibration_led = GPIO_DT_SPEC_GET(DT_CHOSEN(pid_calibration_led), gpios); static const struct gpio_dt_spec uros_error_led = GPIO_DT_SPEC_GET(DT_CHOSEN(uros_error_led), gpios);
static const struct device *rotenc0 = DEVICE_DT_GET(DT_CHOSEN(pid_rotenc)); static const struct device *rotenc0 = DEVICE_DT_GET(DT_CHOSEN(pid_rotenc));
static const struct device *stepper0 = DEVICE_DT_GET(DT_CHOSEN(pid_stepper)); static const struct device *stepper0 = DEVICE_DT_GET(DT_CHOSEN(pid_stepper));

View File

@@ -34,6 +34,8 @@ int main(void)
zephyr_transport_read zephyr_transport_read
); );
gpio_pin_configure_dt(&uros_connection_status_led, GPIO_OUTPUT_INACTIVE);
while (1) { while (1) {
micro_ros_state_machine(); micro_ros_state_machine();
} }

View File

@@ -1,8 +1,10 @@
#include "microros_state_machine.hpp" #include "microros_state_machine.hpp"
#include "devices.hpp"
#include "stepper_controller.hpp" #include "stepper_controller.hpp"
#include <zephyr/kernel.h> #include <zephyr/kernel.h>
#include <zephyr/sys/reboot.h>
#include <rcl/rcl.h> #include <rcl/rcl.h>
#include <rclc/rclc.h> #include <rclc/rclc.h>
#include <rclc/executor.h> #include <rclc/executor.h>
@@ -26,6 +28,7 @@ void micro_ros_state_machine() {
static rclc_executor_t executor; static rclc_executor_t executor;
switch (micro_ros_state) { switch (micro_ros_state) {
case ROS_AGENT_CONNECTION_UNINITIALIZED: case ROS_AGENT_CONNECTION_UNINITIALIZED:
gpio_pin_configure_dt(&uros_connection_status_led, GPIO_OUTPUT_INACTIVE);
allocator = rcl_get_default_allocator(); allocator = rcl_get_default_allocator();
printk("allocator initialized!\r\n"); printk("allocator initialized!\r\n");
micro_ros_state = ROS_AGENT_CONNECTION_DISCONNECTED; micro_ros_state = ROS_AGENT_CONNECTION_DISCONNECTED;
@@ -34,9 +37,10 @@ void micro_ros_state_machine() {
StepperController::kill(); StepperController::kill();
rclc_executor_fini(&executor); rclc_executor_fini(&executor);
rclc_support_fini(&support); rclc_support_fini(&support);
if (rclc_support_init(&support, 0, NULL, &allocator) != RCL_RET_OK) { if (rclc_support_init(&support, 0, NULL, &allocator) != RCL_RET_OK) {
printk("Can't init rcl support!\r\n"); printk("Can't init rcl support!\r\n");
k_msleep(1000); k_msleep(200);
break; break;
} }
if (rclc_executor_init(&executor, &support.context, 8, &allocator) != RCL_RET_OK){ if (rclc_executor_init(&executor, &support.context, 8, &allocator) != RCL_RET_OK){
@@ -55,12 +59,14 @@ void micro_ros_state_machine() {
micro_ros_state = ROS_AGENT_CONNECTION_CONNECTED; micro_ros_state = ROS_AGENT_CONNECTION_CONNECTED;
case ROS_AGENT_CONNECTION_UNKNOWN: case ROS_AGENT_CONNECTION_UNKNOWN:
if (rmw_uros_ping_agent(150, 3) != RCL_RET_OK) { if (rmw_uros_ping_agent(100, 1) != RCL_RET_OK) {
micro_ros_state = ROS_AGENT_CONNECTION_DISCONNECTED; micro_ros_state = ROS_AGENT_CONNECTION_ERROR;
gpio_pin_configure_dt(&uros_connection_status_led, GPIO_OUTPUT_INACTIVE);
printk("micro ros agent not reachable!\r\n"); printk("micro ros agent not reachable!\r\n");
break; break;
} }
micro_ros_state = ROS_AGENT_CONNECTION_CONNECTED; micro_ros_state = ROS_AGENT_CONNECTION_CONNECTED;
gpio_pin_configure_dt(&uros_connection_status_led, GPIO_OUTPUT_ACTIVE);
printk("micro ros agent reachable!\r\n"); printk("micro ros agent reachable!\r\n");
rmw_uros_sync_session(100); rmw_uros_sync_session(100);
@@ -83,5 +89,10 @@ void micro_ros_state_machine() {
case ROS_AGENT_CONNECTION_ERROR: case ROS_AGENT_CONNECTION_ERROR:
default: default:
micro_ros_state = ROS_AGENT_CONNECTION_ERROR; micro_ros_state = ROS_AGENT_CONNECTION_ERROR;
gpio_pin_configure_dt(&uros_error_led, GPIO_OUTPUT_ACTIVE);
k_sleep(K_MSEC(3000));
sys_reboot(SYS_REBOOT_WARM);
} }
} }

View File

@@ -22,6 +22,8 @@
rcl_node_t StepperController::node; rcl_node_t StepperController::node;
__attribute__((section(".noinit"))) float retained_calibration = 0.0f;
// target pos // target pos
rcl_subscription_t StepperController::stepper0_sub_pos; rcl_subscription_t StepperController::stepper0_sub_pos;
float StepperController::current_angle; float StepperController::current_angle;
@@ -102,38 +104,45 @@ void StepperController::init() {
} }
void StepperController::calibrate() { void StepperController::calibrate() {
gpio_pin_configure_dt(&status_led, GPIO_OUTPUT_INACTIVE); printk("Calibrating stepper motor ...\n");
gpio_pin_configure_dt(&calibration_led, GPIO_OUTPUT_ACTIVE);
set_motor_velocity(0.02); if (fabs(retained_calibration) == 1.0) { // NaN check
k_sleep(K_MSEC(1000)); direction_factor = retained_calibration;
printk("Cached calibration -> %c\n" , direction_factor > 0 ? '+' : '-');
return;
}
set_motor_velocity(0.05);
k_sleep(K_MSEC(500));
sample_angle(); sample_angle();
float left_angle = current_angle; float left_angle = current_angle;
set_motor_velocity(-0.02); set_motor_velocity(-0.05);
k_sleep(K_MSEC(2000)); k_sleep(K_MSEC(1000));
sample_angle(); sample_angle();
float right_angle = current_angle; float right_angle = current_angle;
set_motor_velocity(0.02); set_motor_velocity(0.05);
k_sleep(K_MSEC(1000)); k_sleep(K_MSEC(500));
if (right_angle < left_angle) { if (right_angle < left_angle) {
direction_factor = -1.0; direction_factor = -1.0;
} }
stepper_stop(stepper0);
printk("Servo direction calibration:\n"); printk("Stepper direction calibration:\n");
printk("Left = %d.%02d\n", (int)left_angle, abs((int)(left_angle * 100) % 100)); printk("Left = %d.%02d\n", (int)left_angle, abs((int)(left_angle * 100) % 100));
printk("Right = %d.%02d\n", (int)right_angle, abs((int)(right_angle * 100) % 100)); printk("Right = %d.%02d\n", (int)right_angle, abs((int)(right_angle * 100) % 100));
printk("-> %c\n" , direction_factor > 0 ? '+' : '-'); printk("-> %c\n" , direction_factor > 0 ? '+' : '-');
printk("----------------------------\n"); printk("----------------------------\n");
stepper_stop(stepper0); retained_calibration = direction_factor;
k_sleep(K_MSEC(100));
gpio_pin_configure_dt(&status_led, GPIO_OUTPUT_ACTIVE); k_sleep(K_MSEC(100));
gpio_pin_configure_dt(&calibration_led, GPIO_OUTPUT_INACTIVE);
} }
rcl_ret_t StepperController::setup(rclc_support_t* support, rclc_executor_t* executor) rcl_ret_t StepperController::setup(rclc_support_t* support, rclc_executor_t* executor)
@@ -273,7 +282,7 @@ void StepperController::pid() {
} }
void StepperController::set_motor_velocity(float rps) { void StepperController::set_motor_velocity(float rps) {
gpio_pin_configure_dt(&work_led, fabs(rps) > 0.05 ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE); gpio_pin_configure_dt(&pid_offset_led, fabs(rps) >= 0.05 ? GPIO_OUTPUT_ACTIVE : GPIO_OUTPUT_INACTIVE);
uint32_t motor_steps_hz = abs((int32_t)(rps * (float)SENSOR_STEPS_PER_REVOLUTION)); uint32_t motor_steps_hz = abs((int32_t)(rps * (float)SENSOR_STEPS_PER_REVOLUTION));