All Files Functions Typedefs Enumerations Enumerator Macros Pages
Programmer's Guide

Getting Started

The Programmer's Guide for a BCON Adapter is a quick guide on how to build and debug a BCON Adapter library. It can be used together with the BCON Adapter sample code in order to get started. The documentation of the interfaces to be implemented is also available in the header files of the pylon BCON Adapter API.

Building and Installing the pylon BCON Adapter Library

This section shows how to build the pylon BCON Adapter using the GNU tool chain.

The BCON Adapter library is a dynamic link library that is loaded at runtime by pylon. It connects the pylon libraries to the custom BCON host hardware.

Our BCON Adapter sample shows how to implement this dynamic link library. In order to use the library you also need to run an application that loads pylon. In the following section the GenApiParam C sample is used for this purpose. It is also possible to use a pylon C++ sample instead. Build both, the GenApiParam C sample and the BCON Adapter library sample, and then run the GenApiParam sample as illustrated in the following snippet. The GenApiParam sample opens a device and displays some camera settings on the screen. After the GenApiParam sample has been exited, the log traces produced by pylon are shown.

Attention
The environment variables shown in the example below must be configured according to the system configuration used. Adapt the location of the installed pylon, pylon samples, BCON Adapter, and the I2C settings accordingly. All values shown are for demonstration purposes only.
export PYLON_ROOT=/opt/pylon5
export SAMPLES_DIRECTORY=/home/pylon_user/pylon5/Samples
make -C ${SAMPLES_DIRECTORY}/C/GenApiParam
make -C ${SAMPLES_DIRECTORY}/BconAdapterSample
export BCON_ADAPTER_LIB=${SAMPLES_DIRECTORY}/BconAdapterSample/libBconAdapterMySample.so
export BCON_ADAPTER_I2C_DEVICES="/dev/i2c-0:60"
export GENICAM_LOG_CONFIG_V3_0=${PYLON_ROOT}/share/pylon/log/config/DebugLoggingUnix.properties
export BXAPI_TRACE_LEVEL=60
${SAMPLES_DIRECTORY}/C/GenApiParam/GenApiParam
less /tmp/pylonLog.txt

In the paragraphs and sections below the used variables are explained in detail.

The PYLON_ROOT environment variable has to be set to the location of the pylon SDK. Usually the pylon SDK is installed at /opt/pylon5. If you installed it at a different location, adopt the PYLON_ROOT value. This is important because the sample makefiles and the utilities use this variable.

The BCON_ADAPTER_LIB locates the BCON Adapter library that should be loaded. Here the built BCON Adapter library sample is used by setting the value of BCON_ADAPTER_LIB to ${SAMPLES_DIRECTORY}/BconAdapterSample/libBconAdapterSample.so. This can be helpful when modifying the sample code.

The settings of the I2C devices have to be defined as value of the BCON_ADAPTER_I2C_DEVICES environment variable. The required settings are the device path, e.g. /dev/i2c-1, and the BCON address as decimal number, e.g. 60 or 61.

The GENICAM_LOG_CONFIG_V3_0 and BXAPI_TRACE_LEVEL variables are used to control the output of the logging facilities, see Logging section for more information. In the logging configuration file provided by pylon (DebugLoggingUnix.properties) all output is written into the /tmp/pylonLog.txt file.

BCON_ADAPTER_LIB

Basler pylon loads a single instance of the BCON Adapter library. It uses the BCON_ADAPTER_LIB environment variable to locate your BCON Adapter library. The environment variable should contain the complete path to the BCON Adapter library.

BCON_ADAPTER_LIB=<path_to_bcon_adapter_library>

Instead of using the BCON_ADAPTER_LIB evironment variable, you can copy the BCON Adapter library file name into the lib directory of the pylon installation. When copied to the lib directory of pylon the BCON Adapter library must match the pattern libBconAdapter*.so. If multiple BCON Adapter libraries are found, the first library is used, when sorted by file name in ascending order.

BCON_ADAPTER_I2C_DEVICES

The BCON Adapter sample uses all the I2C devices you configure in the BCON_ADAPTER_I2C_DEVICES environment variable. Each BCON device is described by the device path of the I2C bus it is attached to, followed by a colon, and then followed by the configured bus address as a decimal number. A single space seperates each BCON device.

