Technical questions about CIA402 and homecomp.comp on A6

More
16 Feb 2026 00:45 #343035 by Marcos DC
From what I understand, the immediate goal here is to get the A6 working reliably, and for that it makes a lot of sense to tailor the logic to what this specific drive exposes in 0x6040/0x6041. In that context, taking an SCL-style example and adapting it is a very pragmatic approach.

I also agree that the resync problem itself is exactly what homecomp is trying to solve. During internal CiA-402 homing the drive moves on its own, so LinuxCNC needs a way to keep pos_cmd in sync with pos_fb or to resynchronize cleanly afterwards to avoid the jump / E87.1. So the mechanism for handling this is already there.

Where I think we just need to be a bit careful (based on the docs and on what’s described in this thread) is mainly in the integration details:

1) The actual semantics of the homing bits.
Yes, 0x6040/0x6041 are standardized for the basic FSA, but in practice the homing-related bits are OMS / manufacturer-specific. Bosch uses 10/12/13 in a very clean and well-documented way, but Lichuan, for example, documents “origin found” on bit 15 and leaves 12/13 as “mode specific”. So for the A6, it probably makes sense to first confirm which bits really indicate “in progress / done / error” and then wire exactly those into homecomp.

2) When exactly the resync should happen.
homecomp provides the mechanism, but it still depends on being told when homing is active, when it is finished, and when it failed. If those signals come from bits that don’t quite match the drive’s real behavior, the resync may simply happen at the wrong time. So the key part here is just making sure the drive-specific semantics are mapped correctly.

3) Details like how “start homing” is triggered (pulse vs level, required preconditions, etc.) also tend to be drive-specific and are probably best verified on the A6 itself.

So I think we’re actually pretty close in approach: for the A6, observing the bits during a home run and adapting the logic accordingly sounds like the right next step. My only point is that the state machine itself is the easy part — the main work is just confirming the drive’s real homing semantics and hooking those cleanly into homecomp so everything stays consistent.
The following user(s) said Thank You: andrax

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

  • rodw
  • rodw's Avatar
  • Away
  • Platinum Member
  • Platinum Member
More
16 Feb 2026 10:23 #343043 by rodw

I have an idea.
rodw: Can you make the bits from 0x6041 available as pins?
Then we can observe the bits during the home run.
If we know which bit is set when, the state machine could be set up accordingly.
 

Of course, that is supported. I wanted to do this with #if debug statements but it is not possible to insert such statements before the pins so I had to also include some comments to put them in or out.

Sorry but I am flat out on other projects right now!

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

  • andrax
  • andrax's Avatar Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
16 Feb 2026 18:43 #343062 by andrax
@rodw I'm sorry. You're doing a great job.
I understand PLC programming, control technology, and sensor technology myself. But when it comes to high-level languages like C, my brain says noooo, you're too stupid.
Nevertheless, I am still thinking about how to solve the problem and trying to contribute something. So I simply fed chatgpt with parameters and this is what came out. I don't think this code is usable, but maybe it will help someone come up with ideas.
component cia402_homecomp "CIA402 homing module with safety watchdog + estop";

pin out bit is_module = 1;
pin out bit cia_estop_out;   // GLOBAL EMERGENCY STOP OUTPUT

license "GPL";
option homemod;

#include "motion.h"
#include "homing.h"

/* ---------------- SAFETY PARAMETERS ---------------- */

param rw float start_timeout_s = 2.0;
param rw float run_timeout_s   = 20.0;

/* ---------------- LOCAL DATA ---------------- */

typedef struct
{
    bool request;
    bool start;
    bool homed;
    bool error;
    bool active;
} cia_local_t;

static cia_local_t ciaH[EMCMOT_MAX_JOINTS];

static double servo_dt;

/* ---------------- HAL PINS ---------------- */

typedef struct
{
    hal_bit_t *request;
    hal_bit_t *is_active;
    hal_bit_t *start;

    hal_bit_t *homed;
    hal_bit_t *error;

} pins_t;

static pins_t *pins;

/* ---------------- PIN CREATION ---------------- */

