Files
PlantWater/MOTOR_CONTROL_README.md

7.0 KiB

Motor Control Module

This module provides safe and reliable control of water pumps using the TB6612FNG motor driver.

Features

  • Dual Motor Control: Independent control of 2 DC water pumps
  • PWM Speed Control: Variable speed from 20% to 100%
  • Safety Features:
    • Maximum runtime protection (default 30 seconds)
    • Minimum interval between runs (default 5 minutes)
    • Soft-start to reduce current spikes
    • Emergency stop functionality
  • Runtime Statistics: Track usage, runtime, and error counts
  • MQTT Integration: Full remote control and monitoring
  • NVS Persistence: Statistics survive reboots

Hardware Connections

ESP32-S3 to TB6612FNG Wiring

ESP32-S3 TB6612FNG Function
GPIO4 AIN1 Pump 1 Direction
GPIO5 AIN2 Pump 1 Direction
GPIO6 BIN1 Pump 2 Direction
GPIO7 BIN2 Pump 2 Direction
GPIO8 PWMA Pump 1 Speed (PWM)
GPIO9 PWMB Pump 2 Speed (PWM)
GPIO10 STBY Standby (Active High)
GND GND Ground
3.3V VCC Logic Power

Power Connections

  • VM on TB6612FNG: Connect to pump power supply (12V typical)
  • Pump 1: Connect to AOUT1 and AOUT2
  • Pump 2: Connect to BOUT1 and BOUT2

Usage

Basic Control

// Initialize the motor control system
motor_control_init();

// Start pump at default speed (80%)
motor_start(MOTOR_PUMP_1, MOTOR_DEFAULT_SPEED);

// Start pump at specific speed
motor_start(MOTOR_PUMP_2, 60);  // 60% speed

// Stop pumps
motor_stop(MOTOR_PUMP_1);
motor_stop_all();  // Stop all pumps

// Emergency stop (immediate)
motor_emergency_stop();

Timed Operations

// Run pump for specific duration
motor_start_timed(MOTOR_PUMP_1, 80, 10000);  // 80% speed for 10 seconds

// Pulse operation
motor_pulse(MOTOR_PUMP_1, 90, 2000, 1000, 5);  // On 2s, off 1s, repeat 5x

Speed Control

// Change speed while running
motor_set_speed(MOTOR_PUMP_1, 50);  // Change to 50%

// Set speed limits
motor_set_speed_limits(MOTOR_PUMP_1, 30, 90);  // Min 30%, Max 90%

Safety Configuration

// Set maximum runtime (prevents pump from running too long)
motor_set_max_runtime(MOTOR_PUMP_1, 60000);  // 60 seconds max

// Set minimum interval between runs (prevents frequent cycling)
motor_set_min_interval(MOTOR_PUMP_1, 300000);  // 5 minutes

Status and Statistics

// Check if pump is running
if (motor_is_running(MOTOR_PUMP_1)) {
    uint32_t runtime = motor_get_runtime_ms(MOTOR_PUMP_1);
    ESP_LOGI(TAG, "Pump has been running for %d ms", runtime);
}

// Check if in cooldown
if (motor_is_cooldown(MOTOR_PUMP_1)) {
    ESP_LOGI(TAG, "Pump is in cooldown period");
}

// Get statistics
motor_stats_t stats;
motor_get_stats(MOTOR_PUMP_1, &stats);
ESP_LOGI(TAG, "Total runtime: %d seconds", stats.total_runtime_ms / 1000);
ESP_LOGI(TAG, "Total runs: %d", stats.run_count);

MQTT Commands

Basic Control

  • Topic: plant_watering/pump/[1-2]/set
  • Payload:
    • on - Start pump at default speed
    • off - Stop pump
    • pulse - Run pump for 5 seconds

Speed Control

  • Topic: plant_watering/pump/[1-2]/speed
  • Payload: 0-100 (percentage)

Test Commands

  • Topic: plant_watering/commands/test_pump/[1-2]
  • Payload: Duration in milliseconds (max 10000)