BCON_ADAPTER_I2C_DEVICES="<device_path>:<device_address> [...]"

Debugging pylon BCON Adapter Library

The usage of a debugger as gdb is not scope of this document. Please refer to the gdb manual or gdb tutorials.

Analyzing the program flow is done best using the Basler pylon logging facility, which is explained in the Logging section. It is important to know that, if you don't set the GENICAM_LOG_CONFIG_V3_0 environment variable correctly, there will be no output. The amount of generated information is controlled best by defining the trace level using the BXAPI_TRACE_LEVEL environment variable.

Also compare the program flow of your BCON Adapter with the pre-built libBconAdapterSample.so that can be found in the samples folder.

Setting up the pylon BCON Adapter Library

The following sections describe the main parts of setting up a pylon BCON Adapter library.

Mandatory Functions of the pylon BCON Adapter library

The functions shown in the following section must be implemented by a BCON Adapter library. The code snippets are taken from the BCON Adapter library sample.

BconAdapterInit

The first call of the library is made to BconAdapterInit(). The caller passes a pointer to the tracing function. Store the pointer to the tracing function and use it to add traces to the pylon log until BconAdapterExit() returned. Initialize, or reinitialize, any ressource you need for this library.

{
SetExternalLogFunction(pTraceFunc);
return BCON_OK;
}

After the function BconAdapterExit() has been called, the BconAdapterInit() can be called again.

BconAdapterGetVersion

The BconAdapterGetVersion() BCON Adapter library function is called by pylon to check whether the BCON adapter library is built against a compatible version of the BCON Adapter API. In addition, you can return the version of the adapter library. The latter is only used for display.

unsigned int *apiMajorVersion,
unsigned int *apiMinorVersion,
unsigned int *adapterMajorVersion,
unsigned int *adapterMinorVersion)
{
assert(apiMajorVersion);
assert(apiMinorVersion);
assert(adapterMajorVersion);
assert(adapterMinorVersion);
apiMajorVersion = BCON_ADAPTER_API_MAJORVERSION;
apiMinorVersion = BCON_ADAPTER_API_MINORVERSION;
adapterMajorVersion = 1;
adapterMinorVersion = 0;
return BCON_OK;
}

BconAdapterExit

Before unloading the BCON Adapter library the BconAdapterExit() function is called. Release ressources that are not required anymore and clear the pointer to the tracing function received in the BconAdapterLibraryInit().

Do not call the tracing function after returning from BconAdapterExit().

Enumeration of pylon Devices

The BconAdapterStartDiscovery() BCON Adapter library function is called by pylon to search for devices or to provide static information about attached BCON devices. When the device configuration has been determined BconAdapterStartDiscovery() must call a callback function for each device to pass the device information to pylon. See BconAdapterEnumerator.h for detailed interface documentation.

Example:

Getting the device configuration:

// Get the I2C device configuration from environment variable BCON_ADAPTER_I2C_DEVICES
//
// Example for how to set BCON_ADAPTER_I2C_DEVICES for two devices:
//
// export BCON_ADAPTER_I2C_DEVICES="/dev/i2c-1:77 /dev/i2c-2:99"
//
// The two device identifiers /dev/i2c-1:77 and /dev/i2c-2:99 are separated by a blank.
// The first device identifier /dev/i2c-1:77 consists of the I2C bus to open /dev/i2c-1
// and the device address 77, the bus and address parts being separated by a colon.
// Analog for the second device identifier /dev/i2c-2:99.
char *env_config = getenv("BCON_ADAPTER_I2C_DEVICES");

Calling the callback for each device:

