267 lines
7.0 KiB
Markdown
267 lines
7.0 KiB
Markdown
# 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 <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
|
|
|
|
```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%
|
|
}
|
|
}
|
|
``` |