Hull controller technical documentation - SergeGit/rc-tank-platform GitHub Wiki

RC Tank Hull Controller Documentation

Overview

The RC Tank Hull Controller is an Arduino Nano-based system that acts as an I2C slave to a Raspberry Pi Turret Controller. The system provides comprehensive control over a model tank's movement, weapons systems, and lighting.

The controller architecture is modular, separating functionality into distinct systems:

  • BMS (Battery Management System): Monitors and controls battery voltage
  • Tracks: Controls tank forward/backward movement and turning
  • Turret: Controls turret rotation and elevation
  • Weapons: Controls cannon, laser, and IR emitters
  • Lights: Controls front and rear lighting systems
  • Motor Control: Unified system for multiple motor types with speed ramping

Hardware Requirements

  • Arduino Nano microcontroller
  • Motor drivers:
    • Cytron motor drivers for tracks
    • L293D motor drivers for turret controls
  • Voltage divider for battery monitoring
  • Relay for battery control (optional)
  • LED lights for front/rear indicators
  • Cannon, laser, and IR emitter components
  • Appropriate wiring and power supply

Pin Configuration

All pin assignments are centralized in config.h for easy modification. Key pin assignments include:

Battery Management

  • Battery Voltage: A0
  • Battery Relay: A1

Lights

  • Front Lights: A2
  • Rear Lights: A7

Weapons

  • Cannon: 13 (also built-in LED)
  • Laser: A3
  • IR Light: 6
  • Cannon Fired Interrupt: 2

Track Motors (Cytron)

  • Left Track PWM1: 3
  • Left Track PWM2: 9
  • Right Track PWM1: 10
  • Right Track PWM2: 11

Turret Motors (L293D)

  • Rotation Enable: 5
  • Rotation Input 1: 8
  • Rotation Input 2: 7
  • Elevation Enable: 6
  • Elevation Input 1: 4
  • Elevation Input 2: 12

I2C Communication Protocol

The controller operates as an I2C slave at address 0x08 (configurable in config.h). It responds to commands from the Raspberry Pi master.

Command Format

Commands typically consist of two bytes:

  1. Command byte (identifies the action)
  2. Data byte (parameter for the action)

Command Codes

Command Hex Code Description Data Range
Turret Rotate 0x10 Controls turret rotation 0-200 (maps to -100 to +100)
Turret Elevate 0x11 Controls turret elevation 0-200 (maps to -100 to +100)
Tracks Move 0x20 Controls forward/backward movement 0-200 (maps to -100 to +100)
Tracks Turn 0x21 Controls left/right turning 0-200 (maps to -100 to +100)
Laser Toggle 0x30 Toggles laser on/off 0 (off) or 1 (on)
IR Toggle 0x31 Toggles IR emitter on/off 0 (off) or 1 (on)
Cannon Fire 0x32 Fires cannon Duration (see config)
Front Lights 0x40 Controls front lights 0 (off), 1 (on), 2 (blinking)
Rear Lights 0x41 Controls rear lights 0 (off), 1 (on), 2 (blinking)
Get Battery 0xE0 Request battery info N/A
Get Position 0xE1 Request position data N/A
Get Cannon Status 0xE2 Request cannon ready state N/A
Get GPS 0xE3 Request GPS data N/A
Get All Sensors 0xEF Request all sensor data N/A
Get Status 0xF0 Request system status N/A
Emergency Stop 0xFF Emergency stop all systems 0 (stop), 1 (resume)

Response Format

The controller responds with varying amounts of data depending on the command:

Command Response Size Response Format
Get Battery 5 bytes Battery data (voltage, type, relay state)
Get Position 4 bytes Position data (x, y coordinates as uint16)
Get Cannon Status 1 byte Cannon ready state (0 or 1)
Get GPS 8 bytes GPS coordinates (latitude, longitude as uint16)
Get All Sensors 16 bytes Combined sensor data
Get Status 1 byte Status flags (see below)

