aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthias P. Braendli <matthias.braendli@mpb.li>2020-10-25 15:14:39 +0100
committerMatthias P. Braendli <matthias.braendli@mpb.li>2020-10-25 15:14:39 +0100
commit4fb62abd2ff61d03ada52fd3f522755b6a659025 (patch)
treeca559bbcdac9aa93663630c298933dde5bc3a74c
parenta0ccf32157a48c291b02bf8d1de0b25b06768cbc (diff)
downloadglutte-o-matic-4fb62abd2ff61d03ada52fd3f522755b6a659025.tar.gz
glutte-o-matic-4fb62abd2ff61d03ada52fd3f522755b6a659025.tar.bz2
glutte-o-matic-4fb62abd2ff61d03ada52fd3f522755b6a659025.zip
Add EOL SK message when wind gen breaker is open
-rw-r--r--src/common/Core/fsm.c20
-rw-r--r--src/common/GPIO/batterycharge.c106
-rw-r--r--src/common/GPIO/batterycharge.h3
-rw-r--r--src/glutt-o-logique/Makefile3
-rw-r--r--src/simulator/src/Gui/gui.c18
5 files changed, 130 insertions, 20 deletions
diff --git a/src/common/Core/fsm.c b/src/common/Core/fsm.c
index 7d3e6ca..e98ba91 100644
--- a/src/common/Core/fsm.c
+++ b/src/common/Core/fsm.c
@@ -482,9 +482,11 @@ void fsm_update() {
if (current_state == FSM_BALISE_STATS1) {
eol_info = "PSK125";
}
+ else if (batterycharge_wind_disconnected()) {
+ eol_info = "EOL \\"; // backslash is <SK>
+ }
else if (!fsm_in.wind_generator_ok) {
- eol_info = "\\";
- // The backslash is the SK digraph
+ eol_info = "\\"; // backslash is <SK>
}
if (balise_message_empty()) {
@@ -583,9 +585,11 @@ void fsm_update() {
if (balise_message_empty()) {
const char *eol_info = "73";
- if (!fsm_in.wind_generator_ok) {
- eol_info = "\\";
- // The backslash is the SK digraph
+ if (batterycharge_wind_disconnected()) {
+ eol_info = "EOL \\"; // backslash is <SK>
+ }
+ else if (!fsm_in.wind_generator_ok) {
+ eol_info = "\\"; // backslash is <SK>
}
snprintf(balise_message, BALISE_MESSAGE_LEN-1,
CW_PREDELAY "%s" CW_POSTDELAY,
@@ -616,9 +620,11 @@ void fsm_update() {
if (current_state == FSM_BALISE_SPECIALE_STATS1) {
eol_info = "PSK125";
}
+ else if (batterycharge_wind_disconnected()) {
+ eol_info = "EOL \\"; // backslash is <SK>
+ }
else if (!fsm_in.wind_generator_ok) {
- eol_info = "\\";
- // The backslash is the SK digraph
+ eol_info = "\\"; // backslash is <SK>
}
size_t len = 0;
diff --git a/src/common/GPIO/batterycharge.c b/src/common/GPIO/batterycharge.c
index d68a805..1126a17 100644
--- a/src/common/GPIO/batterycharge.c
+++ b/src/common/GPIO/batterycharge.c
@@ -22,38 +22,68 @@
* SOFTWARE.
*/
+#include "Core/common.h"
#include "GPIO/batterycharge.h"
#include "FreeRTOS.h"
#include "task.h"
#include <string.h>
#include <stdlib.h>
+#include <stdio.h>
#include <errno.h>
// Hysteresis:
#define CHARGE_QRP 1300000
#define CHARGE_QRO 1350000
+// If last message older than that, consider the coulomb-counter broken
+#define MAX_MESSAGE_AGE 60 // seconds
+
+static uint64_t timestamp_last_message;
+
+static int breaker_valid;
+static int breaker_is_open;
static int charge_valid;
static uint32_t last_charge;
static int charge_qrp;
+static void reset(void)
+{
+ breaker_valid = 0;
+ breaker_is_open = -1;
+ charge_valid = 0;
+ last_charge = 0;
+ charge_qrp = 0;
+}
+
+static void check_timestamp(void)
+{
+ const uint64_t now = timestamp_now();
+ if (timestamp_last_message + MAX_MESSAGE_AGE * 1000 < now) {
+ reset();
+ }
+}
+
void batterycharge_init()
{
/* No need to protect the variables, this is called at init before the
* tasks get created.
*/
- charge_valid = 0;
- last_charge = 0;
- charge_qrp = 0;
+ timestamp_last_message = 0;
+ reset();
}
void batterycharge_push_message(const char *ccounter_msg)
{
+ const uint64_t ts = timestamp_now();
+
+ const int is_capa = strncmp(ccounter_msg, "CAPA", 4) == 0;
+ const int is_eol = strncmp(ccounter_msg, "DISJEOL", 7) == 0;
+
/* We ignore TEXT, ERROR, VBAT+ and VBAT- for the moment, and only parse CAPA.
* The \r\n has been trimmed off the message already, therefore the value
* should extend until the end of string.
*/
- if (strncmp(ccounter_msg, "CAPA", 4) == 0) {
+ if (is_capa || is_eol) {
size_t ix_value = 0;
int second_found = 0;
@@ -69,13 +99,35 @@ void batterycharge_push_message(const char *ccounter_msg)
}
const char *valuestr = ccounter_msg + ix_value;
- char *endptr;
- errno = 0;
- const uint32_t value = strtol(valuestr, &endptr, 10);
- if (errno == 0 && endptr != valuestr) {
+ if (is_capa) {
+ /* Field is the capacity in mAh */
+ char *endptr;
+ errno = 0;
+ const uint32_t value = strtol(valuestr, &endptr, 10);
+ if (errno == 0 && endptr != valuestr) {
+ taskDISABLE_INTERRUPTS();
+ last_charge = value;
+ charge_valid = 1;
+ timestamp_last_message = ts;
+ taskENABLE_INTERRUPTS();
+ }
+ }
+ else if (is_eol) {
+ /* Field is either `On` or `Off` */
+ const int is_on = strncmp(valuestr, "On", 2) == 0;
+ const int is_off = strncmp(valuestr, "Off", 2) == 0;
+
taskDISABLE_INTERRUPTS();
- last_charge = value;
- charge_valid = 1;
+ if (is_on) {
+ breaker_valid = 1;
+ breaker_is_open = 0;
+ timestamp_last_message = ts;
+ }
+ else if (is_off) {
+ breaker_valid = 1;
+ breaker_is_open = 1;
+ timestamp_last_message = ts;
+ }
taskENABLE_INTERRUPTS();
}
}
@@ -83,8 +135,10 @@ void batterycharge_push_message(const char *ccounter_msg)
uint32_t batterycharge_retrieve_last_capacity()
{
- taskDISABLE_INTERRUPTS();
uint32_t ret = 0;
+ taskDISABLE_INTERRUPTS();
+ check_timestamp();
+
if (charge_valid) {
ret = last_charge;
}
@@ -94,16 +148,28 @@ uint32_t batterycharge_retrieve_last_capacity()
int batterycharge_too_low()
{
- taskDISABLE_INTERRUPTS();
uint32_t c = 0;
+ int b = -1;
+ taskDISABLE_INTERRUPTS();
+ check_timestamp();
+
if (charge_valid) {
c = last_charge;
}
+
+ if (breaker_valid) {
+ b = breaker_is_open;
+ }
taskENABLE_INTERRUPTS();
- if (c == 0) {
+ /* Disconnected wind generator implies QRP always */
+ if (b == 1) {
+ return 1;
+ }
+ else if (c == 0) {
return -1;
}
+ /* Implement hysteresis */
else if (charge_qrp == 0 && c < CHARGE_QRP) {
charge_qrp = 1;
}
@@ -112,3 +178,17 @@ int batterycharge_too_low()
}
return charge_qrp;
}
+
+int batterycharge_wind_disconnected()
+{
+ int b = -1;
+ taskDISABLE_INTERRUPTS();
+ check_timestamp();
+
+ if (breaker_valid) {
+ b = breaker_is_open;
+ }
+ taskENABLE_INTERRUPTS();
+
+ return b;
+}
diff --git a/src/common/GPIO/batterycharge.h b/src/common/GPIO/batterycharge.h
index 6785d79..f4a2c1a 100644
--- a/src/common/GPIO/batterycharge.h
+++ b/src/common/GPIO/batterycharge.h
@@ -36,3 +36,6 @@ uint32_t batterycharge_retrieve_last_capacity(void);
// Return 1 if battery charge is too low, -1 if unknown
int batterycharge_too_low(void);
+
+// Return 0 if the wind generator is connected, 1 if the breaker is open, -1 if unknown
+int batterycharge_wind_disconnected(void);
diff --git a/src/glutt-o-logique/Makefile b/src/glutt-o-logique/Makefile
index 3794856..c26baba 100644
--- a/src/glutt-o-logique/Makefile
+++ b/src/glutt-o-logique/Makefile
@@ -178,3 +178,6 @@ ifeq ($(wildcard /opt/openocd/bin/openocd),)
else
/opt/openocd/bin/openocd -f stm32f4discovery-with-stlinkv2.1.cfg -c "program bin/"$(BINELF)" verify reset" -c "init" -c "reset" -c "exit"
endif
+
+help:
+ @echo "targets: all clean deploy (with stm32f4discovery.cfg) deploy21 (with stm32f4discovery-with-stlinkv2.1.cfg)"
diff --git a/src/simulator/src/Gui/gui.c b/src/simulator/src/Gui/gui.c
index 3dab969..dea5007 100644
--- a/src/simulator/src/Gui/gui.c
+++ b/src/simulator/src/Gui/gui.c
@@ -183,6 +183,11 @@ float gui_measured_voltage = 14.0f;
int gui_measured_capacity = 1630; // Ah
int gui_measured_capacity_last = 1630; // Ah
+static const char *breaker_status[] = {"Closed", "Open"};
+static const char *breaker_message[] = {"On", "Off"};
+int gui_breaker_status = 0;
+int gui_breaker_status_last = 0;
+
/**
* SWR
@@ -803,6 +808,19 @@ void main_gui() {
nk_property_float(ctx, "V", 0.0f, &gui_measured_voltage, 24.0f, 0.5f, 0.5f);
nk_layout_row_dynamic(ctx, 25, 2);
+ nk_label_colored(ctx, "Eolienne breaker", NK_TEXT_LEFT, c);
+ gui_breaker_status = nk_combo(ctx, breaker_status, LEN(breaker_status), gui_breaker_status, 30);
+
+ if (gui_breaker_status != gui_breaker_status_last) {
+ uart_send_txt_len = snprintf(uart_send_txt, sizeof(uart_send_txt), "DISJEOL,%ld,%s", timestamp_now()/1000, breaker_message[gui_breaker_status]);
+
+ uart_send_txt[uart_send_txt_len] = '\0';
+ gui_usart_send(uart_send_txt);
+
+ gui_breaker_status_last = gui_breaker_status;
+ }
+
+ nk_layout_row_dynamic(ctx, 25, 2);
nk_label_colored(ctx, "Capacity", NK_TEXT_LEFT, c);
nk_property_int(ctx, "Ah", 0, &gui_measured_capacity, 1650, 10, 0.1f);