// Duplicate string for usage
char *config = strdup(env_config);
if (config == NULL)
{
LogOutput(TRACE_LEVEL_ERROR, "Error out of memory. ");
}
// Splitting the config string at the blanks yields the device identifier tokens.
// Call the callback function for each token.
char *token = strtok(config, " ");
do
{
LogOutput(TRACE_LEVEL_INFORMATION, "Current Token is _%s_", token);
if (callbackToBconAdapterUser != NULL)
{
BCONSTATUS callbackToBconAdapterUserStatus = callbackToBconAdapterUser(token, (userCtx));
if (!BCON_SUCCESS(callbackToBconAdapterUserStatus))
{
LogOutput(TRACE_LEVEL_ERROR, "Error calling BCON Adapter user callback in enumeration, status = 0x%08X", callbackToBconAdapterUserStatus);
returnCode = callbackToBconAdapterUserStatus;
}
}
token = strtok(NULL, " ");
}
while (token != NULL);

The code snippets above can be found in the MyBconAdapterEnumerator.c code sample.

Managing the I2C Connection

The BCON Adapter library manages the I2C connection. Before using the I2C bus of a device pylon opens the I2C bus connection by calling BconAdapterI2cOpenConnection(). This function returns the device address and the I2C bus handle, which are used to read data blocks from or write data blocks to the I2C bus calling BconAdapterI2cRead() and BconAdapterI2cWrite() respectively. When the I2C bus connection of the device is not used anymore it is closed by calling BconAdapterI2cCloseConnection(). See BconAdapterI2C.h for detailed interface documentation.

Example:

Opening the I2C connection of a camera device:

const char deviceId[], BconAdapterI2cBusHandle *phBus, uint32_t *pDeviceAddress)
{
// Copy string for usage
char devicePath[MAX_STRING_LENGTH] = { 0 };
strcpy(devicePath, deviceId);
// String is like "/dev/i2c-2:99", so find ':'
char *separator = (char*)strchr(devicePath, ':');
if (separator == NULL)
{
LogOutput(TRACE_LEVEL_ERROR, "Device ID incomplete.");
}
// Open device
separator[0] = '\0';
int fp = open(devicePath, O_RDWR);
if (fp <= 0)
{
LogOutput(TRACE_LEVEL_ERROR, "Could not open device.");
}
// Parse device address
int deviceAddress = atoi(separator + 1);
if ((deviceAddress < 0) || (deviceAddress >= 128))
{
LogOutput(TRACE_LEVEL_ERROR, "Error parsing device address, only 7-bit address allowed.");
close(deviceAddress);
}
// Return value device address
if (pDeviceAddress != NULL)
{
pDeviceAddress = deviceAddress;
}
// Return value bus handle
if (phBus != NULL)
{
phBus = (BconAdapterI2cBusHandle)(long)fp;
}
return BCON_OK;
}

Helper function used in the following:

// Helper function to convert BconAdapterI2cBusHandle to file descriptor (int)
static int getFd(BconAdapterI2cBusHandle arg)
{
return *((int*)(&arg));
}

Reading a block of data from the I2C bus:

EXTERN_C BCON_ADAPTER_API BCONSTATUS BCON_ADAPTER_CALL BconAdapterI2cRead(
uint32_t deviceAddress,
void *pData,
size_t sizeInBytes,
size_t *pBytesRead,
uint32_t timeout_ms)
{
(void)timeout_ms;
// Set target device address
if (ioctl(getFd(hBus), I2C_SLAVE, deviceAddress) < 0)
{
LogOutput(TRACE_LEVEL_ERROR, "Error setting target address.");
}
// Read from I2C
int bytesRead = read(getFd(hBus), pData, sizeInBytes);
if (bytesRead <= 0)
{
}
else
{
pBytesRead = bytesRead;
return BCON_OK;
}
}

Writing a block of data to the I2C bus:

EXTERN_C BCON_ADAPTER_API BCONSTATUS BCON_ADAPTER_CALL BconAdapterI2cWrite(
uint32_t deviceAddress,
const void *pData,
size_t sizeInBytes,
uint32_t timeout_ms)
{
(void)timeout_ms;
// Set target device address
if (ioctl(getFd(hBus), I2C_SLAVE, deviceAddress) < 0)
{
LogOutput(TRACE_LEVEL_ERROR, "Error setting target address.");
}
// Write to I2C
// Note: The BCON camera uses clock stretching.
// The used I2C master hardware must support clock stretching properly.
int bytesWritten = write(getFd(hBus), pData, sizeInBytes);
if (bytesWritten != sizeInBytes)
{
}
else
{
return BCON_OK;
}
}