static int cia_makepins(int id, int njoints)
{
    int r = 0;

    pins = hal_malloc(sizeof(pins_t) * njoints);
    if (!pins) return -1;

    for(int j=0;j<njoints;j++)
    {
        r += hal_pin_bit_newf(HAL_IN , &pins[j].request, id,
                             "joint.%d.request-cia-homing", j);

        r += hal_pin_bit_newf(HAL_OUT, &pins[j].is_active, id,
                             "joint.%d.is-cia-homing", j);

        r += hal_pin_bit_newf(HAL_OUT, &pins[j].start, id,
                             "joint.%d.start-cia-homing", j);

        r += hal_pin_bit_newf(HAL_IN , &pins[j].homed, id,
                             "joint.%d.cia-homed", j);

        r += hal_pin_bit_newf(HAL_IN , &pins[j].error, id,
                             "joint.%d.cia-error", j);
    }

    return r;
}

/* ---------------- IO ---------------- */

static void read_pins(int njoints)
{
    for(int j=0;j<njoints;j++)
    {
        ciaH[j].request = *pins[j].request;
        ciaH[j].homed   = *pins[j].homed;
        ciaH[j].error   = *pins[j].error;
    }
}

static void write_pins(int njoints)
{
    for(int j=0;j<njoints;j++)
    {
        *pins[j].is_active = ciaH[j].active;
        *pins[j].start     = ciaH[j].start;
    }
}

/* ---------------- GLOBAL ESTOP ---------------- */

static void global_estop(int njoints)
{
    cia_estop_out = 1;

    for(int j=0;j<njoints;j++)
    {
        ciaH[j].start  = 0;
        ciaH[j].active = 0;

        H[j].homing = 0;
        H[j].home_state = HOME_IDLE;
    }
}

/* ---------------- SAFETY STATE MACHINE ---------------- */

static int cia_1joint_sm(int j)
{
    typedef enum { IDLE, WAIT_START, RUN } st_t;

    static st_t st[EMCMOT_MAX_JOINTS];
    static double start_t[EMCMOT_MAX_JOINTS];
    static double run_t[EMCMOT_MAX_JOINTS];

    switch(st[j])
    {
        case IDLE:

            if (H[j].home_state == HOME_START && ciaH[j].request)
            {
                ciaH[j].start  = 1;
                ciaH[j].active = 1;

                H[j].homing = 1;
                H[j].homed  = 0;

                start_t[j]=0;
                run_t[j]=0;

                st[j]=WAIT_START;
            }
            break;

        case WAIT_START:

            start_t[j]+=servo_dt;

            if (ciaH[j].error)
            {
                rtapi_print_msg(RTAPI_MSG_ERR,"CIA start error joint %d\n",j);
                return -1;
            }

            if (start_t[j] > start_timeout_s)
            {
                rtapi_print_msg(RTAPI_MSG_ERR,"CIA start timeout joint %d\n",j);
                return -1;
            }

            if (!ciaH[j].request)
                st[j]=RUN;

            break;

        case RUN:

            run_t[j]+=servo_dt;

            if (ciaH[j].error)
                return -1;

            if (ciaH[j].homed)
            {
                ciaH[j].start=0;
                ciaH[j].active=0;

                H[j].homing=0;
                H[j].homed=1;
                H[j].home_state=HOME_IDLE;

                st[j]=IDLE;
                return 0;
            }

            if (run_t[j] > run_timeout_s)
            {
                rtapi_print_msg(RTAPI_MSG_ERR,"CIA run timeout joint %d\n",j);
                return -1;
            }
            break;
    }

    return 1;
}

/* ---------------- API ---------------- */

int homing_init(int id,
                double servo_period,
                int n_joints,
                int n_extrajoints,
                emcmot_joint_t *pjoints)
{
    servo_dt = servo_period;

    int r = base_homing_init(id, servo_period, n_joints, n_extrajoints, pjoints);
    r += cia_makepins(id, n_joints);

    return r;
}

void read_homing_in_pins(int njoints)
{
    base_read_homing_in_pins(njoints);
    read_pins(njoints);
}

void write_homing_out_pins(int njoints)
{
    base_write_homing_out_pins(njoints);
    write_pins(njoints);
}