Status Byte Flags

  • Bit 0: Cannon ready state
  • Bit 1: Laser on
  • Bit 2: IR emitter on
  • Bit 3: Front lights on/blinking
  • Bit 4: Rear lights on/blinking
  • Bit 5: Battery relay enabled
  • Bit 6: Error state
  • Bit 7: Emergency stop active

Subsystem Details

Battery Management System (BMS)

The BMS monitors battery voltage through a voltage divider connected to analog pin A0. It can:

  • Detect battery type
  • Enable/disable a battery relay
  • Provide battery status information
  • Implement voltage compensation for motors

Key functions:

  • setupBatteryManagement(): Initialize the BMS
  • updateBatteryManagement(): Regularly update battery readings
  • updateBatteryVoltage(): Get current battery voltage
  • detectBatteryType(): Auto-detect the battery type
  • enableRelay(): Control the battery relay

Motor Control System

The unified motor control system handles both track and turret motors. It features:

  • Support for multiple motor types (L293D, Cytron)
  • Smooth speed ramping
  • Voltage compensation based on battery level
  • Minimum speed thresholds to overcome inertia

Key functions:

  • registerL293DMotor(): Add an L293D motor to the control system
  • registerCytronMotor(): Add a Cytron motor to the control system
  • setMotorSpeed(): Set target speed (-100 to 100)
  • stopMotor(): Immediately stop a specific motor
  • stopAllMotors(): Emergency stop all motors
  • updateMotors(): Update motor speeds (call in main loop)

Tracks Control

Controls the tank's movement using two track motors in a differential drive configuration.

Key functions:

  • handleTracksMove(): Process forward/backward movement commands
  • handleTracksTurn(): Process turning commands
  • setArcadeDriveInput(): Direct joystick-style control
  • trackdrive(): Set left and right track speeds directly
  • emergencyStopTracks(): Immediately stop both tracks

Turret Control

Controls the turret's rotation and elevation motors.

Key functions:

  • handleTurretRotate(): Process turret rotation commands
  • handleTurretElevate(): Process turret elevation commands
  • stopTurret(): Stop all turret motors

Weapons System

Controls the tank's weapons systems including cannon, laser, and IR emitter.

Key functions:

  • handleCannonFire(): Fire the cannon for a specified duration
  • handleLaserToggle(): Toggle the laser on/off
  • handleIrToggle(): Toggle the IR emitter on/off
  • getIsCannonReady(): Check if cannon is ready to fire

Light Control

Controls the tank's front and rear lights with support for blinking.

Key functions:

  • handleFrontLights(): Control front lights
  • handleRearLights(): Control rear lights
  • getFrontLightState(): Get current front light state
  • getRearLightState(): Get current rear light state

System States

The controller can be in one of three states:

  1. STATE_NORMAL: Normal operation
  2. STATE_ERROR: Error detected
  3. STATE_EMERGENCY_STOP: Emergency stop activated

Error Handling and Safety Features

The system includes several safety features:

  • Watchdog timer (1-second timeout)
  • Emergency stop command
  • Input validation for all commands
  • Battery voltage monitoring
  • LED indicators for system state

Configuration Parameters

All configurable parameters are centralized in config.h:

Timing Configuration

  • Battery check interval: 2000ms
  • Light blink interval: 500ms
  • Motor update interval: 20ms
  • Cannon cooldown period: 2000ms

Motor Control Parameters

  • Default ramp step: 5 PWM units per update
  • Track motor minimum threshold: 20 PWM units
  • Turret motor minimum threshold: 25 PWM units

Battery Monitoring

  • Voltage divider values: R1=100kΩ, R2=22kΩ
  • Reference voltage: 5.0V
  • Readings for moving average: 10

Usage Examples

Initializing the System

#include "main.h"

void setup() {
  // All subsystems are initialized in main.cpp's setup()
  // No additional setup required
}

void loop() {
  // All subsystem updates are handled in main.cpp's loop()
  // No additional loop code required
}

Sending Commands from Raspberry Pi

import smbus
import time

# Create I2C bus
bus = smbus.SMBus(1)  # Use 0 for older Raspberry Pi models