Closing the I2C connection of a camera device:

BconAdapterI2cBusHandle hBus, uint32_t deviceAddress)
{
(void)deviceAddress;
// Close file descriptor
int ret = close(getFd(hBus));
if (ret != 0)
{
LogOutput(TRACE_LEVEL_ERROR, "Could not close device.");
}
return BCON_OK;
}

The code snippets above can be found in the MyBconAdapterI2CConnection.c code sample.

Logging

Basler pylon uses the GenICam logging facility which is based on log4cpp, a log4j port. This allows a very detailed configuration with multiple outputs and a hierarchy of logging categories. A standard configuration can be found in the DebugLoggingUnix.properties file. This is provided in order to help analyzing problems with customer scenarios. To enable logging the GENICAM_LOG_CONFIG_V3_0 environment variable must hold the path of a configuration file.

GENICAM_LOG_CONFIG_V3_0=/opt/pylon5/share/pylon/log/config/DebugLoggingUnix.properties

In this file the base logging level is set to DEBUG for the rootCategory, which is inherited by all subcategories. The GenApi sub-category is restricted to ERROR level. Consequently, you only receive error messages of the GenApi, but full debug output from all other modules in your application.

All output is directed to so-called appenders, here into a "/tmp/pylonLog.txt" file. Each instance of an appender has got a name, here File, that is used to attach the appender to a category. Other appender types are possible, e.g. the console appender.

# enable everything on root
log4j.rootCategory=DEBUG, File
# now disable some stuff we don't want to see
log4j.category.GenApi=ERROR
# This appender writes to a /tmp/pylonLog.txt file
log4j.appender.File=org.apache.log4j.FileAppender
log4j.appender.File.fileName=/tmp/pylonLog.txt

This configuration may produce too much output. If you want to limit the output in the logfile, you can change the BCON category to WARN level for instance. Because this limits also the output of all sub-categories, you may change the level for the BxAdapter again to get more log output from the BCON Adapter.

log4j.category.Bcon=WARN
log4j.category.Bcon.BxAdapter=DEBUG

At runtime many BCON log messages are only produced when the log level is configured accordingly. With the BXAPI_TRACE_LEVEL environment variable the maximum level is determined. All traces with a lower or equal log level are included. The default value is currently TRACE_LEVEL_ERROR.

BXAPI_TRACE_LEVEL=20

The possible values are listed below.

TRACE_LEVEL_FATAL10
TRACE_LEVEL_ERROR20
TRACE_LEVEL_WARNING30
TRACE_LEVEL_INFORMATION40
TRACE_LEVEL_VERBOSE50
TRACE_LEVEL_DEBUG60

At runtime log messages are emitted by calling the BconTraceFunc in the code. The first parameter determines the log respectively trace level TRACE_LEVEL_ERROR. A format string is the third parameter followed by a variable length list of parameter. The standard printf rules apply. The BconTraceFunc function is passed to the BCON Adapter library with the BconAdapterInit call. In the sample code the LogOutput function helps to perform these calls. The following snippet shows how it is used.

BconAdapterI2cBusHandle hBus, uint32_t deviceAddress)
{
(void)deviceAddress;
// Close file descriptor
int ret = close(getFd(hBus));
if (ret != 0)
{
LogOutput(TRACE_LEVEL_ERROR, "Could not close device.");
}
return BCON_OK;
}

Error Handling

All errors are returned as a 32-bit value of the BCONSTATUS type. The standard codes BCON_OK and BCON_E_OPERATION_FAILED used in the snippet above are defined in the BconAdapterDefines.h file. If custom return codes are required, use values out of the following ranges.

0xE2208000 - 0xE220FFFFfor errors
0x22208000 - 0x2220FFFFfor success

Stream Interface

The BconAdapterStreamXXX() functions define the BCON adapter stream interface. They are described in BconAdapterStream.h.

The current MyBconAdapter Sample sample code does not include streaming.

A sample can be found in the Basler PowerPack for Embedded Vision available at http://www.baslerweb.com.


BCONAdapterAPI 3.0
© 2016-2017 Basler AG (Tue May 30 2017 17:24:55)