Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: add a CurrentMonitor service #148

Open
wants to merge 3 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions extras/config/default-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,5 +76,10 @@
"nmea2000": {
"txEnabled": true,
"rxEnabled": true
},
"currentMonitor": {
"enabled": false,
"frequency": 1,
"shuntResistance": 0.0001
}
}
4 changes: 4 additions & 0 deletions src/common/signalk/SKJSONVisitor.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/common/signalk/SKPathEnum.generated.h
Original file line number Diff line number Diff line change
@@ -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,
Expand Down Expand Up @@ -39,6 +39,7 @@ typedef enum {
// Marker value - Every path below requires an index.
SKPathEnumIndexedPaths,

SKPathElectricalBatteriesCurrent,
SKPathElectricalBatteriesVoltage,

} SKPathEnum;
5 changes: 4 additions & 1 deletion src/common/signalk/SKPathToString.generated.cpp
Original file line number Diff line number Diff line change
@@ -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"

Expand Down Expand Up @@ -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;
Expand Down
3 changes: 2 additions & 1 deletion src/common/signalk/SKSource.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ enum SKSourceInput {
SKSourceInputNMEA2000,
SKSourceInputKBoxIMU,
SKSourceInputKBoxADC,
SKSourceInputKBoxBarometer
SKSourceInputKBoxBarometer,
SKSourceInputKBoxCurrentMonitor
};

const String skSourceInputLabels[] = {
Expand Down
11 changes: 10 additions & 1 deletion src/common/signalk/SKUpdateSyntacticSugar.generated.h
Original file line number Diff line number Diff line change
@@ -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);
Expand Down Expand Up @@ -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));
};
Expand Down
5 changes: 4 additions & 1 deletion src/common/signalk/SKVisitor.generated.cpp
Original file line number Diff line number Diff line change
@@ -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

/*
__ __ ______ ______ __ __
Expand Down Expand Up @@ -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);
}
Expand Down
3 changes: 2 additions & 1 deletion src/common/signalk/SKVisitor.generated.h
Original file line number Diff line number Diff line change
@@ -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

/*
__ __ ______ ______ __ __
Expand Down Expand Up @@ -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) {};
Expand Down
6 changes: 6 additions & 0 deletions src/common/signalk/signalk.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
38 changes: 38 additions & 0 deletions src/host/config/CurrentMonitorConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
/*
__ __ ______ ______ __ __
/\ \/ / /\ == \ /\ __ \ /\_\_\_\
\ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_
\ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\
\/_/\/_/ \/_____/ \/_____/ \/_/\/_/

The MIT License

Copyright (c) 2018 Thomas Sarlandie [email protected]

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;
};
2 changes: 2 additions & 0 deletions src/host/config/KBoxConfig.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@
#include "BarometerConfig.h"
#include "WiFiConfig.h"
#include "SDLoggingConfig.h"
#include "CurrentMonitorConfig.h"

/**
* A KBox configuration in memory
Expand All @@ -48,4 +49,5 @@ struct KBoxConfig {
BarometerConfig barometerConfig;
WiFiConfig wifiConfig;
SDLoggingConfig sdLoggingConfig;
CurrentMonitorConfig currentMonitorConfig;
};
18 changes: 18 additions & 0 deletions src/host/config/KBoxConfigParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@
json[#name] .as<int>(); \
}

#define READ_DOUBLE_VALUE(name) READ_VALUE_WITH_TYPE(name, double)

#define READ_STRING_VALUE(name) if (json[#name].is<const char *>()) {\
config.name = \
String(json[#name].as<const char*>()); \
Expand Down Expand Up @@ -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) {
Expand All @@ -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) {
Expand Down Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions src/host/config/KBoxConfigParser.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
7 changes: 7 additions & 0 deletions src/host/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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";

Expand Down Expand Up @@ -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);

Expand All @@ -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);
Expand Down
57 changes: 57 additions & 0 deletions src/host/services/CurrentMonitorService.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
__ __ ______ ______ __ __
/\ \/ / /\ == \ /\ __ \ /\_\_\_\
\ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_
\ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\
\/_/\/_/ \/_____/ \/_____/ \/_/\/_/

The MIT License

Copyright (c) 2018 Thomas Sarlandie [email protected]

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 <KBoxHardware.h>
#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);
}
52 changes: 52 additions & 0 deletions src/host/services/CurrentMonitorService.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/*
__ __ ______ ______ __ __
/\ \/ / /\ == \ /\ __ \ /\_\_\_\
\ \ _"-. \ \ __< \ \ \/\ \ \/_/\_\/_
\ \_\ \_\ \ \_____\ \ \_____\ /\_\/\_\
\/_/\/_/ \/_____/ \/_____/ \/_/\/_/

The MIT License

Copyright (c) 2018 Thomas Sarlandie [email protected]

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 <host/os/Task.h>
#include <common/signalk/SKHub.h>
#include <Adafruit_INA219.h>
#include <host/config/CurrentMonitorConfig.h>

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();
};

Loading