# I2C address of the Arduino
ARDUINO_ADDRESS = 0x08

# Command codes
CMD_TRACKS_MOVE = 0x20
CMD_CANNON_FIRE = 0x32
CMD_FRONT_LIGHTS = 0x40

# Move forward at half speed
bus.write_byte_data(ARDUINO_ADDRESS, CMD_TRACKS_MOVE, 150)  # 150 maps to +50 speed

# Fire cannon with medium duration
bus.write_byte_data(ARDUINO_ADDRESS, CMD_CANNON_FIRE, 128)  # ~half max duration

# Turn on front lights
bus.write_byte_data(ARDUINO_ADDRESS, CMD_FRONT_LIGHTS, 1)  # 1 = on

# Request battery data
bus.write_byte(ARDUINO_ADDRESS, 0xE0)
battery_data = bus.read_i2c_block_data(ARDUINO_ADDRESS, 0, 5)
voltage = (battery_data[0] | (battery_data[1] << 8)) / 100.0  # Convert to voltage
print(f"Battery: {voltage}V")

Troubleshooting

Common Issues

  1. Motors not responding:

    • Check motor driver connections
    • Verify battery voltage is sufficient
    • Ensure motor speed exceeds minimum threshold
  2. I2C communication errors:

    • Verify I2C address matches in both devices
    • Check SDA/SCL connections
    • Reduce I2C speed if experiencing issues
    • Use pull-up resistors on SDA/SCL lines
  3. Erratic behavior:

    • Check for adequate power supply
    • Verify no pin conflicts exist
    • Check for proper grounding
    • Isolate motor power from logic power if possible
  4. System repeatedly resets:

    • Watchdog timer may be triggering
    • Ensure loop() executes quickly enough
    • Add wdt_reset() calls if needed in long operations

Extending the System

Adding New Motors

// In your setup function:
byte newMotorIndex = registerL293DMotor(
  9,    // Enable pin (PWM)
  10,   // Input 1 pin
  11,   // Input 2 pin
  "New Motor",  // Name for diagnostics
  25    // Minimum threshold
);

// In your command handler:
void handleNewMotorCommand(byte data) {
  // Convert data (0-200) to speed (-100 to 100)
  int speed = data - 100;
  setMotorSpeed(newMotorIndex, speed);
}

Adding New Commands

  1. Add new command code in main.h:
#define CMD_NEW_FEATURE 0x50
  1. Add command handler in processCommand() in main.cpp:
case CMD_NEW_FEATURE:
  handleNewFeature(data);
  break;
  1. Create the handler function:
void handleNewFeature(byte data) {
  // Your implementation here
}

System API Reference

This section provides a complete reference to the API functions available in each module of the tank controller system.

Main System API

Function Parameters Return Type Description
processCommand(byte command, byte data) command: command code
data: parameter value
void Processes I2C commands from the master
prepareResponseData(byte command) command: command code void Prepares response data buffer for I2C requests
emergencyStop() none void Activates emergency stop mode
resumeFromEmergencyStop() none void Resumes normal operation after E-stop

Battery Management System (bms.h)

Function Parameters Return Type Description
setupBatteryManagement() none void Initializes the battery monitoring system
updateBatteryManagement() none void Updates battery readings (call periodically)
updateBatteryResponseData(byte *responseData) responseData: buffer to fill void Fills buffer with battery status data
logBatteryStatus() none void Outputs battery status to serial monitor
updateBatteryVoltage() none float Measures and returns current battery voltage
detectBatteryType() none void Auto-detects connected battery type
enableRelay(bool enable) enable: relay state void Controls battery relay

Exposed Variables

  • float batteryVoltage - Current battery voltage
  • int batteryType - Detected battery type
  • bool isRelayEnabled - Current relay state

Motor Control System (motor_control.h)

