Skip to main content
Version: 1.0.2

Digital Out

Hardware​

AutomatePro comes with 12x digital outputs for controlling external systems, from small solenoids to LEDs or small DC motors. Two different digital outputs are available. One is set up as a high-side output (DO_H_0x), which PWMs the onboard 12V as an output. The second is a low-side sink (DO_L_0x), which sinks up to 36V. The first four low-side channels are PWM controllable, and the final two are binary on/off switches.

Connector Pinout​

Digital Output High-Side (DO_H_x) Specifications​

There are 6x high-side digital outputs, all of which are PWM-controllable switches.


ParameterValue
Output Voltage (On-state)+12V (from on-board 12V)
Drive Current500mA
PWM ControllableAll (DO_H_01 - DO_H_06)
PWM Switching Frequency500Hz
Number of Outputs6

SVG Image created as Graphical Drawings-DO_H_x.svg date 2025/02/06 13:37:17 Image generated by Eeschema-SVG+12VMDO_H_xOnboardAutomatePro+12V


Digital Output Low-Side (DO_L_x) Specifications​

There are 6x low-side digital outputs. The first four are PWM-controllable, while the final two are binary on/off switches.


ParameterValue
On-stateSinks up to 36V
Drive Current500mA
PWM ControllableDO_L_01
DO_L_02
DO_L_03
DO_L_04
DO_L_05 & DO_L_06 are On/Off switches
PWM Switching Frequency15 kHz
Number of Outputs6

SVG Image created as Graphical Drawings-DO_L_x.svg date 2025/02/06 13:37:17 Image generated by Eeschema-SVGGNDMOnboardAutomateProDO_L_x


ROS API​

Subscribers​

TopicTypeDescription
/io/digital_outautomatepro_interfaces/msg/DigitalOutPublish the desired digital output states to this topic. AutomatePro supports 12 digital output pins (6 high-side and 6 low-side). Each output pin is referred to as DIGITAL_OUT_H_XX or DIGITAL_OUT_L_XX, where H/L refers to High Side/Low Side and XX is the pin number, ranging from 01 to 06.

d_out_pin_id:
Data type: uint8
(Use ENUM constants defined in the message definition. DigitalOut.DIGITAL_OUT_H_XX: 01-06
DigitalOut.DIGITAL_OUT_L_XX: 01-06)

duty_cycle_percent:
Data type: uint8
Min: 0 in percentage %
Max: 100 in percentage %
DIGITAL_OUT_H_03 to DIGITAL_OUT_H_06 and DIGITAL_OUT_L_01 to DIGITAL_OUT_L_04 cap at 99; DIGITAL_OUT_L_05 and DIGITAL_OUT_L_06 switch fully on for any value above 0.

Response rate: 200 ms

Example​

This example steps the duty cycle of Digital Out 01 through 0%, 50%, 100%, and 50%, one step per second, by publishing to the /io/digital_out topic. The IO controller keeps the last command it receives, so the example sets Digital Out 01 to 0% when you stop it with Ctrl+C; a node that is killed or crashes leaves the output in its last state. The tutorial package is available in the AutomatePro tutorials repository, and its README explains how to build and run the examples.

Source: digital_out.py

import signal

import rclpy
from rclpy.duration import Duration
from rclpy.node import Node
from rclpy.signals import SignalHandlerOptions
from automatepro_interfaces.msg import DigitalOut


class DigitalOutPublisher(Node):

def __init__(self):
super().__init__('digital_out_publisher')
self.publisher = self.create_publisher(DigitalOut, '/io/digital_out', 10)
self.timer = self.create_timer(1.0, self.timer_callback)
self.duty_cycle_sequence = [0, 50, 100, 50]
self.sequence_index = 0

def timer_callback(self):
msg = DigitalOut()
msg.d_out_pin_id = DigitalOut.DIGITAL_OUT_H_01
msg.duty_cycle_percent = self.duty_cycle_sequence[self.sequence_index]
self.publisher.publish(msg)
self.get_logger().info('Publishing: "%s"' % msg)
self.sequence_index = (self.sequence_index + 1) % len(self.duty_cycle_sequence)

def switch_off(self):
msg = DigitalOut()
msg.d_out_pin_id = DigitalOut.DIGITAL_OUT_H_01
msg.duty_cycle_percent = 0
self.publisher.publish(msg)
if self.publisher.get_subscription_count() == 0:
self.get_logger().warn(
'DIGITAL_OUT_H_01 off command not delivered: no subscriber on %s'
% self.publisher.topic_name)
return
if self.publisher.wait_for_all_acked(Duration(seconds=4)):
self.get_logger().info('Switched DIGITAL_OUT_H_01 off')
else:
self.get_logger().warn('DIGITAL_OUT_H_01 off command not acknowledged')


def main(args=None):
# The IO controller keeps the last command, so switch the output off before exiting.
rclpy.init(args=args, signal_handler_options=SignalHandlerOptions.NO)
signal.signal(signal.SIGTERM, signal.default_int_handler)
node = DigitalOutPublisher()
try:
rclpy.spin(node)
except KeyboardInterrupt:
signal.signal(signal.SIGINT, signal.SIG_IGN)
signal.signal(signal.SIGTERM, signal.SIG_IGN)
node.switch_off()
finally:
node.destroy_node()
rclpy.try_shutdown()


if __name__ == '__main__':
main()

Run the node using the following command:

ros2 run automatepro_python_tutorials digital_out_node