SunnyLensParser C++ library
v1.0.0
Table of contents
- Overview
- Versions
- Library files
- Features and behavior
- SunnyLensParser class description
- Data structures
- Test application
- Build and connect to your project
Overview
The SunnyLensParser is a C++ library that is designed for encoding control commands and decoding responses from Sunny continuous zoom lenses. The library includes basic methods for preparing commands (encoding) and interpreting the lens responses (decoding). It utilizes C++17 standard. The library provides simple interface and doesn’t have third party dependencies. Also, the library provides test application to check communication with the lens via a serial port. Test application depends on SerialPort library (provides methods to work with serial ports, source code included, Apache 2.0 license).
Versions
Table 1 - Library versions.
Version | Release date | What’s new |
---|---|---|
1.0.0 | 31.05.2024 | - First version. |
Library files
The library is supplied only by source code. The user is given a set of files in the form of a CMake project (repository). The repository structure is shown below:
CMakeLists.txt ------------------- Main CMake file of the library.
src ----------------------------- Folder with library source code.
CMakeLists.txt --------------- CMake file of the library.
SunnyLensParser.h ------------ Main library header file.
SunnyLensParserVersion.h ----- Header file with library version.
SunnyLensParserVersion.h.in -- CMake service file to generate version header.
SunnyLensParser.cpp ---------- C++ implementation file.
test ----------------------------- Folder for test application files.
3rdparty --------------------- Folder with third-party libraries.
CMakeLists.txt ----------- CMake file to include third-party libraries.
SerialPort --------------- Folder with SerialPort library source code.
CMakeLists.txt --------------- CMake file for test application.
main.cpp --------------------- Source C++ file of test application.
Features and behavior
There are some features of Sunny lenses that help to better understand their behavior:
- The lens streams temperature (response SYSTEM_TEMPERATURE, SunnyResponse enum) once per second.
- The lens streams Zoom and Focus positions (response FOCUS_ZOOM_ENCODER_POSITIONS, SunnyResponse enum) only if there is a change, with a 5 msec timeout.
- Accuracy of setting up Zoom/Focus position about 5-10 for Zoom/Focus speed = 20.
- There are some issues in setting up the Zoom/Focus position at high speeds. Using a speed value greater than 20 yields unpredictable results.
- Responses ZOOM_POSITION_MAX and FOCUS_POSITION_MAX give values in big endian format, while other commands and responses use little endian format.
- Sometimes, lenses give responses with the wrong format. According to the format, the second byte sets the size of the data block in the message, but there are times when messages have the wrong size.
SunnyLensParser class description
SunnyLensParser class declaration
namespace cr
{
namespace sunny
{
/**
* @brief Sunny lens parser.
*/
class SunnyLensParser
{
public:
/// Get library version.
static std::string getVersion();
/// Encode Sunny lens command (from host tp lens).
bool getCommand(uint8_t *data, int &size, SunnyCommand commandId, int arg = 0);
/// Decode Sunny lens response (from lens to host).
SunnyResponse decodeResponse(uint8_t nextByte, int &data1, int &data2);
};
}
}
getVersion method
The getVersion() method return string of current SunnyLensParser class version. Method declaration:
static std::string getVersion();
Method can be used without SunnyLensParser class instance:
cout << "SunnyLensParser version: " << cr::sunny::SunnyLensParser::getVersion();
Console output:
SunnyLensParser version: 1.0.0
getCommand method
The getCommand(…) method encodes (prepares data) control command for lens. Method declaration:
bool getCommand(uint8_t *data, int &size, SunnyCommand commandId, int arg = 0);
Parameter | Value |
---|---|
data | Pointer to buffer. Buffer must have size >= 10. |
size | Size of encoded command. |
commandId | Command id according to SunnyCommand enum. |
arg | Arguments of command. The value of arguments depends on command id. Some commands don’t have arguments. |
Returns: TRUE if commands encoded or FALSE if not (not valid id, not valid parameters or not valid address).
Below is an example of encoding command.
// Init variables.
uint8_t buffer[128];
int size;
int zoomPosition = 1000;
parser.getCommand(buffer, size, SunnyCommand::SET_ZOOM_ENCODER, zoomPosition);
// Send data.
serialPort.write(buffer, size);
decodeResponse method
The decodeResponse(…) method decodes response from lens. Once the data from the serial port has been read the user must pass it to the method byte-by-byte (each byte separately in sequence). The library has an internal buffer. When the user passes another byte to the method, the library shifts the buffer by one byte and copies the new byte to the end of the buffer. If the library detects a valid response in internal buffer, it returns the response id (see SunnyResponse enum) and returns the response arguments. In all other cases, the library returns a NONE identifier. Method declaration:
SunnyResponse decodeResponse(uint8_t nextByte, int &data1, int &data2);
Parameter | Value |
---|---|
nextByte | Next read byte from serial port. |
data1 | First response arguments from lens. The number of arguments and their values depend on response ID (see SunnyResponse enum). Some responses don’t have arguments. |
data2 | Second response arguments from lens. The number of arguments and their values depend on response ID (see SunnyResponse enum). Some responses don’t have arguments. |
Returns: Response SunnyResponse if response detected or NONE id if not.
Below is an example of decoding response from lens.
// Get data from serial port.
uint8_t buffer[128];
int bytes = serialPort.read(buffer, 128);
int responseArg1, responseArg2;
// Decoding response byte-by-byte.
for (int i = 0; i < bytes; ++i)
{
SunnyResponse response = parser.decodeResponse(buffer[i], responseArg1, responseArg2);
switch (response)
{
case SunnyResponse::FOCUS_ZOOM_ENCODER_POSITIONS:
{
std::cout << "Focus encoder value: " << responseArg1 << std::endl;
std::cout << "Zoom encoder value: " << responseArg2 << std::endl;
}
///...
}
}
Data structures
SunnyCommand enum
The command id’s are described in the SunnyCommand enum in the SunnyLensParser.h file. The definition of the enum is as follows :
enum class SunnyCommand
{
/**
* @brief Focus near. No arguments.
*/
FOCUS_NEAR,
/**
* @brief Focus far. No arguments.
*/
FOCUS_FAR,
/**
* @brief Stop focus. No arguments.
*/
STOP_FOCUS,
/**
* @brief Zoom in. No arguments.
*/
ZOOM_IN,
/**
* @brief Zoom out. No arguments.
*/
ZOOM_OUT,
/**
* @brief Stop zoom. No arguments.
*/
STOP_ZOOM,
/**
* @brief Set the position of the focus motor after reset.
* @param arg Position of the focus motor, int.
*/
SET_FOCUS_HOME_POSITION,
/**
* @brief Set the position of the zoom motor after reset.
* @param arg Position of the zoom motor, int.
*/
SET_ZOOM_HOME_POSITION,
/**
* @brief Set the running speed of the focus motor.
* @param arg Speed of the focus motor. Value range: 0-100.
*/
SET_FOCUS_SPEED,
/**
* @brief Set the running speed of the zoom motor.
* @param arg Speed of the zoom motor. Value range: 0-100.
*/
SET_ZOOM_SPEED,
/**
* @brief Set the maximum position of focus.
* @param arg Maximum position of focus, int. Depends on current lens.
*/
SET_MAX_FOCUS_POSITION,
/**
* @brief Set the maximum position of zoom.
* @param arg Maximum position of zoom, int. Depends on current lens.
*/
SET_MAX_ZOOM_POSITION,
/**
* @brief Motor reset (covers some parameter resets). No arguments.
*/
RESET,
/**
* @brief Reset the focus motor. No arguments.
*/
RESET_FOCUS_MOTOR,
/**
* @brief Reset the zoom motor. No arguments.
*/
RESET_ZOOM_MOTOR,
/**
* @brief Set focus positioning point. Value 0 to FOCUS_POSITION_MAX.
* @param arg1 Focus encoder position, int.
*/
SET_FOCUS_ENCODER,
/**
* @brief Set zoom positioning point. Value 1 to ZOOM_POSITION_MAX.
* @param arg1 Zoom encoder position, int.
*/
SET_ZOOM_ENCODER,
/**
* @brief Not implemented.
*/
SET_FOCUS_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
SET_ZOOM_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
SET_HIGH_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Not implemented.
*/
SET_LOW_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Link mode enabled.
*/
SET_LINK_ENABLE,
/**
* @brief Link mode disabled.
*/
SET_LINK_DISABLE,
/**
* @brief Not implemented.
*/
GET_FOCUS_ZOOM_ENCODER_POSITION,
/**
* @brief Get system temperature. No arguments.
*/
GET_SYSTEM_TEMPERATURE,
/**
* @brief Get focus motor speed. No arguments.
*/
GET_FOCUS_SPEED,
/**
* @brief Get zoom motor speed. No arguments.
*/
GET_ZOOM_SPEED,
/**
* @brief Get focus motor reset presets. No arguments.
*/
GET_FOCUS_HOME_POSITION,
/**
* @brief Get zoom motor reset presets. No arguments.
*/
GET_ZOOM_HOME_POSITION,
/**
* @brief Get the maximum position value of the focus motor. No arguments.
*/
GET_FOCUS_POSITION_MAX,
/**
* @brief Get the maximum position value of the zoom motor. No arguments.
*/
GET_ZOOM_POSITION_MAX,
/**
* @brief Not implemented.
*/
GET_FOCUS_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
GET_ZOOM_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
GET_HIGH_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Not implemented.
*/
GET_LOW_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Not implemented.
*/
GET_SYSTEM_DATA
};
SunnyResponse enum
The response id’s are described in the SunnyResponse enum in the SunnyLensParser.h file. The definition of the enum is as follows:
enum class SunnyResponse
{
/**
* @brief No response.
*/
NONE,
/**
* @brief The focus and zoom motor code values.
* @param data1 Focus motor code value, int. Value 0 to FOCUS_POSITION_MAX.
* @param data2 Zoom motor code value, int. Value 0 to ZOOM_POSITION_MAX.
*/
FOCUS_ZOOM_ENCODER_POSITIONS,
/**
* @brief The system temperature in celsius.
* Constantly sends once per second 4 byte float value.
* @param data1 Temperature, int.
*/
SYSTEM_TEMPERATURE,
/**
* @brief The focus motor speed.
* @param data1 Speed of the focus motor. Value range: 0-100.
*/
FOCUS_SPEED,
/**
* @brief The zoom motor speed.
* @param data1 Speed of the zoom motor. Value range: 0-100.
*/
ZOOM_SPEED,
/**
* @brief The focus motor reset presets.
* @param data1 Position of the focus motor, int. Value 0 to FOCUS_POSITION_MAX.
*/
FOCUS_HOME_POSITION,
/**
* @brief The zoom motor reset presets.
* @param data1 Position of the zoom motor, int. Value 0 to ZOOM_POSITION_MAX.
*/
ZOOM_HOME_POSITION,
/**
* @brief The maximum position value of the focus motor. Depends on lens.
* response 4 byte int value in Big endian.
* @param data1 Maximum position of focus, int.
*/
FOCUS_POSITION_MAX,
/**
* @brief The maximum position value of the zoom motor. Depends on lens.
* response 4 byte int value in Big endian.
* @param data1 Maximum position of zoom, int.
*/
ZOOM_POSITION_MAX,
/**
* @brief Not implemented.
*/
FOCUS_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
ZOOM_POSITION_LINKAGE_DATA,
/**
* @brief Not implemented.
*/
HIGH_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Not implemented.
*/
LOW_TEMPERATURE_COEFFICIENT_DATA,
/**
* @brief Not implemented.
*/
SYSTEM_DATA,
};
Test application
Folder SunnyLensParser/test contains the test application files. The test application allows you to generate any command, send it to the lens over the serial port, receive and decode the response. Once started, the user must enter the serial port name (full name for Linux or just the port number for Windows) and baudrate:
==========================
SunnyLensParser v1.2.0 test.
==========================
Enter the serial port name: portName
Enter the baud rate (115200 for version 2, 19200 for earlier versions): 115200
Commands:
0 - Focus near.
1 - Focus far.
2 - Stop focus.
3 - Zoom in.
4 - Zoom out.
5 - Stop zoom.
6 - Set focus home position.
7 - Set zoom home position.
8 - Set focus speed.
9 - Set zoom speed.
10 - Set max focus position.
11 - Set max zoom position.
12 - Reset.
13 - Reset focus motor.
14 - Reset zoom motor.
15 - Set focus encoder.
16 - Set zoom encoder.
24 - Get system temperature.
25 - Get focus speed.
26 - Get zoom speed.
27 - Get focus home position.
28 - Get zoom home position.
29 - Get focus position max.
30 - Get zoom position max.
-1 - Exit.
Enter the command ID: 8
Enter the focus speed: 70
Then, corresponding command will be generated and sent to lens. Lens will return response and it will be decoded and printed on the screen if related command has a response.
Build and connect to your project
Typical commands to build SunnyLensParser library:
cd SunnyLensParser
git submodule update --init --recursive
mkdir build
cd build
cmake ..
make
If you want to connect SunnyLensParser library to your CMake project as source code you can make the following. For example, if your repository has structure:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
Create folder 3rdparty and copy folder of SunnyLensParser repository there. New structure of your repository:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
SunnyLensParser
Create CMakeLists.txt file in 3rdparty folder. CMakeLists.txt should contain:
cmake_minimum_required(VERSION 3.13)
################################################################################
## 3RD-PARTY
## dependencies for the project
################################################################################
project(3rdparty LANGUAGES CXX)
################################################################################
## SETTINGS
## basic 3rd-party settings before use
################################################################################
# To inherit the top-level architecture when the project is used as a submodule.
SET(PARENT ${PARENT}_YOUR_PROJECT_3RDPARTY)
# Disable self-overwriting of parameters inside included subdirectories.
SET(${PARENT}_SUBMODULE_CACHE_OVERWRITE OFF CACHE BOOL "" FORCE)
################################################################################
## CONFIGURATION
## 3rd-party submodules configuration
################################################################################
SET(${PARENT}_SUBMODULE_SUNNY_LENS_PARSER ON CACHE BOOL "" FORCE)
if (${PARENT}_SUBMODULE_SUNNY_LENS_PARSER)
SET(${PARENT}_SUNNY_LENS_PARSER ON CACHE BOOL "" FORCE)
SET(${PARENT}_SUNNY_LENS_PARSER_TEST OFF CACHE BOOL "" FORCE)
endif()
################################################################################
## INCLUDING SUBDIRECTORIES
## Adding subdirectories according to the 3rd-party configuration
################################################################################
if (${PARENT}_SUBMODULE_SUNNY_LENS_PARSER)
add_subdirectory(SunnyLensParser)
endif()
File 3rdparty/CMakeLists.txt adds folder SunnyLensParser to your project and excludes test application and example from compiling. Your repository new structure will be:
CMakeLists.txt
src
CMakeList.txt
yourLib.h
yourLib.cpp
3rdparty
CMakeLists.txt
SunnyLensParser
Next you need include folder 3rdparty in main CMakeLists.txt file of your repository. Add string at the end of your main CMakeLists.txt:
add_subdirectory(3rdparty)
Next you have to include SunnyLensParser library in your src/CMakeLists.txt file:
target_link_libraries(${PROJECT_NAME} SunnyLensParser)
Done!