Yet Another Calibration Protocol
The YACP project is intended as an open protocol for the calibration of embedded projects. It is an alternative to more complex protocols such as CAN Calibration Protocol (CCP) and XCP though much more simple.
The project is broken into two components, an API for embedded projects and tools for interacting with embedded devices using the YACP protocol. Although any communication medium should be usable with YACP, currently the only supported medium is CAN bus. YACP is written in c and should support any c or c++ projects.
YACP has three main entities:
- Measurements - Data is requested from a device and is returned to the requestor. Used for inspecting the current state and data in a device for debugging purposes or logging.
- Settings - Calibration data is configured on a device and then persisted in some form of non-volatile memory. The stored settings are loaded each time the device is powered on.
- Overrides - Data and application behavior can be changed by overriding the real data with an override value. Useful for bench testing devices.
While some tools start with a model or firmware and extract the calibration entities from the build files, YACP turns this concept on its head. A firmware designer will first define the project measurements, settings, and overrides in a def (JSON) file and from this project definition code will be generated for setting up the calibration structures in the firmware. This approach is meant to cleanly divide the processes of design and implementation.
Workflow Example
- Add or modify measurements, settings and overrides in your project-def.json file
- IMPORTANT Increment the 'version' setting in project-def.json if you have modified the settings section. Failure to do so will mean your saved settings will not match the cal structure.
- Generate cal.h and cal.c files using YACPGen.py command line tool
- Move cal.h and cal.c into your source tree and recompile your project
- Open YACPGUI and connect to a device
- update your settings if needed, save your calibration to a project-cal.csv file and save the settings to NVM
To use YACP in your project you need the API files as well as driver code for your platform and architecture. The drivers folder contains the existing drivers but new drivers can be created easily provided your platform supports sending/receiving CAN messages and storing/reading from non-volatile memory one byte at a time. See the demo project for the Teensy platform for a full example.
Integration Steps
- Add the API files to your project: yacp.h, yacp_api.h, yacp_funs.c
- Add a driver to your project in the same location as the API files: yacp_driver_xxx.c
- Create a project-def.json file for your project and add measurements, settings, and overrides as desired
- Generate the cal.c and cal.h files with YACPGen.py and add them to your project next to the API files
- Add the required include and function calls to your project
// Include the calibration struct definitions generated by the YACP tools.
#include "cal.h"
// The calibration struct is declared in cal.c
extern calibration cal;
const uint8_t yacp_product_firmware_version = FIRMWARE_VERSION; // The firmware version for the project, informational
const uint8_t yacp_product_id = PRODUCT_ID; // Used to filter different YACP devices on a CAN bus
void project_init() {
...
// Load default settings and saved settings from NVM
// into the cal structs
yacp_init();
...
}
void project_tick() {
...
// Periodically check for new YACP CAN messages
yacp_can_recv();
...
}
The calibration itself is simply a struct containing all of your project measurements, settings, and overrides. Measurements are meant to be updated by your project as data/state changes. Settings and overrides are meant to be read by used by your project, read only.
// Measurements can be updated anywhere in the project code at any time
cal.measurements.some_var = 254;
// Each override has a status of overridden or passthrough.
// If the status is set to overridden then use the value set in the override,
// otherwise use your application logic.
if (cal.overrides.some_override.status == CAL_OVERRIDDEN)
do_something(cal.overrides.some_override.value.i32); // 32 bit signed value
else
do_something(some_internal_var);
// Settings are loaded from NVM on startup and can be used as device configuration
set_output(cal.settings.led_output_pin, 1);
The project def file contains the names, types, and location of each measurement, setting, and override in the calibration. This file is used to generate the cal structure in the project code as well as informs the YACPGUI of the available objects in a remote device. The JSON file can be named anything, but for convention a project name followed by -def.json is recommended.
Minimal project-def.json contents
{
"measurements": [
],
"settings": [
{
"name": "device_id",
"type": "uint8",
"default": "1"
},
{
"name": "revision",
"type": "uint8",
"default": "1"
},
],
"overrides": [
]
}
At a minimum, the def file must contain settings for storing the device_id of a device and the revision of the settings section. Any time that the order, contents or types of the settings section are modified the revision MUST BE INCREMENTED in the def file.
The available types are:
- uint8
- uint16
- uint32
- int8
- int16
- int32
- float
The settings have a default value which is used if the NVM has corrupted data or the revision number between the data stored in the NVM does not match the revision stored in the firmware. Measurements and override values do not have default values.
Launch the GUI and connect to a USB to CAN adaptor such as PCAN, IXXAT, and Kvaser. Next open a project def file using the File menu so that the GUI knows what objects are available to work with.
A saved cal (CSV) file can be inspected offline (without connecting to a device) by opening a cal file using the File menu.
Hit the Scan for targets button and the combo box will be updated with the device IDs of any devices on the bus that use the YACP protocol. It is important that if multiple devices are on the BUS that they have been configured to use different IDs. This can be done either by using a different project-def.json file for each device with a different device_id default value in each file, or by using the same default value and bringing the devices online one at a time to be calibrated during which time the device_id can be changed in the GUI.
Select the desired device from the combobox and click Connect. All of the measurements, settings, and overrides will be read from the device and displayed in the GUI. The measurements will continually refreshed at a rate of one measurement every 20ms.
Settings can be changed by double-clicking a cell in the Value column and changing the value. Once Enter is pressed or the mouse is clicked outside the cell the setting will be pushed to the device. At this point the setting is not updated in the NVM of the device. To persist the new calibration click the Persist and Save Cal button. This will persist all of the settings values from the calibration structure into NVM and update the CRC checksum. You will be prompted to save the settings to a cal (CSV) file if desired.
Overridden values can be set in the Override section similar to settings, but they will not take effect until the status is changed from Passthrough to Overridden provided the firmware honors this rule. If the device is reset, all overridden values and status will be reset.
If the settings section has been modified in the project def file, follow the Workflow Example steps above to modify your project firmware and flash your device. When the device is next powered on the saved settings will be erased since the revision of the firmware has changed and no longer matches the NVM revision. In order to restore your calibration follow these steps.
- Scan and connect to your device. This will result in the default values showing for the device settings.
- Open a saved Cal CSV file from the File menu. The values will be loaded into the GUI and pushed to your device.
- Update values for any new or changed settings there were not in the saved Cal file.
- Click the Persist and Save Cal button to store the new settings into NVM so they will be loaded on next startup instead of the default values