/** * Motor Control Hardware Test Program * * This is a standalone test program to verify TB6612FNG motor driver * connections before integrating with the full system. * * Test sequence: * 1. Initialize motor control * 2. Test each pump individually * 3. Test PWM speed control * 4. Test safety features * 5. Test both pumps together */ #include #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" #include "motor_control.h" static const char *TAG = "MOTOR_TEST"; // Test callbacks static void test_state_callback(motor_id_t id, motor_state_t state) { const char *state_str[] = {"STOPPED", "RUNNING", "ERROR", "COOLDOWN"}; ESP_LOGI(TAG, "Motor %d state: %s", id, state_str[state]); } static void test_error_callback(motor_id_t id, const char* error) { ESP_LOGE(TAG, "Motor %d error: %s", id, error); } void app_main(void) { ESP_LOGI(TAG, "=== TB6612FNG Motor Driver Test Program ==="); ESP_LOGI(TAG, "GPIO Connections:"); ESP_LOGI(TAG, " AIN1 (Pump1 Dir): GPIO%d", MOTOR_AIN1_GPIO); ESP_LOGI(TAG, " AIN2 (Pump1 Dir): GPIO%d", MOTOR_AIN2_GPIO); ESP_LOGI(TAG, " BIN1 (Pump2 Dir): GPIO%d", MOTOR_BIN1_GPIO); ESP_LOGI(TAG, " BIN2 (Pump2 Dir): GPIO%d", MOTOR_BIN2_GPIO); ESP_LOGI(TAG, " PWMA (Pump1 PWM): GPIO%d", MOTOR_PWMA_GPIO); ESP_LOGI(TAG, " PWMB (Pump2 PWM): GPIO%d", MOTOR_PWMB_GPIO); ESP_LOGI(TAG, " STBY (Standby): GPIO%d", MOTOR_STBY_GPIO); // Initialize motor control ESP_LOGI(TAG, "\n--- Initializing Motor Control ---"); esp_err_t ret = motor_control_init(); if (ret != ESP_OK) { ESP_LOGE(TAG, "Failed to initialize motor control: %s", esp_err_to_name(ret)); return; } // Register callbacks motor_register_state_callback(test_state_callback); motor_register_error_callback(test_error_callback); // Wait a bit vTaskDelay(pdMS_TO_TICKS(2000)); // Test 1: Basic ON/OFF for Pump 1 ESP_LOGI(TAG, "\n--- Test 1: Pump 1 Basic ON/OFF ---"); ESP_LOGI(TAG, "Starting Pump 1 at default speed (%d%%)", MOTOR_DEFAULT_SPEED); motor_start(MOTOR_PUMP_1, MOTOR_DEFAULT_SPEED); vTaskDelay(pdMS_TO_TICKS(3000)); ESP_LOGI(TAG, "Stopping Pump 1"); motor_stop(MOTOR_PUMP_1); vTaskDelay(pdMS_TO_TICKS(2000)); // Test 2: Basic ON/OFF for Pump 2 ESP_LOGI(TAG, "\n--- Test 2: Pump 2 Basic ON/OFF ---"); ESP_LOGI(TAG, "Starting Pump 2 at default speed (%d%%)", MOTOR_DEFAULT_SPEED); motor_start(MOTOR_PUMP_2, MOTOR_DEFAULT_SPEED); vTaskDelay(pdMS_TO_TICKS(3000)); ESP_LOGI(TAG, "Stopping Pump 2"); motor_stop(MOTOR_PUMP_2); vTaskDelay(pdMS_TO_TICKS(2000)); // Test 3: PWM Speed Control ESP_LOGI(TAG, "\n--- Test 3: PWM Speed Control (Pump 1) ---"); int speeds[] = {30, 50, 70, 90, 100}; for (int i = 0; i < sizeof(speeds)/sizeof(speeds[0]); i++) { ESP_LOGI(TAG, "Testing speed: %d%%", speeds[i]); motor_start(MOTOR_PUMP_1, speeds[i]); vTaskDelay(pdMS_TO_TICKS(2000)); } motor_stop(MOTOR_PUMP_1); vTaskDelay(pdMS_TO_TICKS(2000)); // Test 4: Timed Run ESP_LOGI(TAG, "\n--- Test 4: Timed Run (5 seconds) ---"); ESP_LOGI(TAG, "Starting Pump 1 for 5 seconds"); motor_start_timed(MOTOR_PUMP_1, 70, 5000); vTaskDelay(pdMS_TO_TICKS(7000)); // Wait for completion // Test 5: Both pumps together ESP_LOGI(TAG, "\n--- Test 5: Both Pumps Together ---"); ESP_LOGI(TAG, "Starting both pumps"); motor_start(MOTOR_PUMP_1, 60); motor_start(MOTOR_PUMP_2, 80); vTaskDelay(pdMS_TO_TICKS(3000)); ESP_LOGI(TAG, "Stopping both pumps"); motor_stop_all(); vTaskDelay(pdMS_TO_TICKS(2000)); // Test 6: Safety - Cooldown Period ESP_LOGI(TAG, "\n--- Test 6: Cooldown Period Test ---"); motor_set_min_interval(MOTOR_PUMP_1, 5000); // 5 second cooldown for test ESP_LOGI(TAG, "Starting pump 1"); motor_start(MOTOR_PUMP_1, 50); vTaskDelay(pdMS_TO_TICKS(2000)); motor_stop(MOTOR_PUMP_1); ESP_LOGI(TAG, "Attempting to restart immediately (should fail)"); ret = motor_start(MOTOR_PUMP_1, 50); if (ret != ESP_OK) { ESP_LOGI(TAG, "Good! Cooldown protection working"); } ESP_LOGI(TAG, "Waiting for cooldown period..."); vTaskDelay(pdMS_TO_TICKS(6000)); ESP_LOGI(TAG, "Attempting to start after cooldown"); ret = motor_start(MOTOR_PUMP_1, 50); if (ret == ESP_OK) { ESP_LOGI(TAG, "Good! Pump started after cooldown"); vTaskDelay(pdMS_TO_TICKS(2000)); motor_stop(MOTOR_PUMP_1); } // Test 7: Speed change while running ESP_LOGI(TAG, "\n--- Test 7: Speed Change While Running ---"); ESP_LOGI(TAG, "Starting at 30%%"); motor_start(MOTOR_PUMP_1, 30); vTaskDelay(pdMS_TO_TICKS(2000)); ESP_LOGI(TAG, "Changing to 70%%"); motor_set_speed(MOTOR_PUMP_1, 70); vTaskDelay(pdMS_TO_TICKS(2000)); ESP_LOGI(TAG, "Changing to 100%%"); motor_set_speed(MOTOR_PUMP_1, 100); vTaskDelay(pdMS_TO_TICKS(2000)); motor_stop(MOTOR_PUMP_1); // Test 8: Emergency Stop ESP_LOGI(TAG, "\n--- Test 8: Emergency Stop ---"); ESP_LOGI(TAG, "Starting both pumps"); motor_start(MOTOR_PUMP_1, 80); motor_start(MOTOR_PUMP_2, 80); vTaskDelay(pdMS_TO_TICKS(2000)); ESP_LOGI(TAG, "Triggering emergency stop!"); motor_emergency_stop(); ESP_LOGI(TAG, "Checking states after emergency stop"); if (!motor_is_running(MOTOR_PUMP_1) && !motor_is_running(MOTOR_PUMP_2)) { ESP_LOGI(TAG, "Good! Both pumps stopped"); } vTaskDelay(pdMS_TO_TICKS(2000)); // Test 9: Get Statistics ESP_LOGI(TAG, "\n--- Test 9: Runtime Statistics ---"); motor_stats_t stats; for (int i = 1; i <= 2; i++) { if (motor_get_stats(i, &stats) == ESP_OK) { ESP_LOGI(TAG, "Pump %d Statistics:", i); ESP_LOGI(TAG, " Total runtime: %lu ms", stats.total_runtime_ms); ESP_LOGI(TAG, " Run count: %lu", stats.run_count); ESP_LOGI(TAG, " Last duration: %lu ms", stats.last_run_duration_ms); ESP_LOGI(TAG, " Error count: %lu", stats.error_count); } } // Test 10: Maximum runtime safety ESP_LOGI(TAG, "\n--- Test 10: Maximum Runtime Safety ---"); motor_set_max_runtime(MOTOR_PUMP_1, 3000); // 3 second max for test ESP_LOGI(TAG, "Starting pump 1 (should auto-stop after 3 seconds)"); motor_start(MOTOR_PUMP_1, 50); // Wait for safety timer vTaskDelay(pdMS_TO_TICKS(5000)); if (!motor_is_running(MOTOR_PUMP_1)) { ESP_LOGI(TAG, "Good! Safety timer stopped the pump"); } // Test 11: Soft Start Observation ESP_LOGI(TAG, "\n--- Test 11: Soft Start Observation ---"); ESP_LOGI(TAG, "Watch/listen for gradual speed increase over 500ms"); motor_start(MOTOR_PUMP_1, 100); vTaskDelay(pdMS_TO_TICKS(3000)); motor_stop(MOTOR_PUMP_1); // Final test summary ESP_LOGI(TAG, "\n=== All Tests Complete ==="); ESP_LOGI(TAG, "Test Summary:"); ESP_LOGI(TAG, " ✓ Basic ON/OFF control"); ESP_LOGI(TAG, " ✓ PWM speed control"); ESP_LOGI(TAG, " ✓ Timed operations"); ESP_LOGI(TAG, " ✓ Dual pump control"); ESP_LOGI(TAG, " ✓ Safety features"); ESP_LOGI(TAG, " ✓ Emergency stop"); ESP_LOGI(TAG, " ✓ Statistics tracking"); ESP_LOGI(TAG, ""); ESP_LOGI(TAG, "Monitor the pumps to ensure they responded correctly to all commands"); ESP_LOGI(TAG, "Check for any unusual noises, heating, or behavior"); // Keep running and print status periodically ESP_LOGI(TAG, "\nEntering monitoring mode - System status every 10 seconds"); while (1) { vTaskDelay(pdMS_TO_TICKS(10000)); ESP_LOGI(TAG, "--- System Status ---"); ESP_LOGI(TAG, "Free heap: %d bytes", esp_get_free_heap_size()); for (int i = 1; i <= 2; i++) { motor_stats_t current_stats; if (motor_get_stats(i, ¤t_stats) == ESP_OK) { const char *state = "IDLE"; if (motor_is_running(i)) { state = "RUNNING"; } else if (motor_is_cooldown(i)) { state = "COOLDOWN"; } ESP_LOGI(TAG, "Pump %d: State=%s, Total runs=%lu, Total time=%lu s", i, state, current_stats.run_count, current_stats.total_runtime_ms / 1000); } } } }