Camera Auto-Focus Motor Driver Development
Overview
A camera auto-focus motor device is a dedicated component used to implement auto-focus, typically controlled over an I2C interface. As shown below, the Image Signal Processor (ISP) calculates sharpness metrics for each frame and reports them to the Image Processing Algorithms (IPA); the IPA then analyzes these statistics, commands the auto-focus motor to move, and completes focusing.

Camera Auto-Focus Motor Data Flow
Driver Architecture
The code structure of the camera auto-focus motor driver is as follows:
├── include
│ └── dw9714_types.h
│ └── dw9714.h
├── private_include
│ └── dw9714_settings.h # Initialization settings of the motor driver
└── Kconfig.dw9714
└── dw9714.c # Implementation of the motor driver
Attention
You can adapt an existing driver for an auto-focus motor with similar specifications to bring up your own driver.
There are many possible hardware connection methods between the auto-focus motor and the camera module. Write the driver based on actual hardware needs. It is recommended to reuse pins on the camera sensor and share the SCCB bus with the sensor to save SoC pins.
Feature Overview
The camera auto-focus motor driver provides the following features:
Device Discovery — includes read/write checks of the motor device and how to release resources after use.
Parameter Control — includes querying supported parameter information, and setting and querying parameter values.
I/O Control — includes controls such as device reset and sleep.
Format Management — describes how to enumerate supported formats, and how to set and query formats.
Get Name — describes how to query the current device name during use.
Kconfig Options — lists supported Kconfig options that can affect the driver.
Device Discovery
If the motor device is correctly connected to the SoC and the driver is functioning, the driver will automatically perform SCCB read/write checks on the motor and return esp_cam_motor_device_t to represent the device. You must obtain this device descriptor before calling any other esp_cam_motor_ APIs.
Probe a Specific Device via the Motor-Specific API
Using DW9714 as an example, include the dw9714.h header in your application code, then call dw9714_detect() to check whether the DW9714 motor is present on the bus.
Probe All Devices on a Specified SCCB Bus
The camera auto-focus motor driver provides an array that lets you probe all auto-focus motor devices connected to the specified SCCB bus. Use esp_cam_motor_detect_get_array() to obtain the start and end pointers of the array, ensuring compatibility with different device detection methods.
esp_cam_motor_detect_fn_t *array_start = NULL;
esp_cam_motor_detect_fn_t *array_end = NULL;
esp_cam_motor_detect_get_array(&array_start, &array_end);
for (esp_cam_motor_detect_fn_t *p = array_start; p < array_end; p++) {
esp_cam_motor_config_t cfg = {0};
esp_cam_motor_device_t *motor_dev;
const esp_video_init_cam_motor_config_t *cm = config->cam_motor;
cfg.sccb_handle = create_sccb_device(sccb_mark, ESP_VIDEO_INIT_MOTOR_SCCB, &cm->sccb_config, p->sccb_addr);
if (!cfg.sccb_handle) {
return ESP_FAIL;
}
cfg.reset_pin = cm->reset_pin;
cfg.pwdn_pin = cm->pwdn_pin;
cfg.signal_pin = cm->signal_pin;
motor_dev = (*(p->detect))((void *)&cfg);
if (!motor_dev) {
ESP_LOGE(TAG, "failed to detect motor with address=%x", p->sccb_addr);
continue;
}
break;
}
Delete Device
If the motor is no longer needed, call esp_cam_motor_del_dev() to release resources.
Parameter Control
You can query and set parameters of the camera auto-focus motor using the following functions:
esp_cam_motor_query_para_desc()is used to query parameter types and ranges.esp_cam_motor_get_para_value()is used to get current parameter values.esp_cam_motor_set_para_value()is used to set parameter values.
I/O Control
I/O control of the motor can be performed by calling esp_cam_motor_ioctl().
Format Management
Camera auto-focus motor format information includes operating mode, step information, default position, and more. All information determined by the initialization register list is described by the esp_cam_motor_format_t structure. By setting and querying this structure, the IPA can more clearly control the focus motor to achieve focus.
esp_cam_motor_query_formats()is used to query supported format information.esp_cam_motor_get_format()is used to query the format currently in use.esp_cam_motor_set_format()is used to set the format to use.
Attention
When adjusting the operating mode of the auto-focus motor, note the following:
Ringing effect: Due to inertia, moving the motor can cause oscillation. Auto-focus motor driver ICs typically provide vibration-suppression modes, such as the DW9714’s DLC (Dual Level Control) mode.
Boundary control: Due to inertia, approaching the boundary requires boundary control; otherwise the motor may hit the boundary. If the motor is moved to the farthest position from the image sensor array by default after power-up, a power-off may cause the motor to rapidly return to its initial position, hit the boundary, and produce noise. This is expected behavior.
Step size control: Do not move in a single large step; instead, move in multiple smooth small steps to gradually reach the target position. After writing the driver, you can start a timer, increment or decrement the step size in the timer callback, and then use a preview-capable example to observe whether the motor movement is smooth.
Due to gravity, the motor requires different step values depending on its orientation (horizontal, vertical up, vertical down). If an orientation sensor is available, use it for optimization.
Get Name
Call esp_cam_motor_get_name() to query the current motor device name.
Kconfig Options
Each auto-focus motor has a configuration file. Using DW9714 as an example, it corresponds to esp_cam_sensor/motors/dw9714/Kconfig.dw9714. Through this file, you can configure the default format to load, whether to enable auto-detection, and more.
In addition, there are some common configuration options:
CONFIG_CAMERA_SENSOR_MOTOR_DETECT_METHODselects the device detection method for camera sensors and auto-focus motors, supporting the following two modes:CONFIG_CAMERA_SENSOR_MOTOR_DETECT_METHOD_DYNAMIC_LINK(default): Uses theesp_cam_motor_detect_fnlinker section to automatically include all available auto-focus motor detection functions and their configuration data in the current firmware. Even if the application code does not explicitly reference these functions, the linker retains them, enabling auto-detection of all enabled motors. However, the firmware size is relatively larger.CONFIG_CAMERA_SENSOR_MOTOR_DETECT_METHOD_STATIC_STORE: Stores only the auto-focus motor detection functions and their configuration data actually referenced by the application as a C array in flash. Unreferenced detection functions and data can be excluded from the final firmware by the linker, reducing binary size.
API Reference
Header File
Functions
-
esp_err_t esp_cam_motor_query_para_desc(esp_cam_motor_device_t *dev, esp_cam_motor_param_desc_t *qdesc)
Query the supported data types of extended control parameters.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.qdesc – [out] The pointer to hold the extended control parameters.
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
-
esp_err_t esp_cam_motor_get_para_value(esp_cam_motor_device_t *dev, uint32_t id, void *arg, size_t size)
Get the current value of the control parameter.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.id – [in] Camera motor parameter ID.
arg – [out] Camera motor parameter setting data pointer.
size – [in] Camera motor parameter setting data size.
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
-
esp_err_t esp_cam_motor_set_para_value(esp_cam_motor_device_t *dev, uint32_t id, const void *arg, size_t size)
Set the value of the control parameter.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.id – [in] Camera motor parameter ID.
arg – [in] Camera motor parameter setting data pointer.
size – [in] Camera motor parameter setting data size.
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
-
esp_err_t esp_cam_motor_query_formats(esp_cam_motor_device_t *dev, esp_cam_motor_fmt_array_t *format_array)
Get driver information supported by the motor driver.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.format_array – [out] The pointer to hold the description of the currently supported formats(configurations).
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
-
esp_err_t esp_cam_motor_set_format(esp_cam_motor_device_t *dev, const esp_cam_motor_format_t *format)
Set the working format of the camera motor.
Note
If format is NULL, the camera motor will load the default format.
Note
Query the currently supported formats by calling esp_cam_motor_query_format.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.format – [in] The pointer to hold the description of the currently supported format.
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
ESP_CAM_MOTOR_ERR_FAILED_SET_FORMAT: An error occurred while writing data over the SCCB bus
-
esp_err_t esp_cam_motor_get_format(esp_cam_motor_device_t *dev, esp_cam_motor_format_t *format)
Get the current camera motor Working format.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.format – [out] The pointer to hold the description of the currently format.
- Returns:
ESP_OK: Success
ESP_FAIL: The motor driver has not been formatured the working format yet.
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this operation.
-
esp_err_t esp_cam_motor_ioctl(esp_cam_motor_device_t *dev, uint32_t cmd, void *arg)
Perform an ioctl request on the camera motor.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.cmd – [in] The ioctl command, see esp_cam_motor_types.h.
arg – [in] The argument accompanying the ioctl command.
- Returns:
ESP_OK: Success
ESP_ERR_INVALID_ARG: Error in the passed arguments.
ESP_ERR_NOT_SUPPORTED: The motor driver does not support this cmd or arg.
-
const char *esp_cam_motor_get_name(esp_cam_motor_device_t *dev)
Get the module name of the current camera device.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.- Returns:
Camera module name on success, or “NULL”
-
esp_err_t esp_cam_motor_del_dev(esp_cam_motor_device_t *dev)
Delete camera device.
- Parameters:
dev – [in] Camera motor device handle that was created by
motor_detect.- Returns:
ESP_OK: If Camera motor is successfully deleted.