81 lines
2.9 KiB
Markdown
81 lines
2.9 KiB
Markdown
|
|
# as5600_node — AS5600 12-bit Magnetic Rotary Encoder (C++, I2C)
|
||
|
|
|
||
|
|
ROS2 node for reading AS5600 magnetic rotary position sensors via Linux I2C (`ioctl`). Publishes angle data periodically. Supports multiple encoders on separate I2C buses.
|
||
|
|
|
||
|
|
**Platform:** linux-aarch64 only (Raspberry Pi)
|
||
|
|
|
||
|
|
## ROS2 Interface
|
||
|
|
|
||
|
|
| Direction | Topic | Message | Description |
|
||
|
|
|---|---|---|---|
|
||
|
|
| Publish | `/encoder/state` | `EncoderRead` | Periodic angle readings per encoder |
|
||
|
|
|
||
|
|
```
|
||
|
|
# EncoderRead.msg (as5600_node → executor)
|
||
|
|
uint8 encoder_id # Encoder index (0, 1, 2, ...)
|
||
|
|
float32 angle # Angle in degrees (0.0-360.0)
|
||
|
|
uint16 raw_angle # Raw 12-bit value (0-4095)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Parameters
|
||
|
|
|
||
|
|
| Parameter | Type | Default | Description |
|
||
|
|
|---|---|---|---|
|
||
|
|
| `i2c_devices` | string[] | `["/dev/i2c-1"]` | List of I2C device paths, one per encoder |
|
||
|
|
| `publish_rate` | double | `10.0` | Publish frequency Hz |
|
||
|
|
|
||
|
|
## File Structure
|
||
|
|
|
||
|
|
```
|
||
|
|
src/as5600_node/
|
||
|
|
├── CMakeLists.txt # ament_cmake — NO external lib dependency
|
||
|
|
├── package.xml # depend: rclcpp, blockly_interfaces
|
||
|
|
├── include/as5600_node/
|
||
|
|
│ └── as5600_node.hpp # As5600Node class + I2C helpers + register constants
|
||
|
|
└── src/
|
||
|
|
├── as5600_node.cpp # I2C init, timer_callback, read_raw_angle
|
||
|
|
└── main.cpp # rclcpp::spin(node)
|
||
|
|
```
|
||
|
|
|
||
|
|
## Build & Run
|
||
|
|
|
||
|
|
```bash
|
||
|
|
pixi run build-as5600 # installs system deps (apt) + builds
|
||
|
|
pixi run as5600-node # start node with default parameters (1 encoder)
|
||
|
|
|
||
|
|
# 3 encoders on separate buses, 20 Hz
|
||
|
|
source install/setup.bash
|
||
|
|
ros2 run as5600_node as5600_node --ros-args \
|
||
|
|
-p i2c_devices:="['/dev/i2c-1', '/dev/i2c-3', '/dev/i2c-4']" \
|
||
|
|
-p publish_rate:=20.0
|
||
|
|
```
|
||
|
|
|
||
|
|
## AS5600 Register Map
|
||
|
|
|
||
|
|
| Register | Address | Description |
|
||
|
|
|---|---|---|
|
||
|
|
| RAW_ANGLE | `0x0C`-`0x0D` | 12-bit raw angle (0-4095) |
|
||
|
|
| STATUS | `0x0B` | Magnet detect status |
|
||
|
|
| AGC | `0x1A` | Automatic gain control |
|
||
|
|
|
||
|
|
## Implementation Notes
|
||
|
|
|
||
|
|
- AS5600 has a **fixed I2C address (0x36)** — cannot be changed. For multiple encoders, each must be on a **separate I2C bus**
|
||
|
|
- Uses Linux I2C via `ioctl()` + `linux/i2c-dev.h` — no external library dependency
|
||
|
|
- `I2C_SLAVE` address is set once per fd at startup (each fd is dedicated to one bus/encoder)
|
||
|
|
- Raw angle read: write register `0x0C`, read 2 bytes → `((buf[0] & 0x0F) << 8) | buf[1]` (12-bit)
|
||
|
|
- Angle conversion: `raw * 360.0 / 4096.0` degrees
|
||
|
|
- Timer callback iterates all fds and publishes one `EncoderRead` per encoder with `encoder_id` matching the index in `i2c_devices`
|
||
|
|
|
||
|
|
## Raspberry Pi I2C Setup
|
||
|
|
|
||
|
|
The Pi has one hardware I2C bus (`/dev/i2c-1`) by default. For multiple AS5600 encoders, enable extra I2C buses via GPIO bit-banging overlays in `/boot/config.txt`:
|
||
|
|
|
||
|
|
```
|
||
|
|
# Extra I2C buses using GPIO pins
|
||
|
|
dtoverlay=i2c-gpio,bus=3,i2c_gpio_sda=17,i2c_gpio_scl=27
|
||
|
|
dtoverlay=i2c-gpio,bus=4,i2c_gpio_sda=22,i2c_gpio_scl=23
|
||
|
|
```
|
||
|
|
|
||
|
|
After reboot, verify with `ls /dev/i2c-*` and `i2cdetect -y <bus>`.
|