Skip to content

DroneBlocks/dexi_cpp

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

33 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

DEXI C++ ROS2 Nodes

A collection of C++ ROS2 nodes for the DEXI drone project, providing GPIO control, servo management, and I2C device interfaces.

Nodes Overview

  • Servo Controller: Controls servos via PCA9685 PWM controller
  • TCA9555 Controller: Manages TCA9555 16-bit I2C I/O expander for GPIO control
  • RGB Status LED Controller: Controls RGB status indicators

Architecture

DEXI's expansion hardware is built around two I²C peripherals on the companion computer's I²C-1 bus. They serve different roles and are addressed independently, so they coexist on the same two wires (SDA/SCL).

                   Raspberry Pi (companion computer)
                              │
                       I²C-1 bus (/dev/i2c-1)
                              │
            ┌─────────────────┴─────────────────┐
            │                                   │
        ┌───▼────────┐                    ┌─────▼──────┐
        │  PCA9685   │                    │  TCA9555   │
        │  0x40      │                    │  0x20      │
        │  16-ch PWM │                    │  16-bit IO │
        └───┬────────┘                    └─────┬──────┘
            │ PWM 0..15                         │ GPIO 0–4, 14–15
            ▼                                   ▼
       servos / LEDs                    digital inputs/outputs

Raspberry Pi I²C-1 pinout

/dev/i2c-1 is the standard user I²C bus (the one enabled by raspi-config → Interface Options → I2C and scanned by i2cdetect -y 1). It is wired to the 40-pin header as follows:

Signal BCM GPIO Physical pin
SDA GPIO 2 Pin 3
SCL GPIO 3 Pin 5
GND Pin 6 (or any GND)
3.3 V Pin 1

Both the PCA9685 (0x40) and TCA9555 (0x20) share these two wires; they are distinguished only by their I²C addresses.

PCA9685 — analog-style PWM outputs

  • Chip: NXP PCA9685, 16-channel 12-bit PWM driver.
  • Bus / address: /dev/i2c-1, 0x40.
  • Frequency: configured to 50 Hz (20 ms period) for hobby servos.
  • Channels: 16 independent PWM outputs (0–15).
  • Node: servo_controllersrc/servo_controller.cpp, header include/dexi_cpp/servo_controller.hpp.
  • Interface: service /dexi/servo_control (dexi_interfaces/srv/ServoControl). Request takes a channel pin (0–15), an angle (0–180°), and optional min_pw / max_pw pulse widths in microseconds. The node converts angle → pulse width → duty cycle and writes it to the channel.
  • Typical use: driving servos. The same channels can also dim LEDs or any device that wants a duty-cycled signal.

TCA9555 — digital GPIO expander

  • Chip: TI TCA9555, 16-bit I²C I/O expander.
  • Bus / address: /dev/i2c-1, 0x20 (A0/A1/A2 tied to GND).
  • Pins exposed by the node: 0–4 and 14–15 (seven total). Each pin is individually configured as input or output via launch parameters.
  • Node: tca9555_controllersrc/tca9555_controller.cpp, header include/dexi_cpp/tca9555_controller.hpp.
  • Interface:
    • Service /dexi/gpio_writer_service/write_gpio (dexi_interfaces/srv/GPIOSend) — set an output pin HIGH/LOW.
    • Topics ~/gpio_<pin>_state (std_msgs/Bool) — input pins are polled (default 10 Hz) and their state published.
  • Typical use: relays, status logic levels, switches, buttons — anything that's digital on/off rather than PWM.

Choosing between them

Need to drive… Use
Servo (RC-style 1–2 ms pulse, 50 Hz) PCA9685
LED brightness / motor speed (PWM) PCA9685
Relay, MOSFET gate, digital signal TCA9555 output
Read a button, switch, or logic input TCA9555 input

Both nodes can run simultaneously — they live on the same I²C bus but at different addresses, so there's no contention beyond standard I²C arbitration.

Prerequisites

System Dependencies

# I2C support (required for TCA9555 and PCA9685)
sudo apt-get update
sudo apt-get install i2c-tools
sudo usermod -a -G i2c $USER

I2C Setup

  1. Enable I2C in raspi-config:
sudo raspi-config
# Interface Options -> I2C -> Enable
  1. Create udev rules for I2C access:
sudo bash -c 'echo "SUBSYSTEM==\"i2c-dev\", GROUP=\"i2c\", MODE=\"0660\"" > /etc/udev/rules.d/90-i2c.rules'
sudo udevadm control --reload-rules
sudo udevadm trigger
  1. Verify I2C devices:
i2cdetect -y 1

Building

# Build the package
colcon build --packages-select dexi_cpp --symlink-install

# Source the workspace
source install/setup.bash

Usage

Servo Controller

Controls servos via PCA9685 PWM controller with robust I2C communication and comprehensive error handling.

Hardware Setup:

  • Connect PCA9685 to I2C (SDA: GPIO 2, SCL: GPIO 3)
  • Connect servos to PWM channels 0-15 (all 16 channels supported)
  • Power servos from 5V supply
  • PCA9685 uses I2C address 0x40 by default

