Здравствуйте.
Было времечко на работе, решила написать код настройки модема.
Перезагрузка пока-что программная, потом будет сброс питания.
SoftwareSerial исчезнет, отладочные сообщения уберутся.
Решила совместить проверку наличия сети с проверкой ответа модуля на команды (таймаут)
Спойлер
#include <avr/wdt.h>
#include <SoftwareSerial.h>
SoftwareSerial SIM800(9, 2);
#define MAX_BUF 50 //Размер буфера
#define INT_NET_FOUND 5000 //Интервал проверки сети если сеть найдена
#define INT_NET_NOT_FOUND 3000//Интервал проверки сети если сеть не найдена
#define TIMEOUT_TIME 3000 //Время наступления таймаута
#define MAX_NUM_TIMEOUT_ERR 2 //Максимальное количество ошибок таймаута
#define MAX_NUM_NET_ERR 5 //Максимальное количество ошибок поиска сети
#define MODEM_CONF_COMMAND_INT 1000 //Интервал отправки команд настройки модема
#define MODEM_NOT_CONF 0 //Модем не настроен
#define MODEM_CONF_ROGRESS 1 //Идёт настройка модема
#define MODEM_CONF 2 //Модем настроен
uint8_t amount_command; // Количество команд первоначальной настройки модема
//Команды для первоначальной настройки модема
char *conf_commands[] = {
"ATE1",//0---Включить эхо.
"ATV1",//1---Полные заголовки и текстовые овтеты.
"AT+CLIP=1",//2--- // Включить АОН.
"AT+CMGF=1",//3---Включить TextMode для SMS.
"AT+CPBS=\"SM\"",//4---Память SIM-карты.
};
//Команды для первоначальной настройки модема
void setup() {
wdt_disable();
Serial.begin(9600);
SIM800.begin(9600);
Serial.println(F("Start!"));
SIM800.println(F("AT"));
amount_command = sizeof(conf_commands) / sizeof(conf_commands[0]);
wdt_enable (WDTO_4S);
}
void loop() {
wdt_reset();
static uint8_t pos_buf;//Позиция в буфере
static char buffers[MAX_BUF];//Буфер
static uint32_t modem_setup_tmr;//Таймер настройки модема
static uint16_t modem_setup_int = INT_NET_NOT_FOUND;//Интервал настройки модема
static uint8_t modem_setup_step;//Этап настройки модема
static uint8_t timeout_err_count;//Счётчик ошибок таймаута
static uint8_t net_err_count;//Счётчик ошибок поиска сети
static uint8_t initial_modem_setup; //Начальная настройка модема
static uint8_t command_number; //Номер команды настройка модема
static bool response_number;
switch (modem_setup_step) {
case 0://Проверяю наличие сети
if (millis() - modem_setup_tmr >= modem_setup_int) {
modem_setup_tmr = millis();
modem_setup_step = 1;
SIM800.println(F("AT+CCALR?"));
Serial.print(F("Net_check. Time: "));
Serial.print(millis());
Serial.print(F(" Interval: "));
Serial.print(modem_setup_int);
Serial.println("");
}
break;
case 1://Если нет ответа в течении TIMEOUT_TIME, значит ошибка таймаут
if (millis() - modem_setup_tmr >= TIMEOUT_TIME) {
modem_setup_tmr = millis();
modem_setup_step = 0;
modem_setup_int = INT_NET_NOT_FOUND;
timeout_err_count++;
if (initial_modem_setup == MODEM_CONF_ROGRESS) {
initial_modem_setup = MODEM_NOT_CONF;
command_number = 0;
}
Serial.print(F("Timeout. Time: "));
Serial.print(millis());
Serial.print(F(" Error: "));
Serial.print(timeout_err_count);
Serial.println("");
}
break;
case 2://Сеть найдена
modem_setup_step = 4;
net_err_count = 0;
modem_setup_int = INT_NET_FOUND;
Serial.println(F("Network_found:"));
//Если сеть найдена и модем не настроен
if (initial_modem_setup == MODEM_NOT_CONF) {
initial_modem_setup = MODEM_CONF_ROGRESS;
modem_setup_tmr = millis();
modem_setup_step = 5;
Serial.println(F("Initial_modem_setup:"));
}
break;
case 3://Сеть не найдена
modem_setup_step = 4;
net_err_count++;
modem_setup_int = INT_NET_NOT_FOUND;
Serial.print(F("Network_non_found. Error"));
Serial.print(net_err_count);
Serial.println("");
break;
case 4://Если ответ пришёл раньше чем TIMEOUT_TIME
modem_setup_tmr = millis();
modem_setup_step = 0;
timeout_err_count = 0;
break;
case 5://Настройка модема
if (millis() - modem_setup_tmr >= MODEM_CONF_COMMAND_INT) {
modem_setup_tmr = millis();
modem_setup_step = 1;
response_number = false;
SIM800.println(conf_commands[command_number]);
Serial.print(conf_commands[command_number]);
Serial.print(F(" Timer: "));
Serial.print(millis());
Serial.println("");
}
break;
case 6://Если команда настройки модема выполнена
Serial.print(conf_commands[command_number]);
Serial.print(F(" --- OK"));
Serial.println("");
command_number++;
if (command_number > amount_command - 1) {
Serial.println(F("Modem_setup_OK"));
modem_setup_tmr = millis();
modem_setup_step = 0;
initial_modem_setup = MODEM_CONF;
} else {
modem_setup_tmr = millis();
modem_setup_step = 5;
}
break;
}//switch(check_step)
//Если предел ошибок таймаута или сети, перезагрузка модема
if (timeout_err_count > MAX_NUM_TIMEOUT_ERR || net_err_count > MAX_NUM_NET_ERR) {
SIM800.println(F("AT+CFUN=1,1"));
timeout_err_count = 0;
net_err_count = 0;
modem_setup_step = 0;
initial_modem_setup = MODEM_NOT_CONF;
modem_setup_tmr = millis();
command_number = 0;
Serial.println(F("Modem_reset:"));
}
if (Serial.available())SIM800.write(Serial.read());
if (SIM800.available()) {
uint8_t temp = SIM800.read();
if (temp) {
buffers[pos_buf] = temp;
pos_buf++;
if (pos_buf >= MAX_BUF) {
memset(buffers, 0, MAX_BUF);
pos_buf = 0;
} else {
if (temp == '\n' && pos_buf > 1 && buffers[pos_buf - 2] == '\r') {
if (modem_setup_step == 1) {
if (strstr (buffers, "+CCALR: 1") != NULL)modem_setup_step = 2;
if (strstr (buffers, "+CCALR: 0") != NULL)modem_setup_step = 3;
if (!response_number && strstr (buffers, conf_commands[command_number]) != NULL)response_number = true;
if (response_number && strstr (buffers, "OK") != NULL) modem_setup_step = 6;
}
//Serial.println(buffers);
memset(buffers, 0, MAX_BUF);
pos_buf = 0;
}//if(temp
}//if(pos_buf >= MAX_BUF) {
}//if(temp) {
}//if(SIM800.available()){
}//loop
Если void modem_setup(uint8_t parametr = 0) Получаю ошибку
если void modem_setup() Ошибки нет
F:\Users\Iren\Documents\Arduino\SIM800L\SIM800L.ino: In function 'void loop()':
SIM800L:23:3: error: 'modem_setup' was not declared in this scope
modem_setup();
^~~~~~~~~~~
F:\Users\Iren\Documents\Arduino\SIM800L\SIM800L.ino:23:3: note: suggested alternative: 'memset'
modem_setup();
^~~~~~~~~~~
memset
exit status 1
'modem_setup' was not declared in this scope
Я не понял - как именно Ардуино ИДЕ связывает ино-файлы. Поэтому я создаю файлы с расширением .h в той же папке и подключаю в основном ино-файле. (Закрой ИДЕ, создай файлы .h и открой ино-файл. Файлы .h «подтянутся» автоматом).
Может быть так делать и «не правильно», но я делаю и никаких проблем у меня с этим нет. По крайней мере я точно знаю где что подключено.
Основная проблема, это логика обработки данных от модема, вы ждёте \rn последовательность, после чего обрабатываете данные. В общем путь правильный, но например представьте что OKrn пришло в последние байты буфера, а он у вас переполнился, O пришло, а остальное нет.
Или буфер кольцевым делать или размером килобайт или больше.
Нет, вопрос не в том, как это должно выглядеть в конце, а в том, как этого добиться наиболее рациональным образом.
Последовательность “закрыть IDE, насоздавать .h/.cpp файлов, открыть IDE” действительно выглядит немного странно.