Bimanual Operation (Paused/Resume) in Homing Process

  • rbobey1989
  • rbobey1989's Avatar Topic Author
  • Offline
  • Premium Member
  • Premium Member
More
07 Dec 2025 22:02 #339835 by rbobey1989
Hello everyone, it's always good to be back after some time:
In my latest projects, a client wanted to certify the safety of the machine I had updated for them. Compliance with safety regulations is always important, and this means complying with Royal Decree 1215/1997 here in Spain.

For my projects, I developed a controller based on LIMIT3 with extra joints, but I modified it to add intermediate braking before reaching the target position, depending on a pair of pushbuttons for occupied hands or bimanual operation. I have this implemented and it works correctly.

Now, the homing process is always performed by homing.c, which doesn't have a default pause/resume function. Evidently, according to Royal Decree 1215/1997 and the certification engineer, the machine cannot move on its own. I actually work with double-head miter saws from different brands: FOM Industries, Mecal, Ozgenc Makina, Fenstek, and of all of them, the only one that has bimanual operation implemented in the homing process is the FOM Industries machine. All the others move automatically and only use bimanual operation to perform the cut. Frankly, it never bothered me that the machine only moved during the homing process, but thanks to my dear friend, the certifying engineer, I've taken on the task of making some changes to homing.c to implement this behavior. What's needed is that if the machine moves long distances, closing the gap between the printheads, the moving printhead stops when the bimanual is released. While not a concern, I've also implemented pause/resume functionality for the final movement to the home position. I haven't implemented this behavior in the home states from 9 to 20 because the movements are very small, and I don't want to have measurement issues with the home switch. Without further ado, here's my version of homing.c for you to review. I've seen that the author is jmkasunich. Any feedback would be great. Thanks and regards.
Attachments:
The following user(s) said Thank You: Aciera

Please Log in or Create an account to join the conversation.

  • rbobey1989
  • rbobey1989's Avatar Topic Author
  • Offline
  • Premium Member
  • Premium Member
More
07 Dec 2025 22:21 #339837 by rbobey1989
A little more information on this: I've added a couple of signals:
-- homing_feed_inhibit: when it's 0, it pauses the homing process, and when it's 1, it resumes it.

- homing_paused: an intermediate and information variable.

A couple of functions have been added for the movements:

static void home_resume_long_move(int jno, double vel)
{
emcmot_joint_t *joint = &joints[jno];

/* If already active, do nothing */

if (joint->free_tp.active) return;

home_start_move(joint, vel);

}

/* helper to resume the final movement to H[jno].home */
static void home_resume_final_move(int jno)
{
emcmot_joint_t *joint = &joints[jno];

/* If already active, do nothing */
if (joint->free_tp.active) return;
/* plan to final move to home position */
joint->free_tp.pos_cmd = H[jno].home;
if (H[jno].home_final_vel > 0) {
joint->free_tp.max_vel = fabs(H[jno].home_final_vel);
if (joint->free_tp.max_vel > joint->vel_limit)
joint->free_tp.max_vel = joint->vel_limit;
} else {
joint->free_tp.max_vel = joint->vel_limit;
}
joint->free_tp.enable = 1;
}

And the most problematic thing, in state 9, in case we set homing_feed_inhibit to 0 and we are very close to the home switch when resuming (homing_feed_inhibit = 1) we would get

rtapi_print_msg(RTAPI_MSG_ERR, _("Home switch inactive before start of backoff move j=%d"), joint_num);

which causes the homing process to be aborted, that's why I make the decision to go to HOME_RISE_SEARCH_START or HOME_FALL_SEARCH_START depending on the search/latch signs

case HOME_FINAL_BACKOFF_START:
/* This state is called once the approximate location of the
switch has been found. It is responsible for starting a
move that will back off of the switch in preparation for a
final slow move that captures the exact switch location. */

/* is the joint already moving? */
if (joint->free_tp.active) {
/* yes, reset delay, wait until joint stops */
H[joint_num].pause_timer = 0;
break;
}
/* have you delayed timed out? */
if (H[joint_num].pause_timer < (HOME_DELAY * servo_freq)) {
/* no, update timer and wait some more */
H[joint_num].pause_timer++;
break;
}
H[joint_num].pause_timer = 0;
/* we should still be on the switch */
if (!home_sw_active) {
// rtapi_print_msg(RTAPI_MSG_ERR,
// _("Home switch inactive before start of backoff move j=%d"),
// joint_num);
// H[joint_num].home_state = HOME_ABORT;

/* Resilient fallback: If the switch bounced just before the backoff,

do not abort; continue fine-tuning the search based on the search/latch signals. */

double tmp2 = H[joint_num].home_search_vel * H[joint_num].home_latch_vel;

if (tmp2 > 0.0) {

/* Expected path: backoff + rising edge search */

H[joint_num].home_state = HOME_RISE_SEARCH_START;

} else {

/* Alternate path: falling edge search */

H[joint_num].home_state = HOME_FALL_SEARCH_START;

}
immediate_state = 1;
break;

}

/* set up a move at '-search_vel' to back off of switch */
home_start_move(joint, - H[joint_num].home_search_vel);

/* next state */
H[joint_num].home_state = HOME_FINAL_BACKOFF_WAIT;
break;

This is a first approach; the idea is to improve it. As I said before, criticism is welcome.

Please Log in or Create an account to join the conversation.

Time to create page: 0.054 seconds
Powered by Kunena Forum