Function Parameters Return Type Description
setupMotorControl() none void Initializes the motor control system
registerL293DMotor() enablePin: PWM pin for speed
in1Pin: direction control 1
in2Pin: direction control 2
motorName: name for debug
minThreshold: starting power
byte Registers an L293D motor and returns its index
registerCytronMotor() driver: CytronMD object
motorName: name for debug
minThreshold: starting power
byte Registers a Cytron motor and returns its index
setMotorSpeed(byte motorIndex, int speed) motorIndex: motor ID
speed: -100 to +100
void Sets target speed with ramping
stopMotor(byte motorIndex) motorIndex: motor ID void Immediately stops specified motor
stopAllMotors() none void Immediately stops all motors
updateMotors() none void Updates motor speeds (call in main loop)
setSpeedRampStep(byte motorIndex, byte rampStep) motorIndex: motor ID
rampStep: ramp increment
void Adjusts ramping rate for smoother starts/stops
getMotorSpeed(byte motorIndex) motorIndex: motor ID int Returns current speed (-100 to +100)
getMotorTargetSpeed(byte motorIndex) motorIndex: motor ID int Returns target speed (-100 to +100)
getMotorState(byte motorIndex) motorIndex: motor ID int Returns state (0=stopped, 1=running, 2=ramping)

Tracks Control (tracks.h)

Function Parameters Return Type Description
setupTracks() none void Initializes track control system
handleTracksMove(byte data) data: 0-200 value void Handles forward/backward from command protocol
handleTracksTurn(byte data) data: 0-200 value void Handles turning from command protocol
setArcadeDriveInput(int forwardBackward, int leftRight) forwardBackward: -100 to +100
leftRight: -100 to +100
void Direct arcade-style control input
trackdrive(int leftSpeed, int rightSpeed) leftSpeed: -100 to +100
rightSpeed: -100 to +100
void Direct control of track speeds
emergencyStopTracks() none void Immediately stops both tracks
stopTracks() none void Alias for emergencyStopTracks()
getLeftTrackSpeed() none int Returns current left track speed
getRightTrackSpeed() none int Returns current right track speed

Turret Control (turret.h)

Function Parameters Return Type Description
setupTurret() none void Initializes turret control system
handleTurretRotate(byte data) data: 0-200 value void Handles rotation from command protocol
handleTurretElevate(byte data) data: 0-200 value void Handles elevation from command protocol
getTurretRotationSpeed() none int Returns current rotation motor speed
getTurretElevationSpeed() none int Returns current elevation motor speed
stopTurret() none void Immediately stops all turret motors

Weapons Control (weapons.h)

Function Parameters Return Type Description
setupWeapons() none void Initializes weapons systems
updateWeapons() none void Updates weapons state (call in main loop)
handleLaserToggle(byte data) data: 0 or 1 void Toggles laser on/off
handleIrToggle(byte data) data: 0 or 1 void Toggles IR emitter on/off
handleCannonFire(byte data) data: duration value void Fires cannon with specified duration
getIsCannonReady() none bool Returns true if cannon is ready to fire
getIsLaserOn() none bool Returns true if laser is active
getIsIrOn() none bool Returns true if IR emitter is active

Lights Control (lights.h)

Function Parameters Return Type Description
setupLights() none void Initializes lighting system
updateLights() none void Updates light states (call in main loop)
handleFrontLights(byte data) data: 0=off, 1=on, 2=blink void Controls front lights
handleRearLights(byte data) data: 0=off, 1=on, 2=blink void Controls rear lights
getFrontLightState() none byte Returns front light state (0,1,2)
getRearLightState() none byte Returns rear light state (0,1,2)

API Usage Examples

Controlling the Tank from Another Arduino

#include <Wire.h>

// Command codes
#define CMD_TRACKS_MOVE 0x20
#define CMD_TRACKS_TURN 0x21
#define CMD_FRONT_LIGHTS 0x40
#define CMD_EMERGENCY_STOP 0xFF

// I2C address of the tank controller
#define TANK_ADDRESS 0x08

void setup() {
  Wire.begin(); // Initialize as master
  Serial.begin(115200);
  delay(1000); // Give slave time to initialize
  
  // Turn on front lights
  sendCommand(CMD_FRONT_LIGHTS, 1);
}

