Write Functions

static HIL.esc_output(protocol, throttle, polarity=1, telemetry=False, command=48)

Generates a PWM output value suitable for an ESC command.

The esc_output function returns an appropriate value to write to a PWM output to perform the given ESC command based on the given protocol and options. The returned value may then be written to the PWM output using a function such as write_pwm.

For ESC protocols like standard PWM, OneShot and Multishot, the throttle value as a percentage (0% to 100% or -100% to 100%) is mapped to a pulse width in seconds. The PWM output mode should be configured as PWMMode.TIME in the set_pwm_mode() function when using these protocols. The desired PWM period must also be configured using the set_pwm_frequency() functions.

The telemetry and command inputs are ignored unless the protocol is EscProtocol.DSHOT.

For the DSHOT protocol, the polarity, throttle, telemetry and command are all used. The throttle value is a percentage (0% to 100% or -100% to 100% depending on the polarity) and the telemetry is a logical input indicating whether to include a telemetry request in the DSHOT output. The command argument is used for special commands. A command value of 0 means “disarm”, for instance. Command values from 0-47 are for special commands and the throttle value will be ignored in the output. A command value of 48 means “armed”. In this case, the throttle value is included in the output value. See the DshotCommand enumeration for a full list of the DSHOT commands.

For DSHOT, the PWM output should be configured in PWMMode.RAW in the set_pwm_mode() function and DSHOT should be enabled in the card-specific options e.g. pwm0_dshot=1 via the set_card_specific_options() function. The PWM frequency will determine the bit rate for the DSHOT. For example, a PWM frequency of 600e3 will result in DSHOT600 being output from the PWM output.

The table below enumerates the typical settings employed for various ESC protocols.

Protocol

Description

PWM Mode

PWM Frequency

ESC Constant

Standard PWM

1 to 2 ms pulse every 20 ms.

PWMMode.TIME

50

EscProtocol.STANDARD_PWM

OneShot125

125 to 250 us pulse every 500us.

PWMMode.TIME

2000

EscProtocol.ONESHOT125

OneShot42

42 to 84 us pulse every 168us.

PWMMode.TIME

1/168e-6

EscProtocol.ONESHOT42

Multishot

5 to 25 us pulse every 50us.

PWMMode.TIME

20000

EscProtocol.MULTISHOT

DShot150

16-bit packet at 150 kbaud.

PWMMode.RAW

150e3

EscProtocol.DSHOT

DShot300

16-bit packet at 300 kbaud.

PWMMode.RAW

300e3

EscProtocol.DSHOT

DShot600

16-bit packet at 600 kbaud.

PWMMode.RAW

600e3

EscProtocol.DSHOT

DShot1200

16-bit packet at 1200 kbaud.

PWMMode.RAW

1200e3

EscProtocol.DSHOT

DShot2400

16-bit packet at 2400 kbaud.

PWMMode.RAW

2400e3

EscProtocol.DSHOT

Parameters
  • protocol (EscProtocol) – The ESC protocol for which the PWM output value will be generated.

  • throttle (double) – A fraction between 0.0 and 1.0 representing the throttle value from 0% to 100% when the polarity is EscPolarity.UNSIGNED. Otherwise it is a double-precision value in the range -1.0 to 1.0 representing a throttle value from -100% to +100%.

  • polarity (EscPolarity) – The ESC polarity determining whether the throttle is unipolar/unsigned or bipolar/signed, and how signed throttle values map to output values (symmetrically or asymmetrically). Note that DSHOT 3D mode for AM32 firmware uses EscPolarity.ASYMMETRIC_SIGNED polarity. Only the DSHOT protocol supports asymmetric polarity.

  • telemetry (boolean) – When the ESC protocol is set to EscProtocol.DSHOT, the telemetry parameter determines whether telemetry information is returned from the selected channel (True or False).

  • command (DshotCommand) – When the ESC protocol is set to EscProtocol.DSHOT, the commmand parameter represents the DSHOT command. Use DshotCommand.ARMED when trying to control the motor throttle.

Raises

HILError – Raises an exception on an error. A suitable error message may be retrieved using get_error_message().

Examples

