27#include "sensesp/sensors/sensor.h"
28#include "sensesp/signalk/signalk_output.h"
29#include "sensesp/system/lambda_consumer.h"
30#include "sensesp_app_builder.h"
36#include "sensesp/sensors/digital_input.h"
37#include "sensesp/transforms/debounce.h"
46#include "sensesp/transforms/angle_correction.h"
47#include "sensesp/transforms/curveinterpolator.h"
53#include "sensesp/signalk/signalk_types.h"
59#include "sensesp/transforms/linear.h"
69#define BOARD_ACCEL_MAG_I2C_ADDR (0x1F)
70#define BOARD_GYRO_I2C_ADDR (0x21)
71#define PIN_I2C_SDA (23)
72#define PIN_I2C_SCL (25)
73#define PIN_SWITCH_CAL_SAVE (32)
74#define SWITCH_ACTIVE_STATE (0)
79#define ORIENTATION_REPORTING_INTERVAL_MS (100)
81using namespace sensesp;
90 : CurveInterpolator( NULL, config_path) {
124 SetupLogging(ESP_LOG_INFO);
133 SensESPAppBuilder builder;
134 sensesp_app = (&builder)
136 ->set_hostname(
"eCompass")
144 ->enable_uptime_sensor()
145 ->enable_ip_address_sensor()
146 ->enable_free_mem_sensor()
147 ->enable_system_hz_sensor()
173 const char* kSKPathHeadingCompass =
"navigation.headingCompass";
174 const char* kSKPathHeadingMagnetic =
"navigation.headingMagnetic";
175 const char* kSKPathAttitude =
"navigation.attitude";
182 const char* kSKPathTurnRate =
"navigation.rateOfTurn";
183 const char* kSKPathRollRate =
"navigation.rateOfRoll";
184 const char* kSKPathPitchRate =
"navigation.rateOfPitch";
189 const char* kSKPathTemperature =
190 "environment.inside.ecompass.temperature";
194 const char* kSKPathAccelX =
"sensors.accelerometer.accel_x";
195 const char* kSKPathAccelY =
"sensors.accelerometer.accel_y";
196 const char* kSKPathAccelZ =
"sensors.accelerometer.accel_z";
207 const char* kSKPathMagFit =
"orientation.calibration.magfit";
208 const char* kSKPathMagFitTrial =
"orientation.calibration.magfittrial";
209 const char* kSKPathMagSolver =
"orientation.calibration.magsolver";
210 const char* kSKPathMagInclination =
"orientation.calibration.maginclination";
211 const char* kSKPathMagBValue =
"orientation.calibration.magmagnitude";
212 const char* kSKPathMagBValueTrial =
"orientation.calibration.magmagnitudetrial";
213 const char* kSKPathMagNoise =
"orientation.calibration.magnoise";
214 const char* kSKPathMagCalValues =
"orientation.calibration.magvalues";
236 const char* kConfigPathNone =
"";
256 PIN_I2C_SDA, PIN_I2C_SCL, BOARD_ACCEL_MAG_I2C_ADDR, BOARD_GYRO_I2C_ADDR);
257 const int fusionIntervalMs = 1000 / orientation_sensor->GetFusionRateHz();
258 event_loop()->onRepeat( fusionIntervalMs,
259 [orientation_sensor]() { orientation_sensor->ReadAndProcessSensors(); }
303 auto compass_heading = std::make_shared<RepeatSensor<float>>(
304 ORIENTATION_REPORTING_INTERVAL_MS,
305 [sensor_heading]() {
return sensor_heading->ReportValue(); }
315 auto compass_sk_output = std::make_shared<SKOutput<float>>(
316 kSKPathHeadingCompass,
325 auto magneticheading_sk_output = std::make_shared<SKOutput<float>>(
326 kSKPathHeadingMagnetic,
339 const char* kConfigPathDeviation =
"/sensors/hdg/deviation";
341 ConfigItem(deviationInterpolator)
342 ->set_title(
"Deviation Table")
343 ->set_description(
"Interpolation Values")
344 ->set_sort_order(1001);
348 const char* kConfigPathHeadingOffset =
"/sensors/hdg/offset";
349 auto* mountingOffset =
new AngleCorrection((PI/2.0), 0.0, kConfigPathHeadingOffset);
350 ConfigItem(mountingOffset)
351 ->set_title(
"Mounting Offset")
352 ->set_description(
"Enter any adjustment to be applied to all headings (e.g. from mounting offsets)")
353 ->set_sort_order(400);
357 ->connect_to(mountingOffset)
358 ->connect_to(compass_sk_output)
359 ->connect_to(deviationInterpolator)
360 ->connect_to(
new AngleCorrection(0.0, 0.0, kConfigPathNone))
361 ->connect_to(magneticheading_sk_output);
375 auto attitude_sensor = std::make_shared<RepeatSensor<AttitudeVector>>(
376 ORIENTATION_REPORTING_INTERVAL_MS,
377 [sensor_roll, sensor_pitch, sensor_yaw]()
378 {
return AttitudeVector(sensor_roll->ReportValue(),
379 sensor_pitch->ReportValue(),
380 sensor_yaw->ReportValue()
384 auto attitude_sk_output = std::make_shared<SKOutput<AttitudeVector>>(
388 attitude_sensor->connect_to(attitude_sk_output);
417 auto magcalfit = std::make_shared<RepeatSensor<float>>(
419 [sensor_magcalfit]() {
return sensor_magcalfit->ReportValue(); });
421 auto magcalfit_metadata = std::make_shared<SKMetadata>();
422 magcalfit_metadata->units_ =
"%";
423 magcalfit_metadata->description_ =
"Goodness-of-fit of readings using current Magnetic Calibration";
424 magcalfit_metadata->display_name_ =
"Magnetic Calibration Fit";
425 magcalfit_metadata->short_name_ =
"MagCalFit";
426 auto magcalfit_output = std::make_shared<SKOutput<float>>(
431 magcalfit->connect_to(magcalfit_output);
436 auto magcaltrial = std::make_shared<RepeatSensor<float>>(
438 [sensor_magcal_candidate]() {
return sensor_magcal_candidate->ReportValue(); });
439 auto magcaltrial_metadata = std::make_shared<SKMetadata>();
440 magcaltrial_metadata->units_ =
"%";
441 magcaltrial_metadata->description_ =
"Goodness-of-fit of readings using trial Magnetic Calibration";
442 magcaltrial_metadata->display_name_ =
"Magnetic Calibration Fit Trial";
443 magcaltrial_metadata->short_name_ =
"MagCalFitTrial";
444 auto magcaltrial_output = std::make_shared<SKOutput<float>>(
449 magcaltrial->connect_to(magcaltrial_output);
454 auto magcalorder = std::make_shared<RepeatSensor<float>>(
456 [sensor_cal_order]() {
return sensor_cal_order->ReportValue(); });
457 auto cal_solver_metadata = std::make_shared<SKMetadata>();
458 cal_solver_metadata->units_ =
"[0,4,7,10]";
459 cal_solver_metadata->description_ =
"Order of calibration algorithm used [0,4,7,10] 10 is best.";
460 cal_solver_metadata->display_name_ =
"Magnetic Calibration Algorithm Order";
461 cal_solver_metadata->short_name_ =
"MagCalOrder";
462 auto cal_solver_output = std::make_shared<SKOutput<int>>(
467 magcalorder->connect_to(cal_solver_output);
472 auto maginclination = std::make_shared<RepeatSensor<float>>(
474 [sensor_mag_inclination]() {
return sensor_mag_inclination->ReportValue(); });
475 auto inclination_metadata = std::make_shared<SKMetadata>();
476 inclination_metadata->units_ =
"rad";
477 inclination_metadata->description_ =
"Magnetic field inclination from horizontal";
478 inclination_metadata->display_name_ =
"Magnetic Inclination";
479 inclination_metadata->short_name_ =
"MagInclination";
480 auto inclination_output = std::make_shared<SKOutput<float>>(
481 kSKPathMagInclination,
485 maginclination->connect_to(inclination_output);
490 auto magbvalue = std::make_shared<RepeatSensor<float>>(
492 [sensor_mag_b_value]() {
return sensor_mag_b_value->ReportValue(); });
493 auto magbvalue_metadata = std::make_shared<SKMetadata>();
494 magbvalue_metadata->units_ =
"uT";
495 magbvalue_metadata->description_ =
"Magnetic field strength using current calibration";
496 magbvalue_metadata->display_name_ =
"Magnetic B Field";
497 magbvalue_metadata->short_name_ =
"B Field";
498 auto magbvalue_output = std::make_shared<SKOutput<float>>(
503 magbvalue->connect_to(magbvalue_output);
508 auto magbtrialvalue = std::make_shared<RepeatSensor<float>>(
510 [sensor_mag_b_trial_value]() {
return sensor_mag_b_trial_value->ReportValue(); });
511 auto magbtrialvalue_metadata = std::make_shared<SKMetadata>();
512 magbtrialvalue_metadata->units_ =
"uT";
513 magbtrialvalue_metadata->description_ =
"Magnetic field strength using trial calibration";
514 magbtrialvalue_metadata->display_name_ =
"Magnetic B Field Trial";
515 magbtrialvalue_metadata->short_name_ =
"B Field Trial";
516 auto magbtrialvalue_output = std::make_shared<SKOutput<float>>(
517 kSKPathMagBValueTrial,
519 magbtrialvalue_metadata
521 magbtrialvalue->connect_to(magbtrialvalue_output);
526 auto magnoise = std::make_shared<RepeatSensor<float>>(
528 [sensor_mag_noise]() {
return sensor_mag_noise->ReportValue(); });
529 auto mag_noise_metadata = std::make_shared<SKMetadata>();
530 mag_noise_metadata->units_ =
"unitless";
531 mag_noise_metadata->description_ =
"Magnetic Noise / Interference";
532 mag_noise_metadata->display_name_ =
"Magnetic Noise";
533 mag_noise_metadata->short_name_ =
"Mag Noise";
534 auto mag_noise_output = std::make_shared<SKOutput<float>>(
539 magnoise->connect_to(mag_noise_output);
546 auto roll_rate = std::make_shared<RepeatSensor<float>>(
548 [sensor_roll_rate]() {
return sensor_roll_rate->ReportValue(); });
549 auto metadata_roll_rate = std::make_shared<SKMetadata>();
550 metadata_roll_rate->units_ =
"rad/s";
551 metadata_roll_rate->description_ =
"Rate of Roll about bow-stern axis";
552 metadata_roll_rate->display_name_ =
"Roll Rate";
553 metadata_roll_rate->short_name_ =
"Roll Rate";
554 auto roll_rate_output = std::make_shared<SKOutput<float>>(
559 roll_rate->connect_to(roll_rate_output);
565 auto pitch_rate = std::make_shared<RepeatSensor<float>>(
567 [sensor_pitch_rate]() {
return sensor_pitch_rate->ReportValue(); });
568 auto metadata_pitch_rate = std::make_shared<SKMetadata>();
569 metadata_pitch_rate->units_ =
"rad/s";
570 metadata_pitch_rate->description_ =
"Rate of Pitch about port-starboard axis";
571 metadata_pitch_rate->display_name_ =
"Pitch Rate";
572 metadata_pitch_rate->short_name_ =
"Pitch Rate";
573 auto pitch_rate_output = std::make_shared<SKOutput<float>>(
578 pitch_rate->connect_to(pitch_rate_output);
583 auto turn_rate = std::make_shared<RepeatSensor<float>>(
585 [sensor_turn_rate]() {
return sensor_turn_rate->ReportValue(); });
586 auto metadata_turn_rate = std::make_shared<SKMetadata>();
587 metadata_turn_rate->units_ =
"rad/s";
588 metadata_turn_rate->description_ =
"Rate of Turn about mast-keel axis";
589 metadata_turn_rate->display_name_ =
"Turn Rate";
590 metadata_turn_rate->short_name_ =
"Turn Rate";
591 auto turn_rate_output = std::make_shared<SKOutput<float>>(
596 turn_rate->connect_to(turn_rate_output);
620 auto accel_X = std::make_shared<RepeatSensor<float>>(
622 [sensor_accel_X]() {
return sensor_accel_X->ReportValue(); });
623 auto metadata_accel_X = std::make_shared<SKMetadata>();
624 metadata_accel_X->units_ =
"m/s^2";
625 metadata_accel_X->description_ =
"Acceleration in X axis of eCompass";
626 metadata_accel_X->display_name_ =
"X Axis Acceleration";
627 metadata_accel_X->short_name_ =
"Accel X";
628 auto accel_X_output = std::make_shared<SKOutput<float>>(
633 accel_X->connect_to(accel_X_output);
642 auto temperature = std::make_shared<RepeatSensor<float>>(
644 [sensor_temperature]() {
return sensor_temperature->ReportValue(); });
650 const char* kConfigPathTemperatureCal =
"/sensors/temp/calibrate";
651 auto temperatureCal = std::make_shared<Linear>(1.0, 0.0,kConfigPathTemperatureCal);
652 ConfigItem(temperatureCal)
653 ->set_title(
"Compass Temperature Calibration")
654 ->set_description(
"Calibration / Linearization of temperature reported by eCompass IC")
655 ->set_sort_order(206);
658 auto temperature_metadata = std::make_shared<SKMetadata>();
659 temperature_metadata->units_ =
"K";
660 temperature_metadata->description_ =
"Temperature reported by orientation sensor";
661 temperature_metadata->display_name_ =
"eCompass Temperature";
662 temperature_metadata->short_name_ =
"Comp. T";
664 auto temperature_output = std::make_shared<SKOutput<float>>(
671 ->connect_to(temperatureCal)
672 ->connect_to(temperature_output);
683 auto* button_watcher =
new DigitalInputChange(
684 PIN_SWITCH_CAL_SAVE, INPUT_PULLUP, CHANGE, kConfigPathNone);
686 const int kDebounceDelay = 350;
687 const char* kConfigPathDebounceSwitch =
"/debounce/delay";
688 auto* debounce =
new DebounceInt(kDebounceDelay, kConfigPathDebounceSwitch);
690 ->set_title(
"MagCal Button Debounce")
691 ->set_description(
"Debounce delay (ms) for Magnetic Calibration save button.")
692 ->set_sort_order(1000);
695 auto save_mcal_function = [orientation_sensor](
int input) {
696 if (input == SWITCH_ACTIVE_STATE) {
697 orientation_sensor->sensor_interface_->SaveMagneticCalibration();
698 debugI(
"Magnetic Calibration values saved");
701 auto* button_consumer =
new LambdaConsumer<int>(save_mcal_function);
703 button_watcher->connect_to(debounce)->connect_to(button_consumer);
713void loop() { event_loop()->tick(); }
DeviationInterpolator(String config_path="")
OrientationSensor represents a 9-Degrees-of-Freedom sensor (magnetometer, accelerometer,...
OrientationValues reads and outputs orientation parameters.
@ kMagCalFitInUse
fit of currently-used calibration. <3.5 is good.
@ kRateOfTurn
rate of change of compass heading
@ kMagFieldMagnitudeTrial
geomagnetic magnitude based on current readings
@ kCompassHeading
compass heading, also called yaw
@ kYaw
rotation about the vertical axis
@ kMagCalAlgorithmSolver
cal algorithm order used. [0,4,7,10] 10 is best
@ kAccelerationX
acceleration in the stern-to-bow axis
@ kRateOfRoll
rate of change of roll
@ kMagCalFitTrial
fit of candidate calibration. <3.5 is good.
@ kRateOfPitch
rate of change of pitch
@ kMagNoiseCovariance
deviation of current reading from calibrated geomag sphere
@ kPitch
rotation about the transverse axis
@ kMagFieldMagnitude
geomagnetic magnitude of current calibration
@ kRoll
rotation about the longitudinal axis
@ kTemperature
temperature as reported by sensor IC
@ kMagInclination
geomagnetic inclination based on current readings
Orientation sensor interface to SensESP.
Vessel orientation data structures definition file.