bool do_homing(void)
{
    int busy=0;
    int fault=0;

    do_homing_sequence();

    for(int j=0;j<all_joints;j++)
    {
        if(!ciaH[j].request)
            busy+=base_1joint_state_machine(j);
        else
        {
            int r=cia_1joint_sm(j);

            if(r<0) fault=1;
            else busy+=r;
        }
    }

    if(fault)
    {
        global_estop(all_joints);
        return 0;
    }

    homing_active=(busy>0);
    return 0;
}

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

More
16 Feb 2026 23:40 #343074 by Marcos DC
@Andrax, first of all: thanks for sharing your examples — it’s clear you’re on the right track, especially by thinking in terms of watchdogs and by splitting the sequence into “start → run → done”. That’s already more than many integrations do.

Just for context: I come more from the Mechatrolink / Yaskawa world, but at the motion-control architecture level the concepts are the same (state machines, ACK semantics, watchdogs, reference sync, etc.), so I’m looking at this more from that angle than from any specific CiA-402 detail.

Looking at your two snippets together, it feels like each one gets an important part right:

In the cia402_homecomp (C) version you already have a proper state machine with timeouts (start_timeout / run_timeout), which is exactly the kind of safety supervision you want in an industrial setup to avoid waiting forever for a drive.

In the pseudo-PLC example you’re already trying to tie the logic to real drive signals (bits from 0x6041, speed, etc.), which is also exactly the right direction.

Where they still feel a bit “misaligned” to me is this:

The cia402_homecomp does have watchdogs, but it’s not really driven by the drive’s real status (it relies on cia-homed / cia-error coming from outside, and doesn’t directly check “started / motion / done” conditions itself).

The pseudo-PLC tries to use real status, but the start and motion proof parts are still fragile (e.g. setting bit 4 = 1 doesn’t guarantee a rising edge, and comparing target speed <> actual speed isn’t a very robust proof that motion really started).

From an industrial point of view, the sequence usually looks roughly like this (independent of whether it’s EtherCAT, Mechatrolink, Sercos, etc.):

Generate a start event (pulse or temporary level, depending on the drive), not just keep the bit stuck at 1 forever.

First watchdog: after start, wait for either a real “homing started” indication or a real proof of motion (position change / actual velocity > threshold). If that doesn’t happen within X seconds → fault.

Second watchdog (overall): while homing is running, wait for the real “done” indication from the drive. If it exceeds the overall timeout → fault.

On completion: clear the start and synchronize the reference (pos_cmd with pos_fb) to avoid jumps / following errors when going back to CSP.

So in a way, the idea in your first code (state machine + timeouts) is right, and the idea in your second one (looking at real 0x6041 bits / real behavior) is also right — what’s missing is bringing those two together: a state machine whose transitions are driven by real drive status and real motion, not only by logical external signals.

One small additional point from an industrial perspective: in your C example a homing fault ends up triggering a global E-STOP. In many systems we try to separate those two concepts: a homing/process fault usually leads to an axis fault or a controlled stop/disable of that axis, while E-STOP is reserved for real safety events. That separation often makes diagnostics and recovery much cleaner, while still keeping the safety chain intact.

This is not meant as criticism of what you’ve done — on the contrary, it’s pretty clear you’re already thinking in exactly the right direction (watchdogs, states, safety). It’s more about aligning it with what is usually done in industrial integrations:
start as an event → real confirmation that it started → real confirmation that it finished → reference synchronization.

If we can move cia402_homecomp more in that direction (even if via masks/config per drive), I think it would solve a big part of the homing and mode-switching issues people are running into.

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

  • andrax
  • andrax's Avatar Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
17 Feb 2026 12:14 #343092 by andrax
Hi,
thanks for the feedback.
On the subject of E-Stop.
In CNC machines, E-Stop is triggered to prevent uncontrolled axis movements. 
In automated production machines with axes that move independently of each other, I agree with you. In most cases, an error message is sufficient here.

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

  • rodw
  • rodw's Avatar
  • Away
  • Platinum Member
  • Platinum Member
More
18 Feb 2026 00:05 #343118 by rodw
chatgpt has a lot to learn. This is the official home comp template
github.com/LinuxCNC/linuxcnc/blob/master...onents/homecomp.comp
these are the pins which are added to joint.N but you can add others
 hal_bit_t *request_custom_homing; // input  requests custom homing
 hal_bit_t *is_custom_homing;      // output verifies custom homing

