diff options
-rw-r--r-- | sw/Makefile | 1 | ||||
-rw-r--r-- | sw/common.hpp | 12 | ||||
-rw-r--r-- | sw/ltc2400.h | 2 | ||||
-rw-r--r-- | sw/main.cpp | 46 | ||||
-rw-r--r-- | sw/pins.hpp (renamed from sw/pins.h) | 6 | ||||
-rw-r--r-- | sw/relays.cpp | 104 | ||||
-rw-r--r-- | sw/relays.hpp | 7 |
7 files changed, 163 insertions, 15 deletions
diff --git a/sw/Makefile b/sw/Makefile index bd9f6ff..0b76729 100644 --- a/sw/Makefile +++ b/sw/Makefile @@ -23,6 +23,7 @@ BUILD_DIR=build APP_NAME = sw HEADERS = \ + pins.hpp \ common.hpp \ relays.hpp \ lib/Arduino.h \ diff --git a/sw/common.hpp b/sw/common.hpp index 345f34b..fa0ee8e 100644 --- a/sw/common.hpp +++ b/sw/common.hpp @@ -26,6 +26,7 @@ #include <stdlib.h> #include <stdint.h> +#include <avr/interrupt.h> struct timer_t { uint32_t seconds_ = 0; /* Timer in seconds */ @@ -58,6 +59,11 @@ struct timer_t { (seconds_ == rhs.seconds_ and ticks_ > rhs.ticks_); } + bool operator<(const timer_t& rhs) const { + return (seconds_ < rhs.seconds_) or + (seconds_ == rhs.seconds_ and ticks_ < rhs.ticks_); + } + void normalise() { while (ticks_ >= 10) { seconds_++; @@ -91,3 +97,9 @@ struct timer_t { static constexpr int ms_to_ticks(int ms) { return ms / 100; } }; + +enum class relay_id_t { + K1, + K2, + K3, +}; diff --git a/sw/ltc2400.h b/sw/ltc2400.h index 9a046b2..ac99521 100644 --- a/sw/ltc2400.h +++ b/sw/ltc2400.h @@ -27,7 +27,7 @@ #include <stdlib.h> #include <stdint.h> -#include "pins.h" +#include "pins.hpp" void ltc2400_init(); diff --git a/sw/main.cpp b/sw/main.cpp index f62fa27..fc61986 100644 --- a/sw/main.cpp +++ b/sw/main.cpp @@ -35,7 +35,8 @@ #include <avr/wdt.h> #include "common.hpp" -#include "pins.h" +#include "pins.hpp" +#include "relays.hpp" #include "ltc2400.h" extern "C" { @@ -55,8 +56,19 @@ constexpr double R_SHUNT = 5e-3; // Ohm constexpr double THRESHOLD_K1 = 1200.0 * 3600; constexpr double THRESHOLD_K2 = 1000.0 * 3600; constexpr double THRESHOLD_K3 = 600.0 * 3600; +constexpr double THRESHOLD_HYSTERESIS = 10.0 * 3600; + +constexpr double THRESHOLD_K1_UP = 1200.0 * 3600 - THRESHOLD_HYSTERESIS; +constexpr double THRESHOLD_K2_UP = 1000.0 * 3600 - THRESHOLD_HYSTERESIS; +constexpr double THRESHOLD_K3_UP = 600.0 * 3600 - THRESHOLD_HYSTERESIS; + +constexpr double THRESHOLD_K1_DOWN = 1200.0 * 3600 + THRESHOLD_HYSTERESIS; +constexpr double THRESHOLD_K2_DOWN = 1000.0 * 3600 + THRESHOLD_HYSTERESIS; +constexpr double THRESHOLD_K3_DOWN = 600.0 * 3600 + THRESHOLD_HYSTERESIS; + constexpr double MAX_CAPACITY = 1500.0 * 3600; -uint32_t current_capacity; +static uint32_t current_capacity; +static uint32_t previous_capacity; /* Storage of battery capacity in mC. * 3600 mC = 1mAh */ @@ -65,8 +77,9 @@ uint32_t current_capacity; uint32_t EEMEM stored_capacity1; uint32_t EEMEM stored_capacity2; uint32_t EEMEM stored_capacity3; -uint32_t last_store_time; /* In seconds */ +uint32_t last_store_time_seconds; +uint32_t last_threshold_calculation_seconds; timer_t last_ltc2400_measure; timer_t last_ltc2400_print_time; @@ -124,6 +137,8 @@ static void load_capacity_from_eeprom() current_capacity = cap2; // arbitrary #warning "Have a meaningful value for the very first startup value" } + + previous_capacity = current_capacity; } static void store_capacity_to_eeprom() @@ -139,6 +154,11 @@ static void store_capacity_to_eeprom() } } +static void handle_thresholds() +{ +#warning "compare previous_capacity and current_capacity to thresholds and toggle relays accordingly" +} + static char timestamp_buf[16]; static void send_message(const char *message) { @@ -201,6 +221,8 @@ int main() pins_set_status(true); + relays_init(); + // Initialise SPI and LTC2400 ltc2400_init(); @@ -247,8 +269,10 @@ int main() /* Load capacity stored in EEPROM */ current_capacity = 0; load_capacity_from_eeprom(); - last_ltc2400_print_time = last_ltc2400_measure = system_timer; - last_store_time = system_timer.get_seconds_atomic(); + last_ltc2400_print_time = + last_ltc2400_measure = system_timer; + last_store_time_seconds = + last_threshold_calculation_seconds = system_timer.get_seconds_atomic(); /* Enable interrupts */ sei(); @@ -265,7 +289,7 @@ int main() pins_set_status(time_now.get_ticks_atomic() == 0); - if (last_store_time + 3600 * 5 >= time_now.seconds_) { + if (last_store_time_seconds + 3600 * 5 >= time_now.seconds_) { store_capacity_to_eeprom(); } @@ -294,16 +318,22 @@ int main() if (accum > MAX_CAPACITY) { accum = MAX_CAPACITY; } current_capacity = lrint(accum); - -#warning "Handle thresholds for relays" } } + constexpr auto threshold_calculation_interval = 4; + if (last_threshold_calculation_seconds + threshold_calculation_interval > time_now.seconds_) { + last_threshold_calculation_seconds += threshold_calculation_interval; + handle_thresholds(); + } + const auto ltc2400_print_interval = timer_t(10, 0); if (last_ltc2400_print_time + ltc2400_print_interval > time_now) { last_ltc2400_print_time += ltc2400_print_interval; send_capacity(current_capacity); } + +#warning "Add call to relays_handle" } return 0; @@ -91,9 +91,3 @@ inline void pins_set_status(bool enable) } } -enum class relay_id_t { - K1, - K2, - K3, -}; - diff --git a/sw/relays.cpp b/sw/relays.cpp index 6604323..cb83626 100644 --- a/sw/relays.cpp +++ b/sw/relays.cpp @@ -23,5 +23,109 @@ */ #include "relays.hpp" +#include "pins.hpp" #include <stdio.h> #include <math.h> + +struct pending_event_t { + timer_t when; + relay_id_t relay; + bool set_not_reset; + bool level; + bool pending; +}; + +static constexpr int RELAY_SIGNAL_HOLD_TIME_MS = 400; + +static constexpr size_t PENDING_EVENTS_SIZE = 8; + +static pending_event_t pending_events[PENDING_EVENTS_SIZE]; + +void relays_init() +{ + for (size_t i = 0; i < PENDING_EVENTS_SIZE; i++) { + pending_events[i].pending = false; + } +} + +static void handle_event(pending_event_t& event) +{ + switch (event.relay) { + case relay_id_t::K1: + if (event.level) { + PORTD |= (event.set_not_reset ? PIND_K1_SET : PIND_K1_RESET); + } + else { + PORTD &= (event.set_not_reset ? ~PIND_K1_SET : ~PIND_K1_RESET); + } + break; + case relay_id_t::K2: + if (event.level) { + PORTC |= (event.set_not_reset ? PINC_K2_SET : PINC_K2_RESET); + } + else { + PORTC &= (event.set_not_reset ? ~PINC_K2_SET : ~PINC_K2_RESET); + } + break; + case relay_id_t::K3: + if (event.level) { + PORTC |= (event.set_not_reset ? PINC_K3_SET : PINC_K3_RESET); + } + else { + PORTC &= (event.set_not_reset ? ~PINC_K3_SET : ~PINC_K3_RESET); + } + break; + } + + event.pending = false; +} + +void relays_handle(const timer_t& time_now) +{ + for (size_t i = 0; i < PENDING_EVENTS_SIZE; i++) { + if (pending_events[i].pending and pending_events[i].when < time_now) { + handle_event(pending_events[i]); + } + } +} + +bool relays_toggle(relay_id_t relay, bool set_not_reset, const timer_t& when) +{ + size_t num_free_events = 0; + + for (size_t i = 0; i < PENDING_EVENTS_SIZE; i++) { + if (not pending_events[i].pending) { + num_free_events++; + } + } + + if (num_free_events < 2) { + return false; + } + + for (size_t i = 0; i < PENDING_EVENTS_SIZE; i++) { + if (not pending_events[i].pending) { + pending_events[i].pending = true; + pending_events[i].relay = relay; + pending_events[i].when = when; + pending_events[i].level = true; + pending_events[i].set_not_reset = set_not_reset; + break; + } + } + + for (size_t i = 0; i < PENDING_EVENTS_SIZE; i++) { + if (not pending_events[i].pending) { + pending_events[i].pending = true; + pending_events[i].relay = relay; + pending_events[i].when = when + + timer_t{0, timer_t::ms_to_ticks(RELAY_SIGNAL_HOLD_TIME_MS)}; + + pending_events[i].level = false; + pending_events[i].set_not_reset = set_not_reset; + break; + } + } + return true; +} + diff --git a/sw/relays.hpp b/sw/relays.hpp index f6fc18b..8dd180e 100644 --- a/sw/relays.hpp +++ b/sw/relays.hpp @@ -26,4 +26,11 @@ #include <stdlib.h> #include <stdint.h> +#include "common.hpp" + +void relays_init(); + +void relays_handle(const timer_t& time_now); + +bool relays_toggle(relay_id_t relay, bool set_not_reset, const timer_t& when); |