void loop() {
  // Move forward at half speed
  sendCommand(CMD_TRACKS_MOVE, 150); // 150 = +50 speed
  delay(2000);
  
  // Turn right at half rate
  sendCommand(CMD_TRACKS_TURN, 150); // 150 = 50% right turn
  delay(1000);
  
  // Stop
  sendCommand(CMD_TRACKS_MOVE, 100); // 100 = 0 speed
  sendCommand(CMD_TRACKS_TURN, 100); // 100 = 0 turn
  delay(2000);
}

void sendCommand(byte command, byte data) {
  Wire.beginTransmission(TANK_ADDRESS);
  Wire.write(command);
  Wire.write(data);
  byte error = Wire.endTransmission();
  
  if (error) {
    Serial.print("I2C error: ");
    Serial.println(error);
  }
}

Reading Battery Status

#include <Wire.h>

#define TANK_ADDRESS 0x08
#define CMD_GET_BATTERY 0xE0

void setup() {
  Wire.begin();
  Serial.begin(115200);
}

void loop() {
  // Request battery data
  Wire.beginTransmission(TANK_ADDRESS);
  Wire.write(CMD_GET_BATTERY);
  Wire.endTransmission();
  
  // Read response (5 bytes)
  Wire.requestFrom(TANK_ADDRESS, 5);
  
  if (Wire.available() >= 5) {
    // First two bytes are voltage (uint16, hundredths of volts)
    uint16_t rawVoltage = Wire.read() | (Wire.read() << 8);
    float voltage = rawVoltage / 100.0;
    
    // Third byte is battery type
    byte batteryType = Wire.read();
    
    // Fourth byte is relay state
    bool relayEnabled = Wire.read() > 0;
    
    // Fifth byte is reserved/status
    byte status = Wire.read();
    
    // Print battery info
    Serial.print("Battery: ");
    Serial.print(voltage);
    Serial.print("V, Type: ");
    Serial.print(batteryType);
    Serial.print(", Relay: ");
    Serial.println(relayEnabled ? "ON" : "OFF");
  }
  
  delay(2000);
}

Extending with Custom Commands

To add a new command to the system, follow these steps:

  1. Define the command code in main.h:
#define CMD_CUSTOM_FEATURE 0x60
  1. Add command handler in the processCommand function in main.cpp:
case CMD_CUSTOM_FEATURE:
  handleCustomFeature(data);
  break;
  1. Implement the handler function:
void handleCustomFeature(byte data) {
  // Implement your custom functionality
  // For example, controlling a new accessory
  digitalWrite(PIN_CUSTOM_FEATURE, data > 0 ? HIGH : LOW);
}

Wiring Table

This table provides a complete reference for connecting all components to the Arduino Nano.

Arduino Nano Pin Assignments

Arduino Pin Connected To Wire Color (Recommended) Notes
Power Pins
VIN 7-12V Power Supply (+) Red Main power input
GND System Ground Black Connect to all GND connections
5V 5V Components Red For low-power sensors/devices
3.3V 3.3V Components Orange For 3.3V logic level components
I2C Pins
A4 (SDA) Raspberry Pi SDA Yellow I2C Data line
A5 (SCL) Raspberry Pi SCL White I2C Clock line
Analog Pins
A0 Battery Voltage Divider Purple Voltage divider output
A1 Battery Relay Control Brown Connect via transistor if needed
A2 Front Lights Blue Via transistor or LED driver
A3 Laser Module Yellow Via transistor
A7 Rear Lights Green Via transistor or LED driver
Digital Pins
D2 Cannon Fired Interrupt White Connect to firing detection
D3 Left Track PWM1 Gray Cytron motor driver
D4 Turret Elevation IN1 Brown L293D motor driver
D5 Turret Rotation EN Purple L293D motor driver (PWM)
D6 Turret Elevation EN Blue L293D motor driver (PWM)
D7 Turret Rotation IN2 Green L293D motor driver
D8 Turret Rotation IN1 Yellow L293D motor driver
D9 Left Track PWM2 White Cytron motor driver
D10 Right Track PWM1 Gray Cytron motor driver
D11 Right Track PWM2 White Cytron motor driver
D12 Turret Elevation IN2 Orange L293D motor driver
D13 Cannon Fire Control Red Controls cannon firing mechanism