Andrax, the best way to learn C code is to read it as you understand basic control mechnisms

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

More
18 Feb 2026 00:18 - 18 Feb 2026 00:31 #343121 by Marcos DC
@Andrax
I think we’re actually very close in spirit here, but there is one important distinction worth making.In the current code, the triggers for global_estop() are:
  • drive reports error, or
  • start watchdog timeout, or
  • run watchdog timeout.
All of these indicate a sequence / handshake failure (homing didn’t start in time, didn’t finish in time, or the drive signaled a fault). They are not, by themselves, evidence of uncontrolled or runaway motion.So from an industrial point of view, this logic is more a process watchdog / fault handling than a true safety watchdog. Using a global E-Stop here is a very conservative choice (and understandable for a “fail-safe” CNC-style approach), but conceptually it mixes two layers:
  • Fault handling: homing failed, timeout, drive error → abort sequence, raise alarm, inhibit motion.
  • Safety / E-Stop: hazardous or potentially uncontrolled motion → immediate safety stop (usually hardware/ STO).
That’s why I was suggesting that most of these cases could be handled as axis/sequence faults rather than a global E-Stop, unless there is real evidence of dangerous or uncontrolled motion (e.g. runaway, loss of feedback, velocity growing when it shouldn’t, etc.).So the current logic is consistent as a conservative “stop everything on any homing failure”, but the triggers themselves are not proof of uncontrolled motion — they are proof that the homing sequence didn’t progress as expected.
Last edit: 18 Feb 2026 00:31 by Marcos DC.

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

More
18 Feb 2026 00:51 #343123 by Hakan
You don't do estop in the component.
Have an ouput pin flag for this condition and connect that to machine estop pin if you like to,

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

More
18 Feb 2026 02:50 #343127 by Marcos DC
I think there is a small but important distinction here between a process/sequence watchdog and a true safety watchdog.

A true safety watchdog is about detecting potentially dangerous or uncontrolled physical motion and forcing the system into a safe state (typically STO / safety stop), for example:

If |actual_velocity| > Vmax_safe when the axis should not be moving → trigger STO

If |pos_cmd - pos_fb| grows beyond a safe limit → trigger STO

If encoder feedback is lost while moving → trigger STO

If an axis moves while it is not enabled → trigger STO

If the real-time servo thread watchdog trips → trigger STO

If a safety PLC reports an invalid condition → trigger STO

These kinds of checks usually live in the safety layer (drive safety functions, safety PLC, safety relays, or core safety logic), not inside a process component.

What the current code is doing is more a sequence/process watchdog: it detects that homing did not start in time, did not finish in time, or the drive reported an error. That’s important, but it’s not the same as detecting unsafe or uncontrolled motion.

So I agree with Hakan’s point: the component should probably just signal a fault condition via an output pin, and the machine/safety layer can decide whether that becomes a controlled stop, an axis fault, or in some cases a real E-Stop.

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

  • andrax
  • andrax's Avatar Topic Author
  • Offline
  • Elite Member
  • Elite Member
More
26 Feb 2026 17:33 #343550 by andrax
I have continued to work on this issue.
Since I don't know “C,” I asked chatgpt for help. Unfortunately, with limited success. On the one hand, chatgpt provides good suggestions for implementation, but on the other hand, it suffers from Alzheimer's. It constantly forgets important components when creating the code. 
So it's useless as a programming aid.
Nevertheless, after many attempts, I managed to create a code that basically corresponds to my ideas of the logical sequence. Unfortunately, it cannot be created and crashes with massive errors. 
Could someone please help me troubleshoot this?
component cia402_safety_homecomp "cia402 homing module";

description """
A homing module for cia402 devices buildable with halcompile.
This module should be used with the provided cia402.comp

\\fBHOMING_BASE\\fR must be #defined and must point to a valid homing.c file,
an example of a customized homing module is built. This module
creates input hal pins joint.n.request-cia-homing that enables an
alternate joint homing state machine for requested joints. A hal output
pin joint.N.is_cia-homing verifies selection"

If \\fBHOMING_BASE\\fR is not #defined, an actual homing scheme is
\\fBnot\\fR implemented but all necessary functions are included as
skeleton code. (All joints are effectively homed at all times and
cannot be unhomed).

See the source code file: src/emc/motion/homing.c for the baseline
implementation that includes all functions for the default \\fBhomemod\\fR
module.

This cia402 homing component can be built and installed with
halcompile and then substituted for the default homing module
(\\fBhomemod\\fR) using:
Sor by inifile setting: \\fB[EMCMOT]HOMEMOD=user_homecomp\\fR

\\fBNote:\\fR If using a deb install:
1) halcompile is provided by the package linuxcnc-uspace-dev
""";

pin out bit is_module = 1; // required by halcompile
pin out bit homing_error; // new pin to signal homing error
pin in float cia_homing_timer1; // Timer for homing start timeout
pin in float cia_homing_timer2; // Timer for movement check timeout

license "GPL";
author "me and chatgpt";
option homemod;
option extra_setup;


/* To incorporate default homing.c file from a local git src tree:
** enable #define HOMING_BASE set to the path to the current homing.c file.
*/

#define HOMING_BASE /home/ich/linuxcnc/Sicherung/cia402/homing.c
#define STR(s) #s
#define XSTR(s) STR(s)

#include "motion.h"
#include "homing.h"

static char *home_parms;
RTAPI_MP_STRING(home_parms, "Example home parms");

// EXTRA_SETUP executed before rtapi_app_main()
EXTRA_SETUP()
{
    rtapi_print_msg(RTAPI_MSG_ERR, "HomeComp Started\n");
    return 0;
}

//=====================================================================
#ifdef HOMING_BASE
#define USE_HOMING_BASE XSTR(HOMING_BASE)

// Disable duplicate symbols from homing.c
#define CUSTOM_HOMEMODULE
#include USE_HOMING_BASE

// CIA Status Word
typedef union
{
    struct
    {
        unsigned char ReadyToSwitchOn : 1;
        unsigned char SwitchOn : 1;
        unsigned char OperationEnabled : 1;
        unsigned char Fault : 1;
        unsigned char VoltageEnabled : 1;
        unsigned char QuickStop : 1;
        unsigned char SwitchOnDisabled : 1;
        unsigned char Warning : 1;
        unsigned char keep1 : 1;
        unsigned char Remote : 1;
        unsigned char TargetReached : 1;
        unsigned char bit11 : 1;
        unsigned char HomingCompletedOutput : 1;
        unsigned char keep2 : 1;
        unsigned char keep3 : 1;
        unsigned char HomingComplete : 1;
    } b;
    hal_u32_t Word;
} Status_t;

typedef struct
{
    bool request_cia_homing;
    bool is_cia_homing;
    bool start_cia_homing;
    // CIA402 pins
    Status_t Status;
    float timer1; // Timer for start timeout
    float timer2; // Timer for movement check
    int step;     // safety state machine step
} cia_home_local_data;

static cia_home_local_data ciaH[EMCMOT_MAX_JOINTS];

// Data for per-joint CIA-Homing HAL pins
typedef struct
{
    hal_bit_t *request_cia_homing;
    hal_bit_t *is_cia_homing;
    hal_bit_t *start_cia_homing;
    hal_bit_t *homing_error;
    hal_u32_t *statusword;
    hal_float_t *timer1;
    hal_float_t *timer2;
} cia_one_joint_home_data_t;

typedef struct
{
    cia_one_joint_home_data_t cia_jhd[EMCMOT_MAX_JOINTS];
} cia_all_joints_home_data_t;

static cia_all_joints_home_data_t *cia_joint_home_data = 0;