Features:

  • Supports all 16 PCA9685 channels (0-15)
  • Custom pulse width control per servo
  • Input validation and error handling
  • 50Hz PWM frequency optimized for servos
ros2 launch dexi_cpp servo_controller.launch.py

Services:

  • /dexi/servo_control (dexi_interfaces/srv/ServoControl) - Control servo position

Service Interface:

# Request fields:
int32 pin      # Servo channel (0-15)
int32 angle    # Target angle in degrees (0-180)
int32 min_pw   # Optional: minimum pulse width in microseconds (default: 500)
int32 max_pw   # Optional: maximum pulse width in microseconds (default: 2500)
---
# Response fields:
bool success   # Operation success status
string message # Status or error message

Usage Examples:

# Move servo on channel 0 to 90 degrees (using defaults: 500-2500μs pulse width)
ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: 0, angle: 90}"

# Move servo on channel 1 to 0 degrees
ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: 1, angle: 0}"

# Move servo on channel 2 to 180 degrees
ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: 2, angle: 180}"

# Use custom pulse width range for specific servo (e.g., 600-2400μs)
ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: 0, angle: 90, min_pw: 600, max_pw: 2400}"

# Control servo on channel 5 (demonstrates 16-channel support)
ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: 5, angle: 45}"

Testing Multiple Servos:

# Sequential servo control - sweep through channels 0-4
for i in {0..4}; do
  ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: $i, angle: 90}"
  sleep 0.5
done

# Center all servos
for i in {0..4}; do
  ros2 service call /dexi/servo_control dexi_interfaces/srv/ServoControl "{pin: $i, angle: 90}"
done

TCA9555 Controller

Manages TCA9555 16-bit I2C I/O expander for GPIO control with configurable pin modes.

Hardware Setup:

  • Connect TCA9555 to I2C (SDA: GPIO 2, SCL: GPIO 3)
  • Set address pins A0, A1, A2 to GND for address 0x20
  • Power from 3.3V
  • Note: Supports pins 0-4 and 14-15
ros2 launch dexi_cpp tca9555_controller.launch.py

Configuration: The launch file configures pins 0-2 and 14-15 as outputs and pins 3-4 as inputs by default.

Services:

  • /dexi/gpio_writer_service/write_gpio (dexi_interfaces/srv/GPIOSend) - Set output pin state

Topics:

  • /tca9555_controller/gpio_<pin>_state (std_msgs/Bool) - Input pin states

Usage:

# Set output pin 0 high
ros2 service call /dexi/gpio_writer_service/write_gpio dexi_interfaces/srv/GPIOSend "{pin: 0, state: true}"

# Set output pin 0 low
ros2 service call /dexi/gpio_writer_service/write_gpio dexi_interfaces/srv/GPIOSend "{pin: 0, state: false}"

# Monitor input pin 3
ros2 topic echo /tca9555_controller/gpio_3_state

RGB Status LED Controller

Controls RGB status indicators.

ros2 launch dexi_cpp rgb_status_led_controller.launch.py

Configuration

TCA9555 Pin Configuration

Modify pin modes in launch/tca9555_controller.launch.py:

'pin_0_mode': True,   # Pin 0: output
'pin_1_mode': True,   # Pin 1: output
'pin_2_mode': True,   # Pin 2: output
'pin_3_mode': False,  # Pin 3: input
'pin_4_mode': False,  # Pin 4: input
'pin_14_mode': True,  # Pin 14: output
'pin_15_mode': True   # Pin 15: output

Parameter Overrides

Override parameters at launch:

# Change I2C device and polling rate
ros2 launch dexi_cpp tca9555_controller.launch.py i2c_device:=/dev/i2c-0 input_polling_rate:=5.0

# Change servo parameters
ros2 launch dexi_cpp servo_controller.launch.py i2c_address:=64

Troubleshooting

Permission Issues

# Add user to i2c group (required for I2C devices)
sudo usermod -a -G i2c $USER

# Log out and back in for group changes to take effect

I2C Issues

# Check I2C devices
i2cdetect -y 1

# Check I2C permissions
ls -la /dev/i2c-*

# Test I2C communication
i2cget -y 1 0x20 0x00  # Read TCA9555 input port 0

Build Issues

# Clean and rebuild
rm -rf build/dexi_cpp install/dexi_cpp log/latest_build/dexi_cpp
colcon build --packages-select dexi_cpp --symlink-install
source install/setup.bash

Examples

Pin Control Example

A Python example demonstrating how to read TCA9555 input pins and control output pins:

# Make executable
chmod +x examples/example_pin_control.py

# Run the example (requires TCA9555 controller to be running)
python3 examples/example_pin_control.py

This example subscribes to pin 4 input and mirrors its state to pin 0 output.

Toggle Pin Example

A simple example that toggles TCA9555 pin 14 on and off at 1-second intervals:

# Make executable
chmod +x examples/example_toggle_pin.py

# Run the example (requires TCA9555 controller to be running)
python3 examples/example_toggle_pin.py

Dependencies

  • ROS2 Humble or later
  • rclcpp - ROS2 C++ client library
  • std_msgs - Standard ROS2 message types
  • dexi_interfaces - Custom service and message definitions

License

MIT License - see LICENSE file for details.

About

CPP nodes for DEXI drone

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors