Hi Carlos y @beegee,
We bought the RAK13101 because there is no NB-IoT or LTE-M in our region. The device works but only when the USB cable and battery are connected. If the device is left with only battery power, it will not turn on again until the USB port is reconnected.
I deactivated the AT+QGNSSC=0 module, which deactivates the battery power but still does not turn on, and if I set it to 1 it does not turn on with the battery either.
I need to understand if this module is how it works or if I am doing something wrong.
I am using RUI3, but I disable the JOIN so that it does not connect to Lora and I can use the low consumption of RUI3
#include <Wire.h>
#include "inc/app.h"
#define POWER_KEY WB_IO5
String at_rsp = "";
String gps_data = "";
String leerBuffer() {
String respuesta = "";
while (Serial.available()) {
char c = Serial.read();
respuesta += c;
}
return respuesta;
}
// Función para obtener y procesar los datos GPS
void get_gps_data() {
char cmd[128] = {0};
unsigned long start_time = millis(); // Marcar el tiempo de inicio
bool datos_validos = false;
Serial1.println("ATI");
mc20_at("AT+QSCLK=0", 1000);
// Intentar obtener datos GPS durante un máximo de 60 segundos
while (millis() - start_time < 60000) { // 60 segundos
mc20_at("AT+QGNSSRD=\"NMEA/GGA\"", 5000); // Solicitar datos GPS
if (gps_data.length() > 0 && (gps_data.indexOf(",N,") > 0 || gps_data.indexOf(",S,") > 0)) {
// Validar si los datos GPS son válidos (latitud válida)
datos_validos = true;
break; // Salir del bucle si se encuentran datos válidos
}
delay(2000); // Esperar 2 segundos antes del siguiente intento
}
if (datos_validos) {
// Si se encontraron datos GPS válidos, enviar el paquete
send_packet();
} else {
Serial.println("No se encontraron datos GPS válidos dentro del tiempo límite.");
gps_data = ""; // Limpiar los datos si no fueron válidos
}
}
// Función para enviar los datos GPS a través de LoRa
void send_packet() {
char cmd[128] = {0};
String tmp = "";
if (gps_data.length() > 0) {
// Preparar y enviar los datos GPS procesados
tmp = "AT+QISEND=" + String(gps_data.length());
tmp.toCharArray(cmd, 128);
mc20_at(cmd, 1000); // Enviar la longitud de los datos
memset(cmd, 0, 128);
gps_data.toCharArray(cmd, 128); // Convertir datos GPS a formato de comando
mc20_at(cmd, 1000); // Enviar los datos GPS procesados
Serial.println("Datos GPS enviados:");
Serial.println(gps_data); // Mostrar los datos enviados
} else {
Serial.println("No hay datos GPS para enviar.");
}
gps_data = ""; // Limpiar los datos después de enviarlos
mc20_at("AT+QSCLK=2", 1000);
}
// Función principal (handler) que llama a las otras funciones
void handler(void *data) {
get_gps_data(); // Obtener y procesar los datos GPS
delay(2000); // Esperar 2 segundos antes de terminar
}
void setup()
{
String leerBuffer();
// Inicializar la comunicación serial
Serial.begin(115200);
while (!Serial)
{
delay(100);
}
// Inicialización del módem BG77
time_t serial_timeout = millis();
time_t timeout = millis();
bool moduleSleeps = true;
Serial1.begin(9600);
delay(1000);
Serial1.println("ATI");
while ((millis() - timeout) < 6000)
{
if (Serial1.available())
{
String result = Serial1.readString();
Serial.println("Modem response after start:");
Serial.println(result);
moduleSleeps = false;
}
}
if (moduleSleeps)
{
// Despertar el módulo
pinMode(POWER_KEY, OUTPUT);
digitalWrite(POWER_KEY, 0);
delay(1000);
digitalWrite(POWER_KEY, 1);
delay(2000);
digitalWrite(POWER_KEY, 0);
delay(1000);
}
// Configurar el módulo para cambiar a modo de comandos cuando DTR cambia a OFF
delay(1000);
Serial.println("MC20 power up!");
// Registrar en la red GSM
mc20_at("AT+CGACT=1,1", 3000);
mc20_at("AT+QGNSSC=0", 2000);
mc20_at("AT+COPS=?", 10000);
mc20_at("AT+COPS=0,2,\"714020\"", 5000);
mc20_at("AT+QICSGP=1,\"internet.tigo.pa\",\"\",\"\"", 5000);
//mc20_at("AT+COPS?", 3000);
//mc20_at("AT+CREG?", 3000);
//mc20_at("AT+CSQ", 2000);
mc20_at("AT+QPING=\"8.8.8.8\",100,4", 10000); // Ping DNS público de Google
// Conectar a TCP
mc20_at("AT+QIOPEN=\"TCP\",\"190.35.92.44\",10560", 10000);
mc20_at("AT+QSCLK=2", 1000);
// Crear el temporizador para ejecutar la función periódica
if (api.system.timer.create(RAK_TIMER_0, (RAK_TIMER_HANDLER)handler, RAK_TIMER_PERIODIC) != true) {
Serial.printf("Error al crear el temporizador.\r\n");
}
// Iniciar el temporizador con un intervalo de 1000 ms (1 segundo)
else if (api.system.timer.start(RAK_TIMER_0, 30000, NULL) != true) {
Serial.printf("Error al iniciar el temporizador.\r\n");
} else {
Serial.println("Temporizador creado y comenzado correctamente.");
}
}
void loop()
{
api.system.sleep.all();
// api.system.scheduler.task.destroy();
}
// Función para enviar comandos AT al módem y obtener respuestas
void mc20_at(char *at, uint16_t timeout)
{
char tmp[256] = {0};
int len = strlen(at);
strncpy(tmp, at, len);
uint16_t t = timeout;
tmp[len] = '\r';
Serial1.write(tmp);
delay(10);
while (t--)
{
if (Serial1.available())
{
at_rsp += char(Serial1.read());
}
delay(1);
}
if (at_rsp.indexOf("GNGGA") > 1)
{
gps_data = at_rsp;
gps_data = gps_data.substring(gps_data.indexOf("$"));
parse_gps(); // Parsear los datos GPS
}
Serial.println(at_rsp);
at_rsp = "";
}
// Función para procesar los datos GPS
void parse_gps() {
// Verificar que los datos contienen "GNGGA"
int gnggaIndex = gps_data.indexOf("GNGGA,");
if (gnggaIndex == -1) {
Serial.println("Error: 'GNGGA' no encontrado en los datos.");
gps_data = ""; // Limpiar datos si no son válidos
return;
}
// Recortar los datos desde "GNGGA"
gps_data = gps_data.substring(gnggaIndex + 6);
// Determinar si contiene "E" o "W" y recortar
int directionIndex = gps_data.indexOf("E");
if (directionIndex == -1) {
directionIndex = gps_data.indexOf("W");
}
if (directionIndex == -1) {
Serial.println("Error: No se encontró 'E' o 'W' en los datos.");
gps_data = ""; // Limpiar datos si no son válidos
return;
}
// Extraer la información necesaria (hora y coordenadas)
gps_data = gps_data.substring(0, directionIndex + 1);
//Serial.println("Datos GPS procesados:");
//Serial.println(gps_data);
}
``