//-------------------------------------------------------------
static int cia_makepins(int id, int njoints)
{
    int jno, retval;
    cia_one_joint_home_data_t *addr;

    cia_joint_home_data = hal_malloc(sizeof(cia_all_joints_home_data_t));
    if (!cia_joint_home_data)
    {
        rtapi_print_msg(RTAPI_MSG_ERR, "HOMING: malloc failed\n");
        return -1;
    }

    retval = 0;
    for (jno = 0; jno < njoints; jno++)
    {
        addr = &(cia_joint_home_data->cia_jhd[jno]);

        retval += hal_pin_bit_newf(HAL_IN, &(addr->request_cia_homing), id,
                                   "joint.%d.request-cia-homing", jno);
        retval += hal_pin_bit_newf(HAL_OUT, &(addr->is_cia_homing), id,
                                   "joint.%d.is-cia-homing", jno);
        retval += hal_pin_bit_newf(HAL_IO, &(addr->start_cia_homing), id,
                                   "joint.%d.start-cia-homing", jno);
        retval += hal_pin_bit_newf(HAL_OUT, &(addr->homing_error), id,
                                   "joint.%d.homing-error", jno);
        retval += hal_pin_u32_newf(HAL_IN, &(addr->statusword), id,
                                   "joint.%d.cia-statusword", jno);
        retval += hal_pin_float_newf(HAL_IN, &(addr->timer1), id,
                                     "joint.%d.homing-timer1", jno);
        retval += hal_pin_float_newf(HAL_IN, &(addr->timer2), id,
                                     "joint.%d.homing-timer2", jno);
    }
    return retval;
}

//-------------------------------------------------------------
static void cia_read_homing_in_pins(int njoints)
{
    int jno;
    cia_one_joint_home_data_t *addr;
    for (jno = 0; jno < njoints; jno++)
    {
        addr = &(cia_joint_home_data->cia_jhd[jno]);
        ciaH[jno].request_cia_homing = *(addr->request_cia_homing);
        ciaH[jno].Status.Word = *(addr->statusword);
        ciaH[jno].timer1 = *(addr->timer1);
        ciaH[jno].timer2 = *(addr->timer2);
    }
}

//-------------------------------------------------------------
static void cia_write_homing_out_pins(int njoints)
{
    int jno;
    cia_one_joint_home_data_t *addr;
    for (jno = 0; jno < njoints; jno++)
    {
        addr = &(cia_joint_home_data->cia_jhd[jno]);
        *(addr->is_cia_homing) = ciaH[jno].is_cia_homing;
        *(addr->start_cia_homing) = ciaH[jno].start_cia_homing;
        *(addr->homing_error) = homing_error; // global error flag
    }
}

//-------------------------------------------------------------
static int cia_1joint_state_machine(int joint_num)
{
    typedef enum
    {
        CIA_IDLE = 0,
        CIA_BEGIN = 1,
        CIA_START_WAIT = 2,
        CIA_RUNNING = 3,
        CIA_FINISHED = 4,
    } cia_home_state_t;

    static cia_home_state_t chomestate[EMCMOT_MAX_JOINTS] = {0};
    static float t_start[EMCMOT_MAX_JOINTS] = {0};
    static float t_run[EMCMOT_MAX_JOINTS] = {0};
    cia_home_state_t nextcstate;

    if (H[joint_num].home_state == HOME_IDLE)
        return 0;

    if ((H[joint_num].home_state == HOME_START) && (chomestate[joint_num] == CIA_IDLE))
    {
        H[joint_num].homing = 1;
        H[joint_num].homed = 0;
        chomestate[joint_num] = CIA_BEGIN;
        ciaH[joint_num].step = 0;
        t_start[joint_num] = 0;
        t_run[joint_num] = 0;
        homing_error = 0;
    }

    switch (chomestate[joint_num])
    {
    case CIA_BEGIN:
        // initialize parameters
        rtapi_print("CIA homing: init parameters\n");
        t_start[joint_num] = 0;
        t_run[joint_num] = 0;
        chomestate[joint_num] = CIA_START_WAIT;
        break;

    case CIA_START_WAIT:
        t_start[joint_num] += H[joint_num].servo_period;
        // check if CIA402 bit9 (Remote) set to start homing
        if (ciaH[joint_num].Status.b.Remote)
        {
            chomestate[joint_num] = CIA_RUNNING;
        }
        else if (t_start[joint_num] > ciaH[joint_num].timer1)
        {
            rtapi_print("CIA homing: start timeout\n");
            homing_error = 1;
            H[joint_num].homing = 0;
            H[joint_num].home_state = HOME_IDLE;
            chomestate[joint_num] = CIA_IDLE;
            return 0;
        }
        break;

    case CIA_RUNNING:
        t_run[joint_num] += H[joint_num].servo_period;
        // safety check: axis movement
        if (!H[joint_num].joint_moving) // Example: joint_moving needs to be replaced by real check
        {
            rtapi_print("CIA homing: axis not moving, error\n");
            homing_error = 1;
            H[joint_num].homing = 0;
            H[joint_num].home_state = HOME_IDLE;
            chomestate[joint_num] = CIA_IDLE;
            return 0;
        }
        // check for CIA homing completion
        if (ciaH[joint_num].Status.b.HomingCompletedOutput &&
            ciaH[joint_num].Status.b.HomingComplete)
        {
            chomestate[joint_num] = CIA_FINISHED;
        }
        else if (t_run[joint_num] > ciaH[joint_num].timer2)
        {
            rtapi_print("CIA homing: movement timeout\n");
            homing_error = 1;
            H[joint_num].homing = 0;
            H[joint_num].home_state = HOME_IDLE;
            chomestate[joint_num] = CIA_IDLE;
            return 0;
        }
        break;

    case CIA_FINISHED:
        rtapi_print("CIA homing complete\n");
        ciaH[joint_num].start_cia_homing = 0;
        H[joint_num].homing = 0;
        H[joint_num].homed = 1;
        H[joint_num].home_state = HOME_IDLE;
        chomestate[joint_num] = CIA_IDLE;
        return 0;

    case CIA_IDLE:
    default:
        break;
    }
    ciaH[joint_num].is_cia_homing = (chomestate[joint_num] != CIA_IDLE);
    return 1;
}

//-------------------------------------------------------------
// Augment base functions
int homing_init(int id, double servo_period, int n_joints, int n_extrajoints, emcmot_joint_t *pjoints)
{
    int retval = base_homing_init(id, servo_period, n_joints, n_extrajoints, pjoints);
    retval += cia_makepins(id, n_joints);
    return retval;
}

void read_homing_in_pins(int njoints)
{
    base_read_homing_in_pins(njoints);
    cia_read_homing_in_pins(njoints);
}

void write_homing_out_pins(int njoints)
{
    base_write_homing_out_pins(njoints);
    cia_write_homing_out_pins(njoints);
}

// do_homing with CIA safety
bool do_homing(void)
{
    int joint_num;
    int homing_flag = 0;
    bool beginning_allhomed = get_allhomed();

    do_homing_sequence();
    for (joint_num = 0; joint_num < all_joints; joint_num++)
    {
        if (!H[joint_num].joint_in_sequence) continue;
        if (!GET_JOINT_ACTIVE_FLAG(&joints[joint_num])) continue;

        if (ciaH[joint_num].is_cia_homing)
            homing_flag += cia_1joint_state_machine(joint_num);
        else
            homing_flag += base_1joint_state_machine(joint_num);
    }

    homing_active = (homing_flag > 0) ? 1 : 0;

    if (!beginning_allhomed && get_allhomed())
    {
        homing_active = 0;
        return 1;
    }

    return 0;
}

//=====================================================================
// EXPORT_SYMBOLS
EXPORT_SYMBOL(homeMotFunctions);
EXPORT_SYMBOL(homing_init);
EXPORT_SYMBOL(do_homing);
EXPORT_SYMBOL(get_allhomed);
EXPORT_SYMBOL(get_homed);
EXPORT_SYMBOL(get_home_is_idle);
EXPORT_SYMBOL(get_home_is_synchronized);
EXPORT_SYMBOL(get_home_needs_unlock_first);
EXPORT_SYMBOL(get_home_sequence);
EXPORT_SYMBOL(get_homing);
EXPORT_SYMBOL(get_homing_at_index_search_wait);
EXPORT_SYMBOL(get_homing_is_active);
EXPORT_SYMBOL(get_index_enable);
EXPORT_SYMBOL(read_homing_in_pins);
EXPORT_SYMBOL(do_home_joint);
EXPORT_SYMBOL(do_cancel_homing);
EXPORT_SYMBOL(set_unhomed);
EXPORT_SYMBOL(set_joint_homing_params);
EXPORT_SYMBOL(update_joint_homing_params);
EXPORT_SYMBOL(write_homing_out_pins);

// Clean up optional
#undef XSTR
#undef STR
#undef HOMING_BASE
#undef USE_HOMING_BASE
#undef CUSTOM_HOMEMODULE

#endif // HOMING_BASE

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

Time to create page: 0.117 seconds
Powered by Kunena Forum