# 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 ```c // 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 ```c // 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 ```c // 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 ```c // 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 ```c // 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 ```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 ```bash # Start pump 1 mosquitto_pub -h -t "plant_watering/pump/1/set" -m "on" # Change speed mosquitto_pub -h -t "plant_watering/pump/1/speed" -m "50" # Stop pump mosquitto_pub -h -t "plant_watering/pump/1/set" -m "off" # Test run for 3 seconds mosquitto_pub -h -t "plant_watering/commands/test_pump/1" -m "3000" # Emergency stop all mosquitto_pub -h -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 ```c // 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% } } ```