From 4c2e15c1f4851f941ef813e15108fd16dfb997d4 Mon Sep 17 00:00:00 2001 From: Thomas Sarlandie Date: Fri, 7 Sep 2018 19:48:51 +0200 Subject: [PATCH 1/2] feature: add a CurrentMonitor service - Add configuration for currentMonitor, config parsing and a test - Add a SignalK path for battery current - Add service with configurable frequency to fetch bus and shunt voltage by i2c and send them to the skHub --- extras/config/default-config.json | 5 ++ src/common/signalk/SKJSONVisitor.cpp | 4 ++ src/common/signalk/SKPathEnum.generated.h | 3 +- .../signalk/SKPathToString.generated.cpp | 5 +- src/common/signalk/SKSource.h | 3 +- .../SKUpdateSyntacticSugar.generated.h | 11 +++- src/common/signalk/SKVisitor.generated.cpp | 5 +- src/common/signalk/SKVisitor.generated.h | 3 +- src/common/signalk/signalk.json | 6 ++ src/host/config/CurrentMonitorConfig.h | 38 +++++++++++++ src/host/config/KBoxConfig.h | 2 + src/host/config/KBoxConfigParser.cpp | 18 ++++++ src/host/config/KBoxConfigParser.h | 1 + src/host/main.cpp | 7 +++ src/host/services/CurrentMonitorService.cpp | 57 +++++++++++++++++++ src/host/services/CurrentMonitorService.h | 52 +++++++++++++++++ src/test/config/KBoxConfigParserTest.cpp | 19 +++++++ 17 files changed, 233 insertions(+), 6 deletions(-) create mode 100644 src/host/config/CurrentMonitorConfig.h create mode 100644 src/host/services/CurrentMonitorService.cpp create mode 100644 src/host/services/CurrentMonitorService.h diff --git a/extras/config/default-config.json b/extras/config/default-config.json index d64db7b0..cee10e3d 100644 --- a/extras/config/default-config.json +++ b/extras/config/default-config.json @@ -76,5 +76,10 @@ "nmea2000": { "txEnabled": true, "rxEnabled": true + }, + "currentMonitor": { + "enabled": false, + "frequency": 1, + "shuntResistance": 0.0001 } } diff --git a/src/common/signalk/SKJSONVisitor.cpp b/src/common/signalk/SKJSONVisitor.cpp index a28f400e..a48282ba 100644 --- a/src/common/signalk/SKJSONVisitor.cpp +++ b/src/common/signalk/SKJSONVisitor.cpp @@ -65,6 +65,10 @@ void SKJSONVisitor::processSource(const SKSource &source, JsonObject &sourceObje break; case SKSourceInputKBoxBarometer: sourceObject["label"] = "KBox.Barometer"; + break; + case SKSourceInputKBoxCurrentMonitor: + sourceObject["label"] = "KBox.CurrentMonitor"; + break; } } diff --git a/src/common/signalk/SKPathEnum.generated.h b/src/common/signalk/SKPathEnum.generated.h index e806e706..a2cae518 100644 --- a/src/common/signalk/SKPathEnum.generated.h +++ b/src/common/signalk/SKPathEnum.generated.h @@ -1,7 +1,7 @@ // This file was automatically generated by sk-code-generator.py // DO NOT MODIFY! YOUR CHANGES WOULD BE OVERWRITTEN // Look at src/common/signalk/SKPathEnum.h.tmpl instead or modify the script -// Generated on 2018-07-26 18:30:17.964584 +// Generated on 2018-09-07 15:19:22.000319 typedef enum { SKPathInvalidPath, @@ -39,6 +39,7 @@ typedef enum { // Marker value - Every path below requires an index. SKPathEnumIndexedPaths, + SKPathElectricalBatteriesCurrent, SKPathElectricalBatteriesVoltage, } SKPathEnum; diff --git a/src/common/signalk/SKPathToString.generated.cpp b/src/common/signalk/SKPathToString.generated.cpp index eea94db4..b3a8ca5e 100644 --- a/src/common/signalk/SKPathToString.generated.cpp +++ b/src/common/signalk/SKPathToString.generated.cpp @@ -1,7 +1,7 @@ // This file was automatically generated by sk-code-generator.py // DO NOT MODIFY! YOUR CHANGES WOULD BE OVERWRITTEN // Look at src/common/signalk/SKPathToString.cpp.tmpl instead or modify the script -// Generated on 2018-07-26 18:30:17.966879 +// Generated on 2018-09-07 15:19:22.002816 #include "SKPath.h" @@ -54,6 +54,9 @@ String SKPath::toString() const { case SKPathEnvironmentWindSpeedApparent: path = "environment.wind.speedApparent"; break; + case SKPathElectricalBatteriesCurrent: + path = "electrical.batteries." + _index + ".current"; + break; case SKPathElectricalBatteriesVoltage: path = "electrical.batteries." + _index + ".voltage"; break; diff --git a/src/common/signalk/SKSource.h b/src/common/signalk/SKSource.h index 7d4fee49..5aec1edb 100644 --- a/src/common/signalk/SKSource.h +++ b/src/common/signalk/SKSource.h @@ -33,7 +33,8 @@ enum SKSourceInput { SKSourceInputNMEA2000, SKSourceInputKBoxIMU, SKSourceInputKBoxADC, - SKSourceInputKBoxBarometer + SKSourceInputKBoxBarometer, + SKSourceInputKBoxCurrentMonitor }; const String skSourceInputLabels[] = { diff --git a/src/common/signalk/SKUpdateSyntacticSugar.generated.h b/src/common/signalk/SKUpdateSyntacticSugar.generated.h index 8ed05060..c538a1ce 100644 --- a/src/common/signalk/SKUpdateSyntacticSugar.generated.h +++ b/src/common/signalk/SKUpdateSyntacticSugar.generated.h @@ -1,7 +1,7 @@ // This file was automatically generated by sk-code-generator.py // DO NOT MODIFY! YOUR CHANGES WOULD BE OVERWRITTEN // Look at src/common/signalk/SKUpdateSyntacticSugar.h.tmpl instead or modify the script -// Generated on 2018-07-26 18:30:17.968282 +// Generated on 2018-09-07 15:19:22.004688 bool hasEnvironmentDepthBelowKeel() const { return hasPath(SKPathEnvironmentDepthBelowKeel); @@ -138,6 +138,15 @@ double getEnvironmentWindSpeedApparent() const { bool setEnvironmentWindSpeedApparent(double newValue) { return setValue(SKPathEnvironmentWindSpeedApparent, newValue); }; +bool hasElectricalBatteriesCurrent(String index) const { + return hasPath(SKPath(SKPathElectricalBatteriesCurrent, index)); +}; +double getElectricalBatteriesCurrent(String index) const { + return this->operator[](SKPath(SKPathElectricalBatteriesCurrent, index)).getNumberValue(); +}; +bool setElectricalBatteriesCurrent(String index, double newValue) { + return setValue(SKPath(SKPathElectricalBatteriesCurrent, index), newValue); +}; bool hasElectricalBatteriesVoltage(String index) const { return hasPath(SKPath(SKPathElectricalBatteriesVoltage, index)); }; diff --git a/src/common/signalk/SKVisitor.generated.cpp b/src/common/signalk/SKVisitor.generated.cpp index 77ea8e53..8eda9ddf 100644 --- a/src/common/signalk/SKVisitor.generated.cpp +++ b/src/common/signalk/SKVisitor.generated.cpp @@ -1,7 +1,7 @@ // This file was automatically generated by sk-code-generator.py // DO NOT MODIFY! YOUR CHANGES WOULD BE OVERWRITTEN // Look at src/common/signalk/SKVisitor.cpp.tmpl instead or modify the script -// Generated on 2018-07-26 18:30:17.969656 +// Generated on 2018-09-07 15:19:22.006177 /* __ __ ______ ______ __ __ @@ -82,6 +82,9 @@ void SKVisitor::visit(const SKUpdate& u, const SKPath &p, const SKValue &v) { if (p.getStaticPath() == SKPathEnvironmentWindSpeedApparent) { visitSKEnvironmentWindSpeedApparent(u, p, v); } + if (p.getStaticPath() == SKPathElectricalBatteriesCurrent) { + visitSKElectricalBatteriesCurrent(u, p, v); + } if (p.getStaticPath() == SKPathElectricalBatteriesVoltage) { visitSKElectricalBatteriesVoltage(u, p, v); } diff --git a/src/common/signalk/SKVisitor.generated.h b/src/common/signalk/SKVisitor.generated.h index a7b6014a..1c041849 100644 --- a/src/common/signalk/SKVisitor.generated.h +++ b/src/common/signalk/SKVisitor.generated.h @@ -1,7 +1,7 @@ // This file was automatically generated by sk-code-generator.py // DO NOT MODIFY! YOUR CHANGES WOULD BE OVERWRITTEN // Look at src/common/signalk/SKVisitor.h.tmpl instead or modify the script -// Generated on 2018-07-26 18:30:17.969000 +// Generated on 2018-09-07 15:19:22.005404 /* __ __ ______ ______ __ __ @@ -63,6 +63,7 @@ class SKVisitor { virtual void visitSKEnvironmentWindSpeedTrue(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; virtual void visitSKEnvironmentWindSpeedOverGround(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; virtual void visitSKEnvironmentWindSpeedApparent(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; + virtual void visitSKElectricalBatteriesCurrent(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; virtual void visitSKElectricalBatteriesVoltage(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; virtual void visitSKNavigationAttitude(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; virtual void visitSKNavigationCourseOverGroundTrue(const SKUpdate &u, const SKPath &p, const SKValue &v) {}; diff --git a/src/common/signalk/signalk.json b/src/common/signalk/signalk.json index 688e2d96..60d0725e 100644 --- a/src/common/signalk/signalk.json +++ b/src/common/signalk/signalk.json @@ -91,6 +91,12 @@ "description": "Apparent wind speed" }, + { + "path": "electrical.batteries.%%.current", + "type": "numberValue", + "unit": "V", + "description": "Current flowing out (+ve) or in (-ve) to the device" + }, { "path": "electrical.batteries.%%.voltage", "type": "numberValue", diff --git a/src/host/config/CurrentMonitorConfig.h b/src/host/config/CurrentMonitorConfig.h new file mode 100644 index 00000000..b2c8083c --- /dev/null +++ b/src/host/config/CurrentMonitorConfig.h @@ -0,0 +1,38 @@ +/* + __ __ ______ ______ __ __ + /\ \/ / /\ == \ /\ __ \ /\_\_\_\ + \ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_ + \ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\ + \/_/\/_/ \/_____/ \/_____/ \/_/\/_/ + + The MIT License + + Copyright (c) 2018 Thomas Sarlandie thomas@sarlandie.net + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#pragma once + +struct CurrentMonitorConfig { + bool enabled; + int frequency; + + double shuntResistance; +}; \ No newline at end of file diff --git a/src/host/config/KBoxConfig.h b/src/host/config/KBoxConfig.h index 25a0627d..3677a224 100644 --- a/src/host/config/KBoxConfig.h +++ b/src/host/config/KBoxConfig.h @@ -36,6 +36,7 @@ #include "BarometerConfig.h" #include "WiFiConfig.h" #include "SDLoggingConfig.h" +#include "CurrentMonitorConfig.h" /** * A KBox configuration in memory @@ -48,4 +49,5 @@ struct KBoxConfig { BarometerConfig barometerConfig; WiFiConfig wifiConfig; SDLoggingConfig sdLoggingConfig; + CurrentMonitorConfig currentMonitorConfig; }; diff --git a/src/host/config/KBoxConfigParser.cpp b/src/host/config/KBoxConfigParser.cpp index f2c2adfc..3474ba80 100644 --- a/src/host/config/KBoxConfigParser.cpp +++ b/src/host/config/KBoxConfigParser.cpp @@ -44,6 +44,8 @@ json[#name] .as(); \ } +#define READ_DOUBLE_VALUE(name) READ_VALUE_WITH_TYPE(name, double) + #define READ_STRING_VALUE(name) if (json[#name].is()) {\ config.name = \ String(json[#name].as()); \ @@ -100,6 +102,11 @@ void KBoxConfigParser::defaultConfig(KBoxConfig &config) { config.sdLoggingConfig.logSignalKGeneratedFromNMEA = false; config.sdLoggingConfig.logSignalKGeneratedFromNMEA2000 = false; config.sdLoggingConfig.logSignalKGeneratedByKBoxSensors = true; + + config.currentMonitorConfig.enabled = false; + config.currentMonitorConfig.frequency = 1; + // .1mOhm is the resistance of the standard Victron shunt. + config.currentMonitorConfig.shuntResistance = 0.0001; } void KBoxConfigParser::parseKBoxConfig(const JsonObject &json, KBoxConfig &config) { @@ -112,6 +119,7 @@ void KBoxConfigParser::parseKBoxConfig(const JsonObject &json, KBoxConfig &confi parseWiFiConfig(json["wifi"], config.wifiConfig); parseNMEA2000Config(json["nmea2000"], config.nmea2000Config); parseSDLoggingConfig(json["logging"], config.sdLoggingConfig); + parseCurrentMonitorConfig(json["currentMonitor"], config.currentMonitorConfig); } void KBoxConfigParser::parseIMUConfig(const JsonObject &json, IMUConfig &config) { @@ -176,6 +184,16 @@ void KBoxConfigParser::parseSDLoggingConfig(const JsonObject &json, SDLoggingCon READ_BOOL_VALUE(logSignalKGeneratedByKBoxSensors); } +void KBoxConfigParser::parseCurrentMonitorConfig(const JsonObject &json, CurrentMonitorConfig &config) { + if (json == JsonObject::invalid()) { + return ; + } + + READ_BOOL_VALUE(enabled); + READ_INT_VALUE_WRANGE(frequency, 1, 10); + READ_DOUBLE_VALUE(shuntResistance); +} + void KBoxConfigParser::parseNMEAConverterConfig(const JsonObject &json, SKNMEAConverterConfig &config) { if (json == JsonObject::invalid()) { return; diff --git a/src/host/config/KBoxConfigParser.h b/src/host/config/KBoxConfigParser.h index c0b681d7..0ec6498e 100644 --- a/src/host/config/KBoxConfigParser.h +++ b/src/host/config/KBoxConfigParser.h @@ -66,6 +66,7 @@ class KBoxConfigParser { void parseNMEA2000Config(const JsonObject &object, NMEA2000Config &config); void parseWiFiConfig(const JsonObject &json, WiFiConfig &config); void parseSDLoggingConfig(const JsonObject &json, SDLoggingConfig &config); + void parseCurrentMonitorConfig(const JsonObject &json, CurrentMonitorConfig &config); void parseWiFiNetworkConfig(const JsonObject &json, WiFiNetworkConfig &config); void parseNMEAConverterConfig(const JsonObject &json, diff --git a/src/host/main.cpp b/src/host/main.cpp index 5afd7723..d08d58d5 100644 --- a/src/host/main.cpp +++ b/src/host/main.cpp @@ -44,6 +44,8 @@ #include "host/services/TimeService.h" #include "host/services/USBService.h" #include "host/services/WiFiService.h" +#include "services/CurrentMonitorService.h" +#include "config/KBoxConfig.h" static const char *configFilename = "kbox-config.json"; @@ -131,6 +133,8 @@ void setup() { reader2->addRepeater(sdLoggingService); n2kService->addSentenceRepeater(sdLoggingService); + CurrentMonitorService *currentMonitorService = new CurrentMonitorService(skHub, config.currentMonitorConfig); + // Tell the wallClock how to get the number of ms elapsed since boot. wallClock.setMillisecondsProvider(millis); @@ -148,6 +152,9 @@ void setup() { if (config.barometerConfig.enabled) { taskManager.addTask(new IntervalTask(baroService, 1000 / config.barometerConfig.frequency)); } + if (config.currentMonitorConfig.enabled) { + taskManager.addTask(new IntervalTask(currentMonitorService, 1000 / config.currentMonitorConfig.frequency)); + } taskManager.addTask(n2kService); taskManager.addTask(reader1); taskManager.addTask(reader2); diff --git a/src/host/services/CurrentMonitorService.cpp b/src/host/services/CurrentMonitorService.cpp new file mode 100644 index 00000000..1f9f40cd --- /dev/null +++ b/src/host/services/CurrentMonitorService.cpp @@ -0,0 +1,57 @@ +/* + __ __ ______ ______ __ __ + /\ \/ / /\ == \ /\ __ \ /\_\_\_\ + \ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_ + \ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\ + \/_/\/_/ \/_____/ \/_____/ \/_/\/_/ + + The MIT License + + Copyright (c) 2018 Thomas Sarlandie thomas@sarlandie.net + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#include "CurrentMonitorService.h" +#include +#include "common/signalk/SKUpdateStatic.h" +#include "common/signalk/SKSource.h" + +void CurrentMonitorService::setup() { + ina219.begin(ina219_address); +} + +void CurrentMonitorService::loop() { + float shuntVoltageMV = ina219.getShuntVoltage_mV(); + float busVoltage = ina219.getBusVoltage_V(); + + + SKUpdateStatic<4> sk; + sk.setSource(SKSource::sourceForKBoxSensor(SKSourceInputKBoxCurrentMonitor)); + sk.setElectricalBatteriesVoltage("shunt", busVoltage); + + double current = shuntVoltageMV * 1e-3 * _config.shuntResistance; + if (_config.shuntResistance > 0) { + // TODO: It would be best to properly configure the INA219 properly and let it do the maths. + sk.setElectricalBatteriesCurrent("shunt", current); + } + + DEBUG("Current monitor: busVoltage=%.2fV shuntVoltage=%.2fmV current=%.2fA", busVoltage, shuntVoltageMV, current); + _skHub.publish(sk); +} \ No newline at end of file diff --git a/src/host/services/CurrentMonitorService.h b/src/host/services/CurrentMonitorService.h new file mode 100644 index 00000000..3a27d099 --- /dev/null +++ b/src/host/services/CurrentMonitorService.h @@ -0,0 +1,52 @@ +/* + __ __ ______ ______ __ __ + /\ \/ / /\ == \ /\ __ \ /\_\_\_\ + \ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_ + \ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\ + \/_/\/_/ \/_____/ \/_____/ \/_/\/_/ + + The MIT License + + Copyright (c) 2018 Thomas Sarlandie thomas@sarlandie.net + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. +*/ + +#pragma once + +#include +#include +#include +#include + +class CurrentMonitorService : public Task { + private: + SKHub &_skHub; + CurrentMonitorConfig &_config; + Adafruit_INA219 ina219; + + public: + CurrentMonitorService(SKHub& skHub, CurrentMonitorConfig &config) : Task("CurrentMonitor"), _skHub(skHub), + _config(config) + {}; + + void setup(); + void loop(); +}; + diff --git a/src/test/config/KBoxConfigParserTest.cpp b/src/test/config/KBoxConfigParserTest.cpp index 4d4197ea..b8b7185b 100644 --- a/src/test/config/KBoxConfigParserTest.cpp +++ b/src/test/config/KBoxConfigParserTest.cpp @@ -53,6 +53,11 @@ TEST_CASE("KBoxConfigParser") { CHECK( config.wifiConfig.vesselURN == "urn:mrn:kbox:unit-testing" ); CHECK( config.sdLoggingConfig.enabled == true ); CHECK( config.sdLoggingConfig.logWithoutTime == false ); + + CHECK( config.currentMonitorConfig.enabled == false ); + CHECK( config.currentMonitorConfig.frequency == 1 ); + CHECK( config.currentMonitorConfig.shuntResistance == 0.0001 ); + } SECTION("No input") { @@ -174,4 +179,18 @@ TEST_CASE("KBoxConfigParser") { CHECK(!sdLoggingConfig.enabled); CHECK(sdLoggingConfig.logWithoutTime); } + + SECTION("Shunt config") { + const char *jsonConfig = "{ 'enabled': true, 'shuntResistance': 0.00002 }"; + JsonObject &root = jsonBuffer.parseObject(jsonConfig); + + CHECK(root.success()); + + CurrentMonitorConfig config; + + kboxConfigParser.parseCurrentMonitorConfig(root, config); + + CHECK(config.enabled); + CHECK(config.shuntResistance == 0.00002); + } } From 26109528517673f8f62df66981a947f62220661a Mon Sep 17 00:00:00 2001 From: Thomas Sarlandie Date: Mon, 10 Sep 2018 15:57:20 +0200 Subject: [PATCH 2/2] fix: maths to calculate current (Yes, I am ashamed of myself) --- src/host/services/CurrentMonitorService.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/host/services/CurrentMonitorService.cpp b/src/host/services/CurrentMonitorService.cpp index 1f9f40cd..a48b5645 100644 --- a/src/host/services/CurrentMonitorService.cpp +++ b/src/host/services/CurrentMonitorService.cpp @@ -46,7 +46,7 @@ void CurrentMonitorService::loop() { sk.setSource(SKSource::sourceForKBoxSensor(SKSourceInputKBoxCurrentMonitor)); sk.setElectricalBatteriesVoltage("shunt", busVoltage); - double current = shuntVoltageMV * 1e-3 * _config.shuntResistance; + double current = (shuntVoltageMV * 1e-3) / _config.shuntResistance; if (_config.shuntResistance > 0) { // TODO: It would be best to properly configure the INA219 properly and let it do the maths. sk.setElectricalBatteriesCurrent("shunt", current);