Send a DSHOT command to arm the motors.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL, EscProtocol, EscPolarity, DshotCommand
>>> card = HIL("qdrone2", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   buffer = array('d', [card.esc_output(EscProtocol.DSHOT, EscPolarity.UNSIGNED, 0.0, False, DShotCommand.ARMED)] * 4)
>>>   card.write_pwm(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL, EscProtocol, EscPolarity, DshotCommand
>>> card = HIL("qdrone2", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([card.esc_output(EscProtocol.DSHOT, EscPolarity.UNSIGNED, 0.0, False, DShotCommand.ARMED)] * 4, dtype=np.float64)
>>>   card.write_pwm(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write_analog(channels, num_channels, buffer)

Writes to analog outputs immediately. The function does not return until the data has been written.

Parameters
  • channels (array_like) – An array containing the channel numbers of the analog outputs to be written.

  • num_channels (int) – The number of channels specified in the channels array.

  • buffer (array_like) – An array containing the voltage values to write to the analog outputs. The array must contain num_channels elements. Each element in the buffer array corresponds to the same element in the channels array.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Examples

Write to the first four analog output channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   buffer = array('d', [0.5, 1.5, 2.5, 3.5])
>>>   card.write_analog(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([0.5, 1.5, 2.5, 3.5], dtype=np.float64)
>>>   card.write_analog(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write_analog_codes(channels, num_channels, buffer)

Writes to the specified analog output channels immediately using raw D/A converter values. The function does not return until the data has been written.

Parameters
  • channels (array_like) – An array containing the channel numbers of the analog outputs to be written.

  • num_channels (int) – The number of channels specified in the channels array.

  • buffer (array_like) – An array containing the raw D/A converter values to write to the analog outputs. The array must contain num_channels elements. Each element in the buffer array corresponds to the same element in the channels array.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Examples

Write to the first four analog output channels using raw D/A converter values.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   buffer = array('i', [0x000, 0x3ff, 0x5ff, 0x7ff])
>>>   card.write_analog_codes(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([0x000, 0x3ff, 0x5ff, 0x7ff], dtype=np.int32)
>>>   card.write_analog_codes(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write_pwm(channels, num_channels, buffer)

Writes to specified PWM output channels immediately. The function does not return until the data has been written.

Parameters
  • channels (array_like) – An array containing the channel numbers of the PWM outputs to be written.

  • num_channels (int) – The number of channels specified in the channels array.

  • buffer (array_like) – An array containing the values to write to the PWM outputs. How these values are interpreted depends on the PWM mode. The PWM mode is configured using the hil_set_pwm_mode function. The array must contain num_channels elements. Each element in the buffer array corresponds to the same element in the channels array.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Examples

Write to the first four PWM output channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   buffer = array('d', [0.0, 0.3, 0.7, 1.0])
>>>   card.write_pwm(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([0.0, 0.3, 0.7, 1.0], dtype=np.float64)
>>>   card.write_pwm(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write_digital(channels, num_channels, buffer)

Writes to digital outputs immediately. The function does not return until the data has been written.

Parameters
  • channels (array_like) – An array containing the channel numbers of the digital outputs to be written.

  • num_channels (int) – The number of channels specified in the channels array.

  • buffer (array_like) – An array containing the binary values to write to the digital outputs. The array must contain num_channels elements. Each element in the buffer array corresponds to the same element in the channels array.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Examples

Write to the first four PWM output channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1, 2, 3])
>>>   num_channels = len(channels)
>>>   buffer = array('b', [0, 1, 1, 0])
>>>   card.write_digital(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([0, 1, 1, 0], dtype=np.int8)
>>>   card.write_digital(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write_other(channels, num_channels, buffer)

Writes to the specified other output channels immediately. The function does not return until the data has been written.

Parameters
  • channels (array_like) – An array containing the channel numbers of the other outputs to be written.

  • num_channels (int) – The number of channels specified in the channels array.

  • buffer (array_like) – An array containing the values to write to the other outputs. The array must contain num_channels elements. Each element in the buffer array corresponds to the same element in the channels array.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Examples

Write to the first two other output channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = array('I', [0, 1])
>>>   num_channels = len(channels)
>>>   buffer = array('d', [1.0, 0.0])
>>>   card.write_other(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   channels = np.array([0, 1], dtype=np.uint32)
>>>   num_channels = len(channels)
>>>   buffer = np.array([1.0, 0.0], dtype=np.float64)
>>>   card.write_other(channels, num_channels, buffer)
>>>   # ...
...
>>> finally:
>>>   card.close()
HIL.write(analog_channels, num_analog_channels, pwm_channels, num_pwm_channels, digital_channels, num_digital_channels, other_channels, num_other_channels, analog_buffer, pwm_buffer, digital_buffer, other_buffer)

Writes to the specified output channels immediately. The function does not return until the data has been written.

The interpretation of the PWM samples to be written depends upon the PWM mode. Typically, the data is interpreted as a duty cycle, in which a magnitude of 0.0 denotes a 0% duty cycle and magnitude of 1.0 indicates a 100% duty cycle. The sign determines the polarity of the output for those boards supporting bidirectional PWM outputs. However, other PWM modes are possible with some boards. Refer to the set_pwm_mode function for details.

Parameters
  • analog_channels (array_like or None) – An array containing the channel numbers of the analog outputs to be written. If no analog channels are required, then this parameter may be None. In this case, num_analog_channels must be zero.

  • num_analog_channels (int) – The number of channels specified in the analog_channels array. This parameter may be zero.

  • pwm_channels (array_like or None) – An array containing the channel numbers of the PWM outputs to be written. If no PWM channels are required, then this parameter may be None. In this case, num_pwm_channels must be zero.

  • num_pwm_channels (int) – The number of channels specified in the pwm_channels array. This parameter may be zero.

  • digital_channels (array_like or None) – An array containing the channel numbers of the digital outputs to be written. If no digital channels are required, then this parameter may be None. In this case, num_digital_channels must be zero.

  • num_digital_channels (int) – The number of channels specified in the digital_channels array. This parameter may be zero.

  • other_channels (array_like or None) – An array containing the channel numbers of the other outputs to be written. If no other channels are required, then this parameter may be None. In this case, num_other_channels must be zero.

  • num_other_channels (int) – The number of channels specified in the other_channels array. This parameter may be zero.

  • analog_buffer (array_like or None) – An array containing the voltage values to write to the analog outputs. The array must contain num_analog_channels elements. Each element in the analog_buffer array corresponds to the same element in the analog_channels array. If no analog channels were specified, then this parameter may be None.

  • pwm_buffer (array_like or None) – An array containing the values to write to the PWM outputs. How these values are interpreted depends on the PWM mode. The PWM mode is configured using the set_pwm_mode function. The array must contain num_pwm_channels elements. Each element in the pwm_buffer array corresponds to the same element in the pwm_channels array. If no PWM channels were specified, then this parameter may be None.

  • digital_buffer (array_like or None) – An array containing the binary values to write to the digital outputs. The array must contain num_digital_channels elements. Each element in the digital_buffer array corresponds to the same element in the digital_channels array. If no digital channels were specified, then this parameter may be None.

  • other_buffer (array_like or None) – An array containing the values to write to the other outputs. The array must contain num_other_channels elements. Each element in the other_buffer array corresponds to the same element in the other_channels array. If no other channels were specified, then this parameter may be None.

Raises

HILError – On non-zero return code. A suitable error message may be retrieved using get_error_message().

Warning

Many cards allow the digital I/O lines to be programmed as inputs or outputs. The digital I/O lines are configured as inputs or outputs using the set_digital_directions function. All the channels which will be used as digital outputs must be configured as outputs using this function. Failure to configure the digital I/O may result in the write function failing to write those outputs.

Examples

Write to two analog output channels, two PWM output channels, and four digital output channels.

Using array:

>>> from array import array
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   analog_channels = array('I', [0, 1])
>>>   pwm_channels = array('I', [0, 1])
>>>   digital_channels = array('I', [0, 1, 2, 3])
>>>   num_analog_channels = len(analog_channels)
>>>   num_pwm_channels = len(pwm_channels)
>>>   num_digital_channels = len(digital_channels)
>>>   analog_buffer = array('d', [0.5, -0.5])
>>>   pwm_buffer = array('d', [-1000.0, 1000.0])
>>>   digital_buffer = array('b', [0, 1, 0, 1])
>>>   card.write(analog_channels, num_analog_channels,
...              pwm_channels, num_pwm_channels,
...              digital_channels, num_digital_channels,
...              None, 0,
...              analog_buffer,
...              pwm_buffer,
...              digital_buffer,
...              None)
>>>   # ...
...
>>> finally:
>>>   card.close()

Using numpy:

>>> import numpy as np
>>> from quanser.hardware import HIL
>>> card = HIL("q8_usb", "0")
>>> try:
>>>   analog_channels = np.array([0, 1], dtype=np.uint32)
>>>   pwm_channels = np.array([0, 1], dtype=np.uint32)
>>>   digital_channels = np.array([0, 1, 2, 3], dtype=np.uint32)
>>>   num_analog_channels = len(analog_channels)
>>>   num_pwm_channels = len(pwm_channels)
>>>   num_digital_channels = len(digital_channels)
>>>   analog_buffer = np.array([0.5, -0.5], dtype=np.float64)
>>>   pwm_buffer = np.array([-1000.0, 1000.0], dtype=np.float64)
>>>   digital_buffer = np.array([0, 1, 0, 1], dtype=np.int8)
>>>   card.write(analog_channels, num_analog_channels,
...              pwm_channels, num_pwm_channels,
...              digital_channels, num_digital_channels,
...              None, 0,
...              analog_buffer,
...              pwm_buffer,
...              digital_buffer,
...              None)
>>>   # ...
...
>>> finally:
>>>   card.close()