diff --git a/include/aprsis.h b/include/aprsis.h index 6dbe92d..0809c75 100644 --- a/include/aprsis.h +++ b/include/aprsis.h @@ -97,7 +97,7 @@ telemetry_description_t aprsis_send_description_telemetry(uint8_t async, void aprsis_igate_to_aprsis(AX25Msg *msg, const char * callsign_with_ssid); void aprsis_send_server_conn_status(const char * callsign_with_ssid); -void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok); +void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok, uint16_t voltage); void aprsis_send_gpsstatus(const char * callsign_with_ssid); char * aprsis_get_tx_buffer(void); diff --git a/include/etc/pwr_save_configuration.h b/include/etc/pwr_save_configuration.h index 63ec4f6..ea2daa8 100644 --- a/include/etc/pwr_save_configuration.h +++ b/include/etc/pwr_save_configuration.h @@ -19,12 +19,12 @@ /** * This is the restore voltage a battery must be charged to for ParaMETEO to restore it's normal operation */ -#define PWR_SAVE_STARTUP_RESTORE_VOLTAGE_DEF 1230u // 12.3V +#define PWR_SAVE_STARTUP_RESTORE_VOLTAGE_DEF 1200u // 12.0V /** * This is voltage above which controller will switch to PWSAVE_AGGRESV */ -#define PWR_SAVE_AGGRESIVE_POWERSAVE_VOLTAGE 1150u // 11.5V +#define PWR_SAVE_AGGRESIVE_POWERSAVE_VOLTAGE 1130u // 11.3V /** * How long in minutes the controller will sleep in L7 state between checking diff --git a/include/packet_tx_handler.h b/include/packet_tx_handler.h index 75487f4..53eda0c 100644 --- a/include/packet_tx_handler.h +++ b/include/packet_tx_handler.h @@ -14,6 +14,7 @@ typedef struct packet_tx_counter_values_t { uint8_t beacon_counter; uint8_t wx_counter; + uint8_t gsm_wx_counter; uint8_t telemetry_counter; uint8_t telemetry_desc_counter; uint8_t kiss_counter; @@ -28,6 +29,7 @@ void packet_tx_handler(const config_data_basic_t * const config_basic, const con void packet_tx_get_current_counters(packet_tx_counter_values_t * out); void packet_tx_set_current_counters(packet_tx_counter_values_t * in); int16_t packet_tx_get_minutes_to_next_wx(void); +uint8_t packet_tx_is_gsm_meteo_pending(void); void packet_tx_force_gsm_status(void); #endif /* PACKET_TX_HANDLER_H_ */ diff --git a/include/pwr_save.h b/include/pwr_save.h index cc02e1f..8efde57 100644 --- a/include/pwr_save.h +++ b/include/pwr_save.h @@ -79,7 +79,7 @@ * * * Transitions between states depends on configuration and value of config_data_powersave_mode_t. - * If 'powersave_keep_gsm_always_enabled' is set to one, the controller will swtich to modem M4a instead of M4 + * If 'powersave_keep_gsm_always_enabled' is set to one, the controller will switch to modem M4a instead of M4 * * ====================================================================================================================================| * | Mode | Powersave Mode | | @@ -93,14 +93,19 @@ * | DIGI + WX + GSM | PWSAVE_NORMAL | C3 --- (1 minute before WX frame)---> C0 -> C3 ; if WX_INTERVAL < 5 minutes | * | DIGI + WX + GSM | PWSAVE_AGGRESV | C2 --- (1 minute before WX frame)---> C0 -> C2 ; no matter WX_INTERVAL | * | WX + GSM | PWSAVE_NONE | C0 | - * | WX + GSM | PWSAVE_NORMAL | M4 --- (1 minute before WX frame)---> C0 -> M4 | - * | WX + GSM (only) | PWSAVE_AGGRESV | L6 --- (2 minute before WX frame)---> C0 -> L6 ; if WX_INTERVAL < 5 minutes | - * | WX + GSM (only) | PWSAVE_AGGRESV | L7 --- (2 minute before WX frame)---> M4 --- (30 sec before)---> C0 -> L7 | + * | WX + GSM | PWSAVE_NORMAL | M4 --- (2 minute before WX frame)---> C0 -> M4 | + * | WX + GSM (only) | PWSAVE_AGGRESV | L7 --- (2 minute before WX frame)---> C0 -> L7 | * | WX | PWSAVE_NONE | M4 --- (2 minute before WX frame)---> C1 -> M4 | * | WX | PWSAVE_NORMAL | L7 --- (2 minute before WX frame)---> C1 -> L7 | * | WX | PWSAVE_AGGRESV | L7 --- (1 minute before WX frame)---> M4 --- (30 sec before)---> C1 -> L7 | * ====================================================================================================================================| * + * Note from October 31st. State machine has been changed sligtly for + * PWSAVE_NORMAL and PWSAVE_AGGRESIVE for WX + GSM configuration. It was + * simplified by turning GSM module off completely when it is not needed. + * It has more sense and it is less risky, as it eliminate a possible situation + * when GSM module will change it internal state while controller is sleeping + * (like GPRS will die for some reason, or a SIM card will stop working) */ diff --git a/src/aprsis.c b/src/aprsis.c index aead08e..8baaddb 100644 --- a/src/aprsis.c +++ b/src/aprsis.c @@ -932,7 +932,7 @@ void aprsis_send_server_conn_status(const char * callsign_with_ssid) { gsm_sim800_tcpip_async_write((uint8_t *)aprsis_packet_tx_buffer, aprsis_packet_tx_message_size, aprsis_serial_port, aprsis_gsm_modem_state); } -void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok) { +void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok, uint16_t voltage) { if (aprsis_logged == 0) { return; @@ -945,10 +945,11 @@ void aprsis_send_loginstring(const char * callsign_with_ssid, uint8_t rtc_ok) { aprsis_packet_tx_message_size = snprintf( aprsis_packet_tx_buffer, APRSIS_TX_BUFFER_LN - 1, - "%s>AKLPRZ,qAR,%s:>[rtc_ok: %d][aprsis]%s\r\n", + "%s>AKLPRZ,qAR,%s:>[rtc_ok: %d][vbat: %d][aprsis]%s\r\n", callsign_with_ssid, callsign_with_ssid, rtc_ok, + voltage, aprsis_login_string_reveived); gsm_sim800_tcpip_async_write((uint8_t *)aprsis_packet_tx_buffer, aprsis_packet_tx_message_size, aprsis_serial_port, aprsis_gsm_modem_state); diff --git a/src/main.c b/src/main.c index 3004d99..e477d08 100644 --- a/src/main.c +++ b/src/main.c @@ -1263,7 +1263,7 @@ int main(int argc, char* argv[]){ if (rte_main_trigger_gsm_loginstring_packet == 1 && gsm_sim800_tcpip_tx_busy() == 0) { rte_main_trigger_gsm_loginstring_packet = 0; - aprsis_send_loginstring((const char *)&main_callsign_with_ssid, system_is_rtc_ok()); + aprsis_send_loginstring((const char *)&main_callsign_with_ssid, system_is_rtc_ok(), rte_main_battery_voltage); } if (rte_main_trigger_gsm_telemetry_values == 1 && gsm_sim800_tcpip_tx_busy() == 0) { @@ -1638,7 +1638,7 @@ int main(int argc, char* argv[]){ } // inhibit any power save switching when modem transmits data - if (!main_afsk.sending && rte_main_woken_up == 0) { + if (!main_afsk.sending && rte_main_woken_up == 0 && packet_tx_is_gsm_meteo_pending() == 0) { pwr_save_pooling_handler(main_config_data_mode, main_config_data_basic, packet_tx_get_minutes_to_next_wx(), rte_main_average_battery_voltage, rte_main_battery_voltage); } diff --git a/src/packet_tx_handler.c b/src/packet_tx_handler.c index 4b1d73c..36d6b61 100644 --- a/src/packet_tx_handler.c +++ b/src/packet_tx_handler.c @@ -64,6 +64,9 @@ uint8_t packet_tx_trigger_tcp = 0; uint8_t packet_tx_meteo_gsm_interval = 2; uint8_t packet_tx_meteo_gsm_counter = 0; +//!< Flag set to one after weather packet has been just send to APRS-IS via GPRS modem and the modem is probably transmitting now +uint8_t packet_tx_meteo_gsm_has_been_sent = 0; + #define API_TRIGGER_STATUS (1 << 1) #define API_TRIGGER_METEO (1 << 2) #define APRSIS_TRIGGER_METEO (1 << 3) @@ -131,32 +134,14 @@ inline void packet_tx_multi_per_call_handler(void) { void packet_tx_tcp_handler(void) { #ifdef STM32L471xx + // TODO: fixme currently there is no way to have APRS-IS and rest api + // client working at the same time + aprsis_return_t aprsis_result = APRSIS_UNKNOWN; if ((packet_tx_trigger_tcp & APRSIS_TRIGGER_METEO) != 0) { - // TODO: fixme - if (gsm_sim800_tcpip_tx_busy() == 0) { + if (gsm_sim800_tcpip_tx_busy() == 0 && aprsis_connected == 1) { - if (aprsis_connected == 0) { - aprsis_result = aprsis_connect_and_login_default(0); - - if (aprsis_result == APRSIS_OK) { - // send APRS-IS frame, if APRS-IS is not connected this function will return immediately - aprsis_send_wx_frame( - rte_wx_average_windspeed, - rte_wx_max_windspeed, - rte_wx_average_winddirection, - rte_wx_temperature_average_external_valid, - rte_wx_pressure_valid, - rte_wx_humidity_valid, - main_callsign_with_ssid, - main_string_latitude, - main_string_longitude, - main_config_data_basic); - } - } - else { - // send APRS-IS frame, if APRS-IS is not connected this function will return immediately aprsis_send_wx_frame( rte_wx_average_windspeed, rte_wx_max_windspeed, @@ -168,11 +153,16 @@ void packet_tx_tcp_handler(void) { main_string_latitude, main_string_longitude, main_config_data_basic); + + // clear the flag requesting weather packet transmission + packet_tx_trigger_tcp ^= APRSIS_TRIGGER_METEO; + + // set this flag to one to inhibit power saving state machine + // for a while (10 seconds) when GPRS modem is communicating + // with the GSM radio network and sending the data independently + // from the controller + packet_tx_meteo_gsm_has_been_sent = 1; } - // TODO: fixme - // clear the bit - packet_tx_trigger_tcp ^= APRSIS_TRIGGER_METEO; - } } else if ((packet_tx_trigger_tcp & API_TRIGGER_STATUS) != 0) { @@ -222,6 +212,11 @@ void packet_tx_tcp_handler(void) { packet_tx_trigger_tcp ^= RECONNECT_APRSIS; // } } + else { + // after 10 second from setting this flag the packet should be + // sent + packet_tx_meteo_gsm_has_been_sent = 0; + } #endif } @@ -337,7 +332,7 @@ void packet_tx_handler(const config_data_basic_t * const config_basic, const con #endif #ifdef PARAMETEO - if (packet_tx_meteo_gsm_counter >= packet_tx_meteo_gsm_interval) { + if (packet_tx_meteo_gsm_counter >= packet_tx_meteo_gsm_interval && gsm_sim800_gprs_ready == 1) { if (main_config_data_gsm->aprsis_enable == 0 && main_config_data_gsm->api_enable == 1) { // and trigger API wx packet transmission packet_tx_trigger_tcp |= API_TRIGGER_METEO; @@ -612,6 +607,7 @@ void packet_tx_get_current_counters(packet_tx_counter_values_t * out) { if (out != 0x00) { out->beacon_counter = packet_tx_beacon_counter; out->wx_counter = packet_tx_meteo_counter; + out->gsm_wx_counter = packet_tx_meteo_gsm_counter; out->telemetry_counter = packet_tx_telemetry_counter; out->telemetry_desc_counter = packet_tx_telemetry_descr_counter; out->kiss_counter = packet_tx_meteo_kiss_counter; @@ -635,16 +631,26 @@ void packet_tx_set_current_counters(packet_tx_counter_values_t * in) { if (in->kiss_counter != 0) packet_tx_meteo_kiss_counter = in->kiss_counter; + + if (in->gsm_wx_counter != 0) + packet_tx_meteo_gsm_counter = in->gsm_wx_counter; } else { packet_tx_beacon_counter = 0; packet_tx_meteo_counter = 2; + packet_tx_meteo_gsm_counter = 0; packet_tx_telemetry_counter = 0; packet_tx_telemetry_descr_counter = 10; packet_tx_meteo_kiss_counter = 0; } } +/** + * Returns how many minutes is left to next weather packet (on radio network!!). + * Used in power saving state machine and to periodically reset VHF radio + * if this feature is enabled in configuration + * @return + */ int16_t packet_tx_get_minutes_to_next_wx(void) { if (packet_tx_meteo_interval != 0) { return packet_tx_meteo_interval - packet_tx_meteo_counter; @@ -654,6 +660,30 @@ int16_t packet_tx_get_minutes_to_next_wx(void) { } } +/** + * This function checks if at the moment any weather packet is scheduled to be sent + * to APRS-IS server, or this packet has been just sent and GPRS module probably + * communicate with GSM network now. The result of this check is used to + * inhibit power saving state machine temporary, not to turn off or disable + * GSM modem while it is talking with GSM radio network. + * @return + */ +uint8_t packet_tx_is_gsm_meteo_pending(void) { + uint8_t out = 0; +#ifdef STM32L471xx + + if (gsm_sim800_gprs_ready == 1 && (packet_tx_trigger_tcp & APRSIS_TRIGGER_METEO) != 0) { + out = 1; + } + + if (packet_tx_meteo_gsm_has_been_sent != 0) { + out = 1; + } +#endif + + return out; +} + void packet_tx_force_gsm_status(void) { #ifdef STM32L471xx packet_tx_gsm_status_sent = 0; diff --git a/src/pwr_save.c b/src/pwr_save.c index 365418b..1da674b 100644 --- a/src/pwr_save.c +++ b/src/pwr_save.c @@ -246,6 +246,7 @@ static void pwr_save_exit_after_last_stop2_cycle(void) { // rewind all timers in packet tx handler as they were no updated when micro was sleeping // sleep shall be always set as wx packet interval minus one minute timers.wx_counter += (pwr_save_sleep_time_in_seconds / 60); + timers.gsm_wx_counter += (pwr_save_sleep_time_in_seconds / 60); timers.beacon_counter += (pwr_save_sleep_time_in_seconds / 60); timers.kiss_counter += (pwr_save_sleep_time_in_seconds / 60); timers.telemetry_counter += (pwr_save_sleep_time_in_seconds / 60); @@ -350,6 +351,8 @@ int pwr_save_switch_mode_to_c1(void) { // disconnect APRS-IS connection if it is established aprsis_disconnect(); + NVIC_DisableIRQ( USART3_IRQn ); + // close and deconfigure port used for communication with GPRS module srl_close(main_gsm_srl_ctx_ptr); @@ -397,6 +400,8 @@ void pwr_save_switch_mode_to_c2(void) { // disconnect APRS-IS connection if it is established aprsis_disconnect(); + NVIC_DisableIRQ( USART3_IRQn ); + // close and deconfigure port used for communication with GPRS module srl_close(main_gsm_srl_ctx_ptr); @@ -478,6 +483,8 @@ int pwr_save_switch_mode_to_m4(void) { // disconnect APRS-IS connection if it is established aprsis_disconnect(); + NVIC_DisableIRQ( USART3_IRQn ); + // close and deconfigure port used for communication with GPRS module srl_close(main_gsm_srl_ctx_ptr); @@ -560,6 +567,8 @@ void pwr_save_switch_mode_to_i5(void) { // disconnect APRS-IS connection if it is established aprsis_disconnect(); + NVIC_DisableIRQ( USART3_IRQn ); + // close and deconfigure port used for communication with GPRS module srl_close(main_gsm_srl_ctx_ptr); @@ -1109,49 +1118,18 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t } else { // WX + GSM (only) - if (timers->wx_transmit_period >= 5) { - // if stations is configured to send wx packet less frequent than every 5 minutes + if (minutes_to_wx > WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES) { + backup_reg_set_monitor(17); - if (minutes_to_wx > WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES) { - backup_reg_set_monitor(17); + // if there is more than WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES minutes to wx packet + pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); // TODO: !!! - // if there is more than one minute to wx packet - pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); // TODO: !!! + reinit_gprs = 1; - reinit_gprs = 1; - - } - else { - if (pwr_save_seconds_to_wx <= 50) { - // if there is 30 seconds or less to next wx packet - reinit_sensors = pwr_save_switch_mode_to_c0(); - } - else { - // if there is 30 to 60 seconds to next wx packet - if (config->powersave_keep_gsm_always_enabled == 0){ - reinit_sensors = pwr_save_switch_mode_to_m4(); - - //reinit_gprs = 1; - } - else { - reinit_sensors = pwr_save_switch_mode_to_m4a(); - } - } - } } else { - // if station is configured to sent wx packet in every 5 minutes or more often - - if (minutes_to_wx > WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES) { - backup_reg_set_monitor(17); - - pwr_save_switch_mode_to_l6((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); // TODO: !!! - - reinit_gprs = 0; - } - else { - reinit_sensors = pwr_save_switch_mode_to_c0(); - } + // if there is 30 seconds or less to next wx packet + reinit_sensors = pwr_save_switch_mode_to_c0(); } } } @@ -1169,7 +1147,7 @@ config_data_powersave_mode_t pwr_save_pooling_handler( const config_data_mode_t if (minutes_to_wx > WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES) { backup_reg_set_monitor(17); - // if there is more than one minute to send wx packet + // if there is more than WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES minutes to send wx packet pwr_save_switch_mode_to_l7((timers->wx_transmit_period * 60) - (WAKEUP_PERIOD_BEFORE_WX_FRAME_IN_MINUTES * 60)); reinit_gprs = 1;