element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • About Us
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Test & Tools
  • Technologies
  • More
Test & Tools
Documents Programmable Electronic Load - Calibration Data in Flash
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Test & Tools to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 24 Dec 2017 11:24 AM Date Created
  • Last Updated Last Updated: 16 Sep 2018 10:21 AM
  • Views 1014 views
  • Likes 6 likes
  • Comments 4 comments
Related
Recommended

Programmable Electronic Load - Calibration Data in Flash

This blog documents explains how persistent calibration data is managed in the electronic load that Robert Peter Oakes, jc2048 and Jan Cumps are designing.

image

This post will again be firmware heavy. It explains how calibration data is structured and managed.

 

Calibration data has to be kept, also when the instrument is powered down. The MSP432 we're using has user Flash for such purposes.

The MSP43x drivers have functions to program it.

 

 

Calibration Structure

 

All calibration data is held in a structure. We'll do a read/write of the flash for that complete structure every time.

 

typedef struct CalibrationData {
    char code[6];
    uint32_t version;
    float temperature_threshold;  // todo convert to the ADC 16 bit value in stead of float
    float sense_voltage_read_multiplier;
    float sense_voltage_read_offset;
    float current_read_multiplier;
    float current_read_offset;
    float current_write_multiplier;
    float current_write_offset;
} CalibrationData;

#define CALIBRATION_DATA_SIZE (sizeof(CalibrationData))

 

The version is used for compatibility with later extensions. It will be set - or overwritten - when callibration data is saved.

The read function can check the version and see if it has to do compatibility functions if the data in the Flash is created by an older firmware version.

 

Writing and reading the data is done in a helper function. They are in a demo state now, to check if I can get this working.

Check the MSP432 datasheet for the relevant Flash memory area.

 

void calibrationRead() {
    calibrationInit();
    EEPROMRead((uint32_t *)&_CalibrationData, (uint32_t)(CALIBRATION_START),
               (uint32_t)CALIBRATION_DATA_SIZE);
    if(strcmp(_CalibrationData.code, "eload")) { // check if code == "eload"s
        calibrationErase();
    }
    // compatibility with older versions of calibration structure
    _calibrationStructureBackwardCompatibility();
}

 

 

Here's RIGOL's calibration guide for a power supply. We could use the same command structure:

:CALibration:Start ...
:CALibration:Clear ...
:CALibration:Set ...
:CALibration:MEAS ...
:CALibration:End  ....

 

This post focuses on the firmware development of the storage mechanism. The actual SCPI commands and calibration/configuration processes are documented in this post: Programmable Electronic Load - Calibration Steps.

 

Manage the Calibration Record Version

 

Detection a previous version is needed when updating firmware. We want to retain any calibration settings stored in the past. Because the new firmware my introduce new fields, there are actions to do.

All existing fields from previous versions are already initialised, or set by the user with calls to the CALIbrate: functions. We don't interfere with them.

But any new field has random data in it: whatever the bits happens to be in the part of FLASH beyond where the existing persistent calibration values are stored.

 

When a new version of the firmware extends the calibration record, it could (Murphy: will) contain garbage.

Every new version of firmware should take care to initialise any field that is added with a reasonable value, if it detects that the stored calibration record did not have this field.

 

The code has two mechanisms to do that.

First, it detects if there is a valid calibration record. It does that by checking if the signature of the persistent calibration area is valid. It checks if that area starts with "eload".

If that is not the case, the firmware decides that you never stored any calibration data, and fully initialises the record. All fields get a default value.

 

    EEPROMRead((uint32_t *)&_CalibrationData, (uint32_t)(CALIBRATION_START),
               (uint32_t)CALIBRATION_DATA_SIZE);
    if(strcmp(_CalibrationData.code, "eload")) { // check if code == "eload"s
        calibrationErase();
    }

 

bool calibrationErase() {
    bool bRetVal = false;
    if (_bCalibrationActive) {
        strcpy(_CalibrationData.code, "eload");
        _CalibrationData.version = CALIBRATION_DATA_VERSION;
        _CalibrationData.temperature_threshold = 0.246244535;
        _CalibrationData.sense_voltage_read_multiplier = 0.33;
        _CalibrationData.sense_voltage_read_offset = 0.0;
        _CalibrationData.current_read_multiplier = 6.8;
        _CalibrationData.current_read_offset = 0.0;
        _CalibrationData.current_write_multiplier = 0.000116;
        _CalibrationData.current_write_offset = 0.008;
        _CalibrationData.sense_resistance = 0.05; //  Ohm
        bRetVal = true;
    }
    return (bRetVal);
}

 

If it detects that there is a valid calibration record in the persistent storage, it checks for the version stamp (an unsigned integer, starting with 1U for the initial firmware version when the project started) of that record.

If that stamp is not lower than the stamp stored in the firmware, nothing happens. We know that each field in the record that we will use has been initialised or set.

If the stamp is lower, we know that the new firmware introduces additional fields to he calibration record. In that case, action is required.

For each field added to the record, a reasonable value is defaulted (but not yet saved) at the startup of the device.

It allows the device to run with reasonable, uncalibrated, values.

 

void _calibrationStructureBackwardCompatibility() {
    // compatibility with older versions of calibration structure
    if(_CalibrationData.version < CALIBRATION_DATA_VERSION) {
        if(_CalibrationData.version < 2U) { // initialise fields added in version 2 of the calibration structure
            _CalibrationData.sense_resistance = 0.05;
        }
    }
}

 

The user can then enter calibration  mode and replace the suggested, reasonable, values with effective values for her instrument.

When the user completely runs the calibration cycle (including calling CALI:END), the data will be stored into persistent storage.That will also stamp the record with the latest calibration data version number.

 

void calibrationWrite() {
    _CalibrationData.version = CALIBRATION_DATA_VERSION; // writing calibration data will always set the version to the latest
    strcpy(_CalibrationData.code, "eload");
    // ..

 

 

On the next run, the code will detect that the calibration data version matches the one stored in firmware. It will then use the stored values instead of providing reasonable defaults.

  • rtos
  • flash
  • msp432
  • launchpad
  • calibration
  • Share
  • History
  • More
  • Cancel
  • Sign in to reply

Top Comments

  • DAB
    DAB over 7 years ago +2
    You are making good progress. DAB
  • Jan Cumps
    Jan Cumps over 7 years ago +1
    I've added a section in the linker command file, so that the linker knows that that area is reserved and should not be used as an area for firmware program or data. The very last main Flash area is now…
  • Jan Cumps
    Jan Cumps over 7 years ago +1
    adapted to the SimpleLink TI-RTOS release. The persistent storage API has been simplified *a lot*
  • Jan Cumps
    Jan Cumps over 7 years ago

    I'm removing pre-SimpleLink documentation because it takes more than half of the document and isn't relevant anymore.

    To check out how it was working, review version 10 of this document on element14: https://www.element14.com/community/docs/DOC-88364/version/10

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago

    adapted to the SimpleLink TI-RTOS release. The persistent storage API has been simplified *a lot*

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • Jan Cumps
    Jan Cumps over 7 years ago

    I've added a section in the linker command file, so that the linker knows that that area is reserved and should not be used as an area for firmware program or data.

    The very last main Flash area is now reserved for the calibration and configuration info.

    • Cancel
    • Vote Up +1 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 7 years ago

    You are making good progress.

     

    DAB

    • Cancel
    • Vote Up +2 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube