C2D

Continuous-to-discrete conversion (“discretization”) is essential for implementing control algorithms on digital hardware. This function converts a continuous-time LTI system into a mathematically equivalent discrete-time system, matching the original dynamics as closely as possible at the given sample rate (T_s).

The default method is Zero-Order Hold (ZOH), which assumes the control inputs are held constant between samples. Other available transformation methods include Bilinear (Tustin’s approximation).

Excel Usage

=C2D(sysc, Ts, disc_method)
  • sysc (list[list], required): The continuous-time transfer function to convert (provided as numerator and denominator coefficients).
  • Ts (float, required): The sampling period (must be > 0) in seconds.
  • disc_method (str, optional, default: “zoh”): Method to use for conversion (‘zoh’, ‘bilinear’, ‘tustin’, ‘euler’, ‘backward_diff’, ‘foh’).

Returns (str): A string representation of the discrete-time system model.

Example 1: ZOH Discretization of 1/s

Inputs:

sysc Ts disc_method
1 0.1 zoh
1

Excel formula:

=C2D({1;1,0}, 0.1, "zoh")

Expected output:

"<TransferFunction>: sys[0]$sampled\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\ndt = 0.1\n\n 0.1\n -----\n z - 1"

Example 2: Bilinear Discretization of 1/(s+1)

Inputs:

sysc Ts disc_method
1 0.05 bilinear
1

Excel formula:

=C2D({1;1,1}, 0.05, "bilinear")

Expected output:

"<TransferFunction>: sys[2]$sampled\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\ndt = 0.05\n\n 0.02439 z + 0.02439\n -------------------\n z - 0.9512"

Example 3: Second order system with 1 sec sample

Inputs:

sysc Ts disc_method
1 2 1 zoh
1 3

Excel formula:

=C2D({1,2;1,3,2}, 1, "zoh")

Expected output:

"<TransferFunction>: sys[4]$sampled\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\ndt = 1.0\n\n 0.6321 z - 0.08555\n ------------------------\n z^2 - 0.5032 z + 0.04979"

Example 4: First order hold discretization

Inputs:

sysc Ts disc_method
2 0.01 foh
1

Excel formula:

=C2D({2;1,5}, 0.01, "foh")

Expected output:

"<TransferFunction>: sys[6]$sampled\nInputs (1): ['u[0]']\nOutputs (1): ['y[0]']\ndt = 0.01\n\n 0.009835 z + 0.009673\n ---------------------\n z - 0.9512"

Python Code

Show Code
import control as ct
import numpy as np

def c2d(sysc, Ts, disc_method='zoh'):
    """
    Convert a continuous-time system to discrete-time by sampling.

    See: https://python-control.readthedocs.io/en/latest/generated/control.c2d.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        sysc (list[list]): The continuous-time transfer function to convert (provided as numerator and denominator coefficients).
        Ts (float): The sampling period (must be > 0) in seconds.
        disc_method (str, optional): Method to use for conversion ('zoh', 'bilinear', 'tustin', 'euler', 'backward_diff', 'foh'). Valid options: Zero-Order Hold, Bilinear (Tustin), Tustin Alias, Euler, Backward Difference, First-Order Hold. Default is 'zoh'.

    Returns:
        str: A string representation of the discrete-time system model.
    """
    try:
        def flatten_to_1d(x):
            if not isinstance(x, list):
                return [float(x)] if str(x) != "" else []
            flat = []
            for row in x:
                if isinstance(row, list):
                    for val in row:
                        if str(val) != "":
                            flat.append(float(val))
                elif str(row) != "":
                    flat.append(float(row))
            return flat

        # For simplicity in Excel, we will assume sysc is provided as a Transfer Function 
        # with num and den in consecutive rows
        if len(sysc) < 2:
            return "Error: sysc must contain at least two rows (numerator and denominator)"

        num = flatten_to_1d(sysc[0])
        den = flatten_to_1d(sysc[1])

        if not num or not den:
            return "Error: Invalid numerator or denominator arrays"

        sys_continuous = ct.tf(num, den)

        sample_time = float(Ts)
        if sample_time <= 0:
            return "Error: Sampling time Ts must be greater than zero"

        valid_methods = ['zoh', 'bilinear', 'tustin', 'euler', 'backward_diff', 'foh']
        conv_method = disc_method.lower() if isinstance(disc_method, str) else 'zoh'

        if conv_method not in valid_methods:
            return f"Error: Invalid method '{conv_method}'. Valid options are {', '.join(valid_methods)}"

        sys_discrete = ct.c2d(sys_continuous, sample_time, method=conv_method)
        return str(sys_discrete)
    except Exception as e:
        return f"Error: {str(e)}"

Online Calculator

The continuous-time transfer function to convert (provided as numerator and denominator coefficients).
The sampling period (must be > 0) in seconds.
Method to use for conversion ('zoh', 'bilinear', 'tustin', 'euler', 'backward_diff', 'foh').