IO Controller
Hardware
The AutomatePro is equipped with comprehensive onboard current and voltage monitoring systems. This reduces the need for external sensors and enables effective downstream monitoring, facilitating early detection of potential issues. The monitored power supply diagram is shown below.
ROS API
Publishers
| Topic | Type | Description |
|---|---|---|
/diagnostic/io_controller_hw | automatepro_interfaces/msg/IOControllerDiagnostic | Hardware and board diagnostics, including rail voltages and currents, power-good states, digital-drive faults, and board temperature. |
/diagnostic/io_controller_fw | automatepro_interfaces/msg/IOFirmwareDiagnostic | Firmware diagnostics, including controller uptime and fault codes. |
IOControllerDiagnostic publishes these fields:
| Field | Type | Description |
|---|---|---|
header | std_msgs/Header | Message timestamp and frame metadata. |
vbatt_voltage_monitor | float32 | Battery voltage in V. |
v12_io_smps_current_monitor | float32 | 12V IO SMPS current in A. |
v12_io_smps_voltage_monitor | float32 | 12V IO SMPS voltage in V. |
main_sbc_smps_current_monitor | float32 | Main SBC SMPS current in A. |
main_sbc_smps_voltage_monitor | float32 | Main SBC SMPS voltage in V. |
v5_io_smps_voltage_monitor | float32 | 5V IO SMPS voltage in V. |
v5_io_smps_current_monitor | float32 | 5V IO SMPS current in A. |
amp_total_power_monitor | float32 | Total power monitor in W. |
v12_io_power_good | bool | 12V IO rail power-good state. |
v5_io_power_good | bool | 5V IO rail power-good state. |
v3_3_io_power_good | bool | 3.3V IO rail power-good state. |
main_sbc_power_good | bool | Main SBC rail power-good state. |
v5_sbc_power_good | bool | 5V SBC rail power-good state. |
v3_3_sbc_power_good | bool | 3.3V SBC rail power-good state. |
v1_8_sbc_power_good | bool | 1.8V SBC rail power-good state. |
digital_drive_fault_1 | bool | Digital-drive fault 1 state. |
digital_drive_fault_2 | bool | Digital-drive fault 2 state. |
digital_drive_fault_3 | bool | Digital-drive fault 3 state. |
digital_drive_fault_4 | bool | Digital-drive fault 4 state. |
board_temp | int8 | Board temperature in degrees Celsius. |
IOFirmwareDiagnostic publishes these fields:
| Field | Type | Description |
|---|---|---|
header | std_msgs/Header | Message timestamp and frame metadata. |
uptime | uint32 | IO controller firmware uptime in seconds. |
fault_code | uint8[10] | Firmware fault-code array. |
Fault Code Index
| Constant | Value | Description |
|---|---|---|
NO_ERROR | 0x00 | No fault bits are set. |
ERROR_INDEX_CAN | 0x01 | CAN fault bitfield index; read CAN faults from fault_code[1]. |
MASK_CAN_RX_BUF_OVERFLOW | 0x01 | Set in fault_code[1] when the CAN RX FIFO reports an overflow or RX overflow condition. |
MASK_CAN_TX_BUF_OVERFLOW | 0x02 | Set in fault_code[1] when the CAN TX send buffer overflows. |
No other fault_code indexes are defined for AutomatePro firmware diagnostics. Firmware diagnostics are published every second on /diagnostic/io_controller_fw; after each publish, the firmware clears all firmware error bits so persistent faults must be reasserted by the failing subsystem.
Example
This example prints diagnostic information about the IO Controller by subscribing to the /diagnostic/io_controller_hw topic.
The ROS package is available here.
- Python
- C++
import rclpy
from rclpy.node import Node
from automatepro_interfaces.msg import IOControllerDiagnostic
class IOControllerDiagnosticSubscriber(Node):
def __init__(self):
super().__init__('io_controller_diagnostic_subscriber')
self.subscription = self.create_subscription(
IOControllerDiagnostic,
'/diagnostic/io_controller_hw',
self.listener_callback,
10)
def listener_callback(self, msg):
self.get_logger().info(f'Battery Voltage: {msg.vbatt_voltage_monitor} V')
self.get_logger().info(f'12V IO SMPS Current: {msg.v12_io_smps_current_monitor} A')
self.get_logger().info(f'12V IO SMPS Voltage: {msg.v12_io_smps_voltage_monitor} V')
self.get_logger().info(f'Main SBC SMPS Current: {msg.main_sbc_smps_current_monitor} A')
self.get_logger().info(f'Main SBC SMPS Voltage: {msg.main_sbc_smps_voltage_monitor} V')
self.get_logger().info(f'5V IO SMPS Voltage: {msg.v5_io_smps_voltage_monitor} V')
self.get_logger().info(f'5V IO SMPS Current: {msg.v5_io_smps_current_monitor} A')
self.get_logger().info(f'Total Power: {msg.amp_total_power_monitor} W')
self.get_logger().info(f'12V IO Power Good: {msg.v12_io_power_good}')
self.get_logger().info(f'5V IO Power Good: {msg.v5_io_power_good}')
self.get_logger().info(f'3.3V IO Power Good: {msg.v3_3_io_power_good}')
self.get_logger().info(f'Main SBC Power Good: {msg.main_sbc_power_good}')
self.get_logger().info(f'5V SBC Power Good: {msg.v5_sbc_power_good}')
self.get_logger().info(f'3.3V SBC Power Good: {msg.v3_3_sbc_power_good}')
self.get_logger().info(f'1.8V SBC Power Good: {msg.v1_8_sbc_power_good}')
self.get_logger().info(f'Digital Drive Fault 1: {msg.digital_drive_fault_1}')
self.get_logger().info(f'Digital Drive Fault 2: {msg.digital_drive_fault_2}')
self.get_logger().info(f'Digital Drive Fault 3: {msg.digital_drive_fault_3}')
self.get_logger().info(f'Digital Drive Fault 4: {msg.digital_drive_fault_4}')
self.get_logger().info(f'Board Temperature: {msg.board_temp} °C')
def main(args=None):
rclpy.init(args=args)
node = IOControllerDiagnosticSubscriber()
rclpy.spin(node)
node.destroy_node()
rclpy.shutdown()
if __name__ == '__main__':
main()
Run the node using the following command:
ros2 run automatepro_python_tutorials io_controller_diagnostic_node
#include <rclcpp/rclcpp.hpp>
#include <automatepro_interfaces/msg/io_controller_diagnostic.hpp>
class IOControllerDiagnosticSubscriber : public rclcpp::Node
{
public:
IOControllerDiagnosticSubscriber()
: Node("io_controller_diagnostic_subscriber")
{
subscription_ = this->create_subscription<automatepro_interfaces::msg::IOControllerDiagnostic>(
"/diagnostic/io_controller_hw", 10,
std::bind(&IOControllerDiagnosticSubscriber::listener_callback, this, std::placeholders::_1));
}
private:
void listener_callback(const automatepro_interfaces::msg::IOControllerDiagnostic::SharedPtr msg) const
{
RCLCPP_INFO(this->get_logger(), "Battery Voltage: %.3f V", msg->vbatt_voltage_monitor);
RCLCPP_INFO(this->get_logger(), "12V IO SMPS Current: %.3f A", msg->v12_io_smps_current_monitor);
RCLCPP_INFO(this->get_logger(), "12V IO SMPS Voltage: %.3f V", msg->v12_io_smps_voltage_monitor);
RCLCPP_INFO(this->get_logger(), "Main SBC SMPS Current: %.3f A", msg->main_sbc_smps_current_monitor);
RCLCPP_INFO(this->get_logger(), "Main SBC SMPS Voltage: %.3f V", msg->main_sbc_smps_voltage_monitor);
RCLCPP_INFO(this->get_logger(), "5V IO SMPS Voltage: %.3f V", msg->v5_io_smps_voltage_monitor);
RCLCPP_INFO(this->get_logger(), "5V IO SMPS Current: %.3f A", msg->v5_io_smps_current_monitor);
RCLCPP_INFO(this->get_logger(), "Total Power: %.3f W", msg->amp_total_power_monitor);
RCLCPP_INFO(this->get_logger(), "12V IO Power Good: %d", msg->v12_io_power_good);
RCLCPP_INFO(this->get_logger(), "5V IO Power Good: %d", msg->v5_io_power_good);
RCLCPP_INFO(this->get_logger(), "3.3V IO Power Good: %d", msg->v3_3_io_power_good);
RCLCPP_INFO(this->get_logger(), "Main SBC Power Good: %d", msg->main_sbc_power_good);
RCLCPP_INFO(this->get_logger(), "5V SBC Power Good: %d", msg->v5_sbc_power_good);
RCLCPP_INFO(this->get_logger(), "3.3V SBC Power Good: %d", msg->v3_3_sbc_power_good);
RCLCPP_INFO(this->get_logger(), "1.8V SBC Power Good: %d", msg->v1_8_sbc_power_good);
RCLCPP_INFO(this->get_logger(), "Digital Drive Fault 1: %d", msg->digital_drive_fault_1);
RCLCPP_INFO(this->get_logger(), "Digital Drive Fault 2: %d", msg->digital_drive_fault_2);
RCLCPP_INFO(this->get_logger(), "Digital Drive Fault 3: %d", msg->digital_drive_fault_3);
RCLCPP_INFO(this->get_logger(), "Digital Drive Fault 4: %d", msg->digital_drive_fault_4);
RCLCPP_INFO(this->get_logger(), "Board Temperature: %.2f °C", msg->board_temp);
}
rclcpp::Subscription<automatepro_interfaces::msg::IOControllerDiagnostic>::SharedPtr subscription_;
};
int main(int argc, char *argv[])
{
rclcpp::init(argc, argv);
auto node = std::make_shared<IOControllerDiagnosticSubscriber>();
rclcpp::spin(node);
rclcpp::shutdown();
return 0;
}
Run the node using the following command:
ros2 run automatepro_cpp_tutorials io_controller_diagnostic_node