Component Wiring Details

Battery Voltage Divider

Component Connection Wire Color
Battery + Voltage Divider R1 (100kΩ) Red
R1 & R2 Junction Arduino A0 Purple
R2 (22kΩ) GND Black

Cytron Motor Drivers (Tracks)

Driver Pin Connection Wire Color Notes
PWM1 Arduino D3 (Left), D10 (Right) Gray Speed control
PWM2 Arduino D9 (Left), D11 (Right) White Direction control
GND System Ground Black
VIN Motor Power Supply Red May need separate power supply
M+ Motor Positive Terminal Red
M- Motor Negative Terminal Black

L293D Motor Driver (Turret)

L293D Pin Connection Wire Color Notes
1 (Enable) Arduino D5 (Rotation) Purple PWM speed control
2 (Input) Arduino D8 Yellow Direction control
3 (Output) Turret Rotation Motor + Red
4, 5 (GND) System Ground Black Heat sink ground
6 (Output) Turret Rotation Motor - Black
7 (Input) Arduino D7 Green Direction control
8 (Vcc2) Motor Power Supply Red Motor voltage
9 (Enable) Arduino D6 (Elevation) Blue PWM speed control
10 (Input) Arduino D4 Brown Direction control
11 (Output) Turret Elevation Motor + Red
12, 13 (GND) System Ground Black Heat sink ground
14 (Output) Turret Elevation Motor - Black
15 (Input) Arduino D12 Orange Direction control
16 (Vcc1) 5V Logic Supply Red Logic voltage

Lights and Weapons

Component Positive Connection GND Control Pin Notes
Front Lights 5V or Battery + GND Arduino A2 via transistor Use NPN transistor or MOSFET
Rear Lights 5V or Battery + GND Arduino A7 via transistor Use NPN transistor or MOSFET
Laser Module 5V or Battery + GND Arduino A3 via transistor Use NPN transistor
IR Emitter 5V via resistor GND Arduino D6 via transistor Include current limiting resistor
Cannon Mechanism 5V or Battery + GND Arduino D13 via driver May need relay or driver circuit

Battery Relay

Relay Pin Connection Wire Color Notes
Control Pin Arduino A1 via transistor Brown NPN transistor or MOSFET
NO (Normally Open) Battery + Output Red
COM (Common) Battery + Input Red
GND System Ground Black
Vcc 5V Red For relay coil

Power Supply Considerations

  • Logic Power: Arduino Nano requires 7-12V DC input via VIN or USB
  • Motor Power: Motors may require separate power supply to prevent voltage drops affecting logic
  • Power Isolation: Consider using optoisolators or separate regulators to isolate motor noise from logic circuits
  • Current Requirements:
    • Arduino Nano: ~50mA
    • Track Motors: ~1-3A per motor
    • Turret Motors: ~500mA per motor
    • Lights: ~100-200mA total
    • Weapons: ~50-500mA depending on components

Connection Notes

  1. Ground Connections: All grounds (Arduino, motors, sensors, power supplies) must be connected together
  2. Signal Isolation: Use transistors or MOSFETs between Arduino pins and higher power components
  3. PWM Pins: Use only designated PWM pins (3, 5, 6, 9, 10, 11) for motor speed control
  4. Noise Reduction: Add 100nF ceramic capacitors across motor terminals to reduce EMI
  5. Wire Gauge: Use appropriate wire gauge for current requirements:
    • 22-24 AWG for signals and low current
    • 18-20 AWG for moderate current (lights, small motors)
    • 16 AWG or larger for high current (main track motors)

License and Credits

This controller software was designed for Arduino Nano to control an RC tank.


Note: This documentation covers the functionality shown in the provided code files. Additional functionality may require updates to this documentation.

⚠️ **GitHub.com Fallback** ⚠️