Emergency Stop

  • Topic: plant_watering/commands/emergency_stop
  • Payload: Any value

MQTT Status Publishing

The system publishes the following status information:

Pump State

  • Topic: plant_watering/pump/[1-2]/state
  • Values: on, off

Runtime (when running)

  • Topic: plant_watering/pump/[1-2]/runtime
  • Value: Current runtime in milliseconds

Statistics (on connect and periodically)

  • Topic: plant_watering/pump/[1-2]/stats
  • Format: JSON
{
  "total_runtime": 123456,
  "run_count": 42,
  "last_duration": 5000
}

Errors

  • Topic: plant_watering/alerts/pump_error/[1-2]
  • Value: Error description string

Testing

Hardware Test Program

A standalone test program is provided in motor_test.c. To use it:

  1. Replace app_main() in your main.c with the test version
  2. Build and flash
  3. Monitor serial output
  4. Verify each pump responds correctly

Test Sequence

  1. Individual pump ON/OFF test
  2. PWM speed ramping
  3. Timed operations
  4. Dual pump operation
  5. Safety features (cooldown, max runtime)
  6. Emergency stop
  7. Statistics verification

Manual Testing via MQTT

# Start pump 1
mosquitto_pub -h <broker> -t "plant_watering/pump/1/set" -m "on"

# Change speed
mosquitto_pub -h <broker> -t "plant_watering/pump/1/speed" -m "50"

# Stop pump
mosquitto_pub -h <broker> -t "plant_watering/pump/1/set" -m "off"

# Test run for 3 seconds
mosquitto_pub -h <broker> -t "plant_watering/commands/test_pump/1" -m "3000"

# Emergency stop all
mosquitto_pub -h <broker> -t "plant_watering/commands/emergency_stop" -m "1"

Troubleshooting

Pump Not Starting

  1. Check cooldown period hasn't been violated
  2. Verify power connections (12V to VM)
  3. Check STBY pin is HIGH
  4. Verify PWM signal on oscilloscope

Pump Runs Continuously

  1. Check safety timer is working
  2. Verify MQTT commands are being received
  3. Check for stuck relay/MOSFET

Low Power/Speed

  1. Check power supply voltage and current capacity
  2. Verify PWM duty cycle
  3. Check for voltage drop in wiring
  4. Ensure pumps aren't clogged

Error Messages

  • "Cooldown period not elapsed": Wait for minimum interval
  • "Maximum runtime exceeded": Safety timer triggered
  • "Motor not initialized": Call motor_control_init() first

Design Considerations

Soft Start

The module implements a 500ms soft-start sequence, ramping PWM from 0 to target speed in 5% increments. This reduces current spikes and mechanical stress.

Unidirectional Operation

While the TB6612FNG supports bidirectional control, pumps are configured for forward operation only. The direction pins are set but typically won't be changed.

Power Management

The STBY pin is used to enable/disable the motor driver. During emergency stop, STBY is pulled low momentarily to ensure immediate motor shutdown.

Statistics Persistence

Runtime statistics are saved to NVS every 10 pump cycles to minimize flash wear while preserving useful data across reboots.

Integration Example

// In your main application
void app_main() {
    // Initialize subsystems
    wifi_manager_init();
    mqtt_client_init();
    motor_control_init();
    
    // Configure safety limits from Kconfig
    motor_set_max_runtime(MOTOR_PUMP_1, CONFIG_WATERING_MAX_DURATION_MS);
    motor_set_min_interval(MOTOR_PUMP_1, CONFIG_WATERING_MIN_INTERVAL_MS);
    
    // Register callbacks
    motor_register_state_callback(on_motor_state_change);
    motor_register_error_callback(on_motor_error);
    
    // Start your application...
}

// Automation example
void water_if_dry() {
    if (soil_moisture < 30 && !motor_is_cooldown(MOTOR_PUMP_1)) {
        motor_start_timed(MOTOR_PUMP_1, 70, 15000);  // 15 seconds at 70%
    }
}