diff --git a/main.c b/main.c index 33d5328..624f44c 100644 --- a/main.c +++ b/main.c @@ -6,6 +6,9 @@ #define SMS_END "\032\n" #define SIM800_DELAY_TIME 100 +#define TARGET_PHONE "+79208109798" +//#define TARGET_PHONE "+7huipissy69" + #define MEASUREMENTS 6 uint8_t sensor_measurements = 0; @@ -13,14 +16,19 @@ char systick_execution_enable = 0; uint16_t sensor_1[MEASUREMENTS]; uint16_t sensor_2[MEASUREMENTS]; + static volatile uint8_t timer0_time; ISR(TIMER0_OVF_vect) { timer0_time++; LED2_Toggle(); } -void sim800_wait_for(PGM_P str) { +uint8_t sim800_wait_for(PGM_P str) { + if (timeout_err) { + return -1; + } PGM_P curr_pos = str; + platform_wdt_start(); LED1_Set(); while (1) { char p = pgm_read_byte(curr_pos); @@ -29,6 +37,11 @@ void sim800_wait_for(PGM_P str) { } char c = uart_read_char(); + + if (timeout_err) { + break; + } + if (c == '\r') { continue; } @@ -40,10 +53,12 @@ void sim800_wait_for(PGM_P str) { } } LED1_Reset(); + platform_wdt_stop(); + return timeout_err; } -void sim800_wait_for_ok() { - sim800_wait_for(PSTR("OK\n")); +uint8_t sim800_wait_for_ok() { + return sim800_wait_for(PSTR("OK\n")); } void sim800_start() { @@ -63,34 +78,59 @@ void sim800_start() { uart_init(); uart_write_fstr(PSTR("AT\n")); - sim800_wait_for_ok(); + if (sim800_wait_for_ok()) { + return; + } // вырубить echo mode (повторяет команду, которая прилетела) ATE0 _delay_ms(SIM800_DELAY_TIME); uart_write_fstr(PSTR("ATE1\n")); // TODO поставить 0 чтобы модем лишнюю херню не слал - sim800_wait_for_ok(); + if (sim800_wait_for_ok()) { + return; + } // после готовности смс все сразу станет понятно - sim800_wait_for(PSTR("SMS Ready\n")); + if (sim800_wait_for(PSTR("SMS Ready\n"))) { + return; + } - while (1) { - _delay_ms(SIM800_DELAY_TIME); + for (uint8_t i = 0; i < 40; i++) { + _delay_ms(500); uart_write_fstr(PSTR("AT+CREG?\n")); - sim800_wait_for(PSTR("+CREG: ")); + if (sim800_wait_for(PSTR("+CREG: "))) { + return; + } + char mode = uart_read_char(); uart_read_char(); // запятая char status = uart_read_char(); + + if (timeout_err) { + return; + } + if (mode == '0' && status == '1') { - break; + return; } } + + timeout_err = 1; } void sim800_stop() { // вырубить модуль - uart_write_fstr(PSTR("AT+CPOWD=1\n")); - sim800_wait_for(PSTR("DOWN\n")); // придет NORMAL POWER DOWN - uart_deinit(); + if (timeout_err) { + uart_deinit(); + GSM_KEY_Set(); + _delay_ms(1100); + GSM_KEY_Reset(); + _delay_ms(500); + } else { + uart_write_fstr(PSTR("AT+CPOWD=1\n")); + sim800_wait_for(PSTR("DOWN\n")); // придет NORMAL POWER DOWN + uart_deinit(); + } + GSM_EN_Reset(); LED2_Reset(); } @@ -102,6 +142,11 @@ uint16_t sim800_get_battery() { for (uint8_t i = 0; i < 2; i++) { sim800_wait_for(PSTR(",")); } + + if (timeout_err) { + return -1; + } + // по идее тут будет напряжение // 4 цифры, но мне не важно на самом деле сколько uint16_t result = 0; @@ -130,7 +175,7 @@ void sim800_prepare_sms() { uart_write_fstr(PSTR("AT+CMGF=1\n")); // PDU режим sim800_wait_for_ok(); _delay_ms(SIM800_DELAY_TIME); - uart_write_fstr(PSTR("AT+CMGS=\"+79208109798\"\n")); // PDU режим + uart_write_fstr(PSTR("AT+CMGS=\"" TARGET_PHONE "\"\n")); // PDU режим sim800_wait_for(PSTR(">")); } @@ -159,6 +204,10 @@ void sim800_send_telemetry() { uint16_t bat = sim800_get_battery(); sim800_prepare_sms(); + if (timeout_err) { + return; + } + char buff[6]; // sprintf(buff, "F1=%d F2=%d\033\n", sensor_1, sensor_2); @@ -185,7 +234,6 @@ void sim800_send_telemetry() { } // все измерения забрали - sensor_measurements = 0; uart_write_fstr(PSTR("BAT=")); num2buff(buff, bat); @@ -238,22 +286,40 @@ int main() { LED2_Set(); _delay_ms(100); LED2_Reset(); - _delay_ms(5000); + _delay_ms(1000); // врубаем модем - sim800_start(); - - // рабочая отправка сообщений - sim800_prepare_sms(); - _delay_ms(SIM800_DELAY_TIME); - uart_write_fstr(PSTR("I'm working!" SMS_END)); // сама смска - sim800_wait_for_sms_send(); - - // отправляем сразу же телеметрию read_sensors(); - sim800_send_telemetry(); - // рубим модем - sim800_stop(); + + for (uint8_t i = 0; i < 3; i++) { + // рабочая отправка сообщений + sim800_start(); + + sim800_prepare_sms(); + _delay_ms(SIM800_DELAY_TIME); + uart_write_fstr(PSTR("I'm working!" SMS_END)); // сама смска + sim800_wait_for_sms_send(); + + // отправляем сразу же телеметрию + sim800_send_telemetry(); + // рубим модем + sim800_stop(); + if (!timeout_err) { + break; + } else { + _delay_ms(500); + timeout_err = 0; + } + } + + sensor_measurements = 0; + + if (timeout_err) { + for (;;) { + _delay_ms(100); + LED2_Toggle(); + } + } MCUCR |= (1 << SE); @@ -266,6 +332,21 @@ int main() { "rjmp main_loop\n"); } +void try_to_send_telemetry() { + for (uint8_t i = 0; i < 3; i++) { + sim800_start(); + sim800_send_telemetry(); + sim800_stop(); + if (!timeout_err) { + break; + } else { + _delay_ms(500); // время между попытками + timeout_err = 0; + } + } + sensor_measurements = 0; +} + ISR(TIMER1_OVF_vect) { static uint16_t time = 0; static char exec = 0; @@ -299,10 +380,9 @@ ISR(TIMER1_OVF_vect) { read_sensors(); // если измерений 6 (и мало ли больше), то отправляем смс if (sensor_measurements >= MEASUREMENTS) { - sim800_start(); - sim800_send_telemetry(); - sim800_stop(); + try_to_send_telemetry(); } + cli(); MCUCR |= (1 << SE); exec = 0; @@ -314,9 +394,7 @@ ISR(TIMER1_OVF_vect) { MCUCR &= ~(1 << SE); sei(); read_sensors(); - sim800_start(); - sim800_send_telemetry(); - sim800_stop(); + try_to_send_telemetry(); cli(); MCUCR |= (1 << SE); exec = 0; diff --git a/platform.c b/platform.c index 85f5728..2eab04f 100644 --- a/platform.c +++ b/platform.c @@ -7,6 +7,11 @@ #include #include +volatile uint8_t timeout_err; + +ISR(WDT_OVERFLOW_vect) { + timeout_err = 1; +} void platform_init() { // инициализация GPIO @@ -40,6 +45,16 @@ void platform_init() { sei(); } +void platform_wdt_start() { + timeout_err = 0; + asm volatile ("wdr"); + WDTCSR = (1 << WDIE) | (1 << WDP3) | (1 << WDP0); // 8 sec, interrupt enable +} + +void platform_wdt_stop() { + WDTCSR = (1 << WDP3) | (1 << WDP0); // stop +} + void uart_init() { // U2X=1, baud=9600, error=0.2%, f=1M UBRRH = 0; @@ -80,8 +95,11 @@ void uart_write_fstr(PGM_P str) { } char uart_read_char() { - while (!(UCSRA & (1 << RXC))) - ; + while (!(UCSRA & (1 << RXC))) { + if (timeout_err) { + return -1; + } + } return UDR; } diff --git a/platform.h b/platform.h index 963beef..ef0a405 100644 --- a/platform.h +++ b/platform.h @@ -8,16 +8,18 @@ #include #include +extern volatile uint8_t timeout_err; + +#define WDR() asm volatile ("wdr") /** * Инициализация модуля */ void platform_init(); -/** - * Переводит камень в режим ожидания, выход из ожидания по прерыванию - */ -void platform_wait_for_interrupt(); +void platform_wdt_start(); + +void platform_wdt_stop(); void uart_init(); void uart_deinit();