Sensor Fusion Library 0.6.1
Orientation sensing for Espressif (ESP32, ESP8266) processors
Loading...
Searching...
No Matches
calibration_storage.cc
Go to the documentation of this file.
1
2/*
3 * Copyright (c) 2020, Bjarne Hansen
4 * All rights reserved.
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 */
8
15#include <stdio.h>
16
17#include <EEPROM.h>
18
19#include "sensor_fusion.h"
20#include "calibration_storage.h"
21#include "debug_print.h"
22
23#define CALIBRATION_STORAGE_SIZE_BYTES 256
24#define CALIBRATION_BUF_MAGNETIC_START 0
25#define CALIBRATION_BUF_MAGNETIC_HDR_SIZE 4
26#define CALIBRATION_BUF_MAGNETIC_HDR_MAGIC 0x12345678
27#define CALIBRATION_BUF_MAGNETIC_VAL_SIZE 64
28#define CALIBRATION_BUF_MAGNETIC_TOT_SIZE (CALIBRATION_BUF_MAGNETIC_HDR_SIZE + CALIBRATION_BUF_MAGNETIC_VAL_SIZE)
29#define CALIBRATION_BUF_GYRO_START (CALIBRATION_BUF_MAGNETIC_TOT_SIZE)
30#define CALIBRATION_BUF_GYRO_HDR_SIZE 4
31#define CALIBRATION_BUF_GYRO_HDR_MAGIC 0x12345678
32#define CALIBRATION_BUF_GYRO_VAL_SIZE 12
33#define CALIBRATION_BUF_GYRO_TOT_SIZE (CALIBRATION_BUF_GYRO_HDR_SIZE + CALIBRATION_BUF_GYRO_VAL_SIZE)
34#define CALIBRATION_BUF_ACCEL_START (CALIBRATION_BUF_MAGNETIC_TOT_SIZE + CALIBRATION_BUF_GYRO_TOT_SIZE)
35#define CALIBRATION_BUF_ACCEL_HDR_SIZE 4
36#define CALIBRATION_BUF_ACCEL_HDR_MAGIC 0x12345678
37#define CALIBRATION_BUF_ACCEL_VAL_SIZE 84
38#define CALIBRATION_BUF_ACCEL_TOT_SIZE (CALIBRATION_BUF_ACCEL_HDR_SIZE + CALIBRATION_BUF_ACCEL_VAL_SIZE)
39#define CALIBRATION_NO_MAGIC 0xdeadbeef
40#if CALIBRATION_STORAGE_SIZE_BYTES < (CALIBRATION_BUF_MAGNETIC_TOT_SIZE + CALIBRATION_BUF_GYRO_TOT_SIZE + CALIBRATION_BUF_ACCEL_TOT_SIZE)
41 #error insufficient space allocated for calibration buffer
42#endif
43
44#ifdef ESP8266
45// define a replacement for EEPROM.readBytes(), which is only available in the
46// ESP32 library
47void EepromReadBytes(int start_loc, void *buffer, int num_bytes);
48void EepromReadBytes(int start_loc, void *buffer, int num_bytes) {
49 uint8_t *ptr = (uint8_t *)buffer;
50 for (int i = 0; i < num_bytes; i++) {
51 ptr[i] = EEPROM.read(i + start_loc); //read single bytes at a time
52 }
53 return; // EEPROM.read() doesn't return errors, so neither do we
54}//end EepromReadBytes()
55#endif
56
57//fetch the Magnetic calibration values from non-volatile memory.
58//If cal values are unavailable, returns false. If successful, returns true.
59bool GetMagCalibrationFromNVM( float *cal_values ) {
60 if( NULL == cal_values ) {
61 return false;
62 }
63#if F_USING_MAG
64 //header of each calibration block type contains
65 //magic value if valid calibration has been previously stored.
66 EEPROM.begin(
67 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
68 //check for the expected header - if not found, then calibration invalid
69 uint8_t buf_magic[CALIBRATION_BUF_MAGNETIC_HDR_SIZE];
70#ifdef ESP8266
71 EepromReadBytes(CALIBRATION_BUF_MAGNETIC_START, buf_magic,
72 CALIBRATION_BUF_MAGNETIC_HDR_SIZE);
73#endif
74#ifdef ESP32
75 EEPROM.readBytes(CALIBRATION_BUF_MAGNETIC_START, buf_magic,
76 CALIBRATION_BUF_MAGNETIC_HDR_SIZE);
77#endif
78 uint32_t magic_value = CALIBRATION_BUF_MAGNETIC_HDR_MAGIC;
79 uint8_t *pSrc = (uint8_t *)&magic_value;
80 for (int i = 0; i < CALIBRATION_BUF_MAGNETIC_HDR_SIZE; i++) {
81 if( *pSrc != buf_magic[i] ) {
82 return false;
83 }
84 ++pSrc;
85 }
86 //read the valid calibration into provided destination
87#ifdef ESP8266
88 EepromReadBytes(
89 CALIBRATION_BUF_MAGNETIC_START + CALIBRATION_BUF_MAGNETIC_HDR_SIZE,
90 cal_values, CALIBRATION_BUF_MAGNETIC_VAL_SIZE);
91#endif
92#ifdef ESP32
93 EEPROM.readBytes(
94 CALIBRATION_BUF_MAGNETIC_START + CALIBRATION_BUF_MAGNETIC_HDR_SIZE,
95 cal_values, CALIBRATION_BUF_MAGNETIC_VAL_SIZE);
96#endif
97 EEPROM.end();
98 return true;
99#endif // if F_USING_MAG
100 return false;
101}//end GetMagCalibrationFromNVM()
102
103bool GetGyroCalibrationFromNVM( float *cal_values ) {
104 if( NULL == cal_values ) {
105 return false;
106 }
107#if F_USING_GYRO
108 //header of each calibration block type contains
109 //magic value if valid calibration has been previously stored.
110 EEPROM.begin(
111 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
112 //check for the expected header - if not found, then calibration invalid
113 uint8_t buf_magic[CALIBRATION_BUF_GYRO_HDR_SIZE];
114#ifdef ESP8266
115 EepromReadBytes(CALIBRATION_BUF_GYRO_START, buf_magic,
116 CALIBRATION_BUF_GYRO_HDR_SIZE);
117#endif
118#ifdef ESP32
119 EEPROM.readBytes(CALIBRATION_BUF_GYRO_START, buf_magic,
120 CALIBRATION_BUF_GYRO_HDR_SIZE);
121#endif
122 uint32_t magic_value = CALIBRATION_BUF_GYRO_HDR_MAGIC;
123 uint8_t *pSrc = (uint8_t *)&magic_value;
124 for (int i = 0; i < CALIBRATION_BUF_GYRO_HDR_SIZE; i++) {
125 if( *pSrc != buf_magic[i] ) {
126 return false;
127 }
128 ++pSrc;
129 }
130 //read the valid calibration into provided destination
131#ifdef ESP8266
132 EepromReadBytes(CALIBRATION_BUF_GYRO_START + CALIBRATION_BUF_GYRO_HDR_SIZE,
133 cal_values, CALIBRATION_BUF_GYRO_VAL_SIZE);
134#endif
135#ifdef ESP32
136 EEPROM.readBytes(CALIBRATION_BUF_GYRO_START + CALIBRATION_BUF_GYRO_HDR_SIZE,
137 cal_values, CALIBRATION_BUF_GYRO_VAL_SIZE);
138#endif
139 EEPROM.end();
140 return true;
141#endif // if F_USING_GYRO
142 return false;
143}//end GetGyroCalibrationFromNVM()
144
145bool GetAccelCalibrationFromNVM( float *cal_values ) {
146 if( NULL == cal_values ) {
147 return false;
148 }
149#if F_USING_ACCEL
150 //header of each calibration block type contains
151 //magic value if valid calibration has been previously stored.
152 EEPROM.begin(
153 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
154
155 //check for the expected header - if not found, then calibration invalid
156 uint8_t buf_magic[CALIBRATION_BUF_ACCEL_HDR_SIZE];
157#ifdef ESP8266
158 EepromReadBytes(CALIBRATION_BUF_ACCEL_START, buf_magic,
159 CALIBRATION_BUF_ACCEL_HDR_SIZE);
160#endif
161#ifdef ESP32
162 EEPROM.readBytes(CALIBRATION_BUF_ACCEL_START, buf_magic,
163 CALIBRATION_BUF_ACCEL_HDR_SIZE);
164#endif
165 uint32_t magic_value = CALIBRATION_BUF_ACCEL_HDR_MAGIC;
166 uint8_t *pSrc = (uint8_t *)&magic_value;
167 for (int i = 0; i < CALIBRATION_BUF_ACCEL_HDR_SIZE; i++) {
168 if( *pSrc != buf_magic[i] ) {
169 return false;
170 }
171 ++pSrc;
172 }
173 //read the valid calibration into provided destination
174#ifdef ESP8266
175 EepromReadBytes(
176 CALIBRATION_BUF_ACCEL_START + CALIBRATION_BUF_ACCEL_HDR_SIZE,
177 cal_values, CALIBRATION_BUF_ACCEL_VAL_SIZE);
178#endif
179#ifdef ESP32
180 EEPROM.readBytes(
181 CALIBRATION_BUF_ACCEL_START + CALIBRATION_BUF_ACCEL_HDR_SIZE,
182 cal_values, CALIBRATION_BUF_ACCEL_VAL_SIZE);
183#endif
184 EEPROM.end();
185 return true;
186#endif // if F_USING_ACCEL
187 return false;
188}//end GetAccelCalibrationFromNVM()
189
190
191void SaveMagCalibrationToNVM(SensorFusionGlobals *sfg)
192{
193#if F_USING_MAG
194 uint8_t *pSrc, *pDst; // scratch pointers
195 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
196
197 EEPROM.begin(
198 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
199 buf_NVM = EEPROM.getDataPtr();
200
201 //modify magnetic, leave existing gyro and accelerometer calibrations in buffer
202 pDst = buf_NVM + CALIBRATION_BUF_MAGNETIC_START;
203
204 // write buffer with magnetic header + calibration in bytes 0 to 67
205 //bytes[0-3]: four byte header denoting magnetic calibration present
206 uint32_t itmp32 = CALIBRATION_BUF_MAGNETIC_HDR_MAGIC;
207 pSrc = (uint8_t *)&itmp32;
208 for (int i = 0; i < CALIBRATION_BUF_MAGNETIC_HDR_SIZE; i++) {
209 *pDst = *pSrc;
210 ++pDst;
211 ++pSrc;
212 }
213 //bytes[4-67]: magnetic calibration: 15x float + 1x int32 subtotal 64 bytes
214 pSrc = (uint8_t *)&(sfg->MagCal);
215 for (int i = 0; i < CALIBRATION_BUF_MAGNETIC_VAL_SIZE; i++) {
216 *pDst = *pSrc;
217 ++pDst;
218 ++pSrc;
219 }
220 // write the whole buffer contents to NVM
221 if( ! EEPROM.commit() ) {
222 debug_log("EEPROM write mag cal failed\n");
223 }
224 EEPROM.end();
225#endif // if F_USING_MAG
226 return;
227}
228
229void SaveGyroCalibrationToNVM(SensorFusionGlobals *sfg)
230{
231#if F_USING_GYRO && (F_9DOF_GBY_KALMAN || F_6DOF_GY_KALMAN)
232 uint8_t *pSrc, *pDst; // scratch pointers
233 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
234
235 EEPROM.begin(
236 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
237 buf_NVM = EEPROM.getDataPtr();
238
239 //modify gyro, leave existing magnetic and accelerometer calibrations in buffer
240 pDst = buf_NVM + CALIBRATION_BUF_GYRO_START;
241
242 // write buffer with gyro header + calibration in bytes 0 to 15
243 //bytes[0-3]: four byte header denoting gyro calibration present
244 uint32_t itmp32 = CALIBRATION_BUF_GYRO_HDR_MAGIC;
245 pSrc = (uint8_t *)&itmp32;
246 for (int i = 0; i < CALIBRATION_BUF_GYRO_HDR_SIZE; i++) {
247 *pDst = *pSrc;
248 ++pDst;
249 ++pSrc;
250 }
251 //bytes [4-15]: 3 gyro offset floats sub totalling 12 bytes
252#if F_9DOF_GBY_KALMAN
253 pSrc = (uint8_t *) sfg->SV_9DOF_GBY_KALMAN.fbPl;
254#elif F_6DOF_GY_KALMAN
255 pSrc = (uint8 *) sfg->SV_6DOF_GY_KALMAN.fbPl;
256#endif
257 pSrc = (uint8_t *)&(sfg->MagCal);
258 for (int i = 0; i < CALIBRATION_BUF_GYRO_VAL_SIZE; i++) {
259 *pDst = *pSrc;
260 ++pDst;
261 ++pSrc;
262 }
263 // write the whole buffer contents to NVM
264 if( ! EEPROM.commit() ) {
265 debug_log("EEPROM write gyro cal failed\n");
266 }
267 EEPROM.end();
268#endif
269 return;
270}
271
272void SaveAccelCalibrationToNVM(SensorFusionGlobals *sfg)
273{
274#if F_USING_ACCEL
275 uint8_t *pSrc, *pDst; // scratch pointers
276 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
277
278 EEPROM.begin(
279 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
280 buf_NVM = EEPROM.getDataPtr();
281
282 //modify accel, leave existing magnetic and gyro calibrations in buffer
283 pDst = buf_NVM + CALIBRATION_BUF_ACCEL_START;
284
285 // write buffer with accel header + calibration in bytes 0 to 87
286 //bytes[0-3]: four byte header denoting gyro calibration present
287 uint32_t itmp32 = CALIBRATION_BUF_ACCEL_HDR_MAGIC;
288 pSrc = (uint8_t *)&itmp32;
289 for (int i = 0; i < CALIBRATION_BUF_ACCEL_HDR_SIZE; i++) {
290 *pDst = *pSrc;
291 ++pDst;
292 ++pSrc;
293 }
294 //bytes [4-87]: 21 precision accelerometer calibration floats subtotalling 84 bytes
295 pSrc = (uint8_t *) &(sfg->AccelCal);
296 for (int i = 0; i < CALIBRATION_BUF_ACCEL_VAL_SIZE; i++) {
297 *pDst = *pSrc;
298 ++pDst;
299 ++pSrc;
300 }
301 // write the whole buffer contents to NVM
302 if( ! EEPROM.commit() ) {
303 debug_log("EEPROM write accel cal failed\n");
304 }
305 EEPROM.end();
306#endif
307 return;
308}
309
310void EraseMagCalibrationFromNVM(void)
311{
312 uint8_t *pSrc, *pDst; // scratch pointers
313 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
314
315 EEPROM.begin(
316 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
317 buf_NVM = EEPROM.getDataPtr();
318
319 pDst = buf_NVM + CALIBRATION_BUF_MAGNETIC_START;
320 //bytes[0-3]: four byte header denoting magnetic calibration present
321 uint32_t itmp32 = CALIBRATION_NO_MAGIC;
322 pSrc = (uint8_t *)&itmp32;
323 for (int i = 0; i < CALIBRATION_BUF_MAGNETIC_HDR_SIZE; i++) {
324 *pDst = *pSrc;
325 ++pDst;
326 ++pSrc;
327 }
328 // write the whole buffer contents to NVM
329 if( ! EEPROM.commit() ) {
330 debug_log("EEPROM clear magnetic cal failed\n");
331 }
332 EEPROM.end();
333
334 return;
335}
336
337void EraseGyroCalibrationFromNVM(void)
338{
339 uint8_t *pSrc, *pDst; // scratch pointers
340 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
341
342 EEPROM.begin(
343 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
344 buf_NVM = EEPROM.getDataPtr();
345
346 pDst = buf_NVM + CALIBRATION_BUF_GYRO_START;
347 //bytes[0-3]: four byte header denoting magnetic calibration present
348 uint32_t itmp32 = CALIBRATION_NO_MAGIC;
349 pSrc = (uint8_t *)&itmp32;
350 for (int i = 0; i < CALIBRATION_BUF_GYRO_HDR_SIZE; i++) {
351 *pDst = *pSrc;
352 ++pDst;
353 ++pSrc;
354 }
355 // write the whole buffer contents to NVM
356 if( ! EEPROM.commit() ) {
357 debug_log("EEPROM clear gyro cal failed\n");
358 }
359 EEPROM.end();
360
361 return;
362}
363
364void EraseAccelCalibrationFromNVM(void)
365{
366 uint8_t *pSrc, *pDst; // scratch pointers
367 uint8_t *buf_NVM = NULL; //pointer into the non-volatile memory buffer
368
369 EEPROM.begin(
370 CALIBRATION_STORAGE_SIZE_BYTES); // access chunk of emulated EEPROM
371 buf_NVM = EEPROM.getDataPtr();
372
373 pDst = buf_NVM + CALIBRATION_BUF_ACCEL_START;
374 //bytes[0-3]: four byte header denoting magnetic calibration present
375 uint32_t itmp32 = CALIBRATION_NO_MAGIC;
376 pSrc = (uint8_t *)&itmp32;
377 for (int i = 0; i < CALIBRATION_BUF_ACCEL_HDR_SIZE; i++) {
378 *pDst = *pSrc;
379 ++pDst;
380 ++pSrc;
381 }
382 // write the whole buffer contents to NVM
383 if( ! EEPROM.commit() ) {
384 debug_log("EEPROM clear magnetic cal failed\n");
385 }
386 EEPROM.end();
387
388 return;
389}
Provides functions to store calibration to NVM, which on ESP devices is provided by EEPROM.
defines function debug_print() that outputs to serial port Can disable these prints by compiling with...
The sensor_fusion.h file implements the top level programming interface.
The top level fusion structure.
struct MagCalibration MagCal
mag cal storage