Skip to content

Startup and Shutdown

JCS dev_host proceeds through a series of phases during operation:

  • Initialisation: dev_host is initialised. Threads are expected to be started.
  • Start network: The network is started and devices and processes have their configurations written.
  • Ready devices: Devices are prepared for operation (optional).
  • Start: Devices and processes are started and the system enters cyclic mode.
  • Running: Devices and processes are running in cyclic mode and data is exchanged with the network.
  • Stop: Devices and processes are stopped and the system exits cyclic mode.
  • Shutdown: System shuts down and all devices are prepared for power off.


Create dev_host instance

Upon creation JCS dev_host must open the configuration file and perform initialisation. This process may fail.

dev_host includes a static member function to build an instance, that handles initialisation. make_jcs_host will return NULL if initialisation fails:

jcs_host* host = jcs_host::make_jcs_host(path_to_config_file, false, false);
if (host == nullptr) {
    // Handle error

In the initialisation process, dev_host will:

  • Read and validate the YAML configuration files.
  • Build and validate the network tree.
  • Initialise any internal systems.
  • Start to warmup the Ethercat network.

Exit and shutdown if any errors occur.

Start the realtime and non realtime threads

The JCS dev_host library requires two threads for operation:

  • Real time thread: Ticks dev_host at the rate configured in Host rates configuration and exchanges synchronous data.
  • Non real time thread: Manages the state of dev_host and exchanges parameter data.

Real time thread

Once the real time thread is started, begin ticking dev_host:

// Build an initial guess of the cycle time
int64_t cycle_time_ns = (int64_t)1e9 / (int64_t)host->base_frequency_get();
task_rt::ready_cycle_rt(&thread_host, cycle_time_ns);

while (do_running) {
    task_rt::wait_next_cycle_rt(&thread_host, cycle_time_ns);

    // If dev_host is running and exchanging data
    // write out commands to the network
    if (host->data_is_valid_rt()) {
        host->sig_input_se_rt(0, 0, input_command);

    // Always tick dev_host
    if (host->step_rt(&cycle_time_ns) != jcs::RET_OK) {
        // Handle error and break from loop
        do_running = false;

    // If dev_host is running and exchanging data
    // fetch any data from the network
    if (host->data_is_valid_rt()) {
        host->sig_output_get_rt(0, 0, &output_data);

data_is_valid_rt() is only true once dev_host and all devices and processes are started.

Warming up the Ethercat network and cycle time

dev_host relies on Ethercat for a fast, deterministic and easy to connect networking system between the host computer and the joint controller devices. dev_host uses Ethercats Distributed Clock feature to ensure timely sync propagation to the underlying network devices.

A consequence of this is that the real time thread must be synchronised to Ethercats sync mechanism.

dev_host features an internal regulator that regulates the wakeup time of the real time thread such that it is woken up to perform the cyclic exchange at a time that is offset from the Ethercat sync pulse.

During startup it is required to allow some time for the thread offset time regulator to settle, before enabling communications on the Ethercat network. This warmup period typically takes a couple of seconds. Once the regulator has settled and the Ethercat network is ready and dev_host has completed any internal initialisation, cyclic_ready() will be asserted as true.

Thread to sync performance

Those looking to extract more performance may look at the Ethercat sync to real time thread time offset regulator. The default thread to sync offset time can be altered in dev_host.yaml via:

    sync_offset_time_us: 200
Note that the default value of 250uS works very well for moderately complex systems at base rates of up to 1kHz - 1.5kHz.

Examine results of jcs_host function dev_jc_ethercat_timing_print()" after a run of the system. The average value in "Sync to TX end" represents the time taken from the joint controller receiving a sync pulse, doing all its sync work, then transmitting data to the Ethercat Phy. All work must be done before the Ethercat data train comes around as set by sync_offset_time_us (default value 200us).

Adjust sync_offset_time_us such that it is greater than "Sync to TX end" and test the system stability.

Non real time thread

The non real time thread must wait until dev_host becomes ready before any parameters or commands can be issued. Wait for dev_host to become ready with:

while (!host->cyclic_ready()) {

Once cyclic_ready() is true, dev_host is ready to accept commands and parameters.

Network Start

Once dev_host is initialised and ready to accept commands and parameters, the network can be started. In starting the network, dev_host will attempt to validate that all devices are available and begin configuration of the devices and processes.

Start the network with:

if (host->start_network() != jcs::RET_OK) {
    // Handle error

Troubleshooting start_network

  • For devices connected back to a joint controller, the order that the device is connected and the order in which the device is listed under that joint controller's network entry in structure.yaml must be the same. start_network will fail if the orders do not match.

  • start_network will validate the configured device IDs with each physical device. If they do not match, start_network will fail. If, for example, a device fails and you replace it with an equivalent device, you must update the configuration file with the new device's ID.

Why so strict?

Why is JCS strict about configuration and device order? Robots have the potential to be very dangerous. We want to ensure that the device you are plugging in is exactly the device you are expecting and configuring.


Now that the network is running and all devices and processes are configured, the JCS network is ready to start to do useful work.

Issuing the start() command will cause the following to happen:

  • The list_start host command list will be executed.
  • Unless nodes autostart is disabled, the start command will be propagated to all devices. All devices will start and enter run mode.
  • data_is_valid_rt() will now return true and synchronous data will be exchanged. The system enters cyclic mode.


If a device is in an error state when start() is issued, the system will e-stop once synchronous data begins to be exchanged.


The system is running, exchanging data and performing control tasks. See Cyclic data exchange


Issuing the stop() command will cause the following to happen:

  • The list_stop host command list will be executed, while the system is still exchanging synchronous data.
  • Unless nodes autostop is disabled, the stop command will be propagated to all devices. All devices will stop and exit run mode.
  • data_is_valid_rt() will return false and synchronous data can not be exchanged. The system exits cyclic mode.


The JCS network can be started and stopped as many times as required.


Issuing the shutdown() command will cause dev_host to shutdown the network, ready for power off. The following will happen:

  • The list_shutdown host command list will be executed.
  • dev_host internal systems and Ethercat network will be shut down.

The user is responsible for managing exiting of the threads.