So I use ESP32 with SIM808 Module to provide me with GPRS and also GPS function. I have tried Http request and GPS, but never combined them. I want to combine request function and GPS function using RTOS so I can have GPS read without waiting for Http data. I use TinyGSMClient lib to handle the connection.
TinyGSM use modem to handle the serial:
HardwareSerial SerialAT(2);
TinyGsm modem(SerialAT);
But I need to use this modem for both Https and GPS at the same time. I knew there would be errors. I got this response:
Initializing modem...
Performing HTTPS GET request... Requesting current GPS/GNSS/GLONASS location
Latitude:-7.30793715
Longitude:112.75830841
Response status code: 200
Enabling GPS/GNSS/GLONASS and waiting 15s for warm-up
Response:
Head \u003cb\u003esoutheast\u003c/b\u003e
Performing HTTPS GET request... Response status code: 200
Requesting current GPS/GNSS/GLONASS location
Performing HTTPS GET request... failed to connect
-2
Enabling GPS/GNSS/GLONASS and waiting 15s for warm-up
Performing HTTPS GET request... failed to connect
-2
Requesting current GPS/GNSS/GLONASS location
Latitude:-7.30793810
Longitude:112.75831604
Performing HTTPS GET request... failed to connect
-2
Requesting current GPS/GNSS/GLONASS location
Performing HTTPS GET request... failed to connect
-2
Well for summary, at first everything is okay until the http request suddenly doesn't return anything. After that only GPS working, and http request return -2 and sometimes -3 error code, which is:
static const int HTTP_ERROR_API =-2;
// Spent too long waiting for a reply
static const int HTTP_ERROR_TIMED_OUT =-3;
// The response from the server is invalid, is it definitely an HTTP
// server?
So http work for a while before it doesn't get a reply anymore, but GPS still work. Sometimes GPS can't return the location too. I think http and gps interfere each other because they both use the same modem. My full code is:
#define TINY_GSM_MODEM_SIM808
// Set serial for debug console (to the Serial Monitor, default speed 115200)
#define SerialMon Serial
// #define TINY_GSM_DEBUG SerialMon
HardwareSerial SerialAT(2);
#if !defined(TINY_GSM_RX_BUFFER)
#define TINY_GSM_RX_BUFFER 650
#endif
// Define the serial console for debug prints, if needed
// #define TINY_GSM_DEBUG SerialMon
// set GSM PIN, if any
#define GSM_PIN ""
// flag to force SSL client authentication, if needed
//#define TINY_GSM_SSL_CLIENT_AUTHENTICATION
// Your GPRS credentials, if any
const char apn[] = "YourAPN";
const char gprsUser[] = "";
const char gprsPass[] = "";
// Server details
const char server[] = "maps.googleapis.com";
const char resource[] = "/maps/api/directions/json?origin=-7.282058008443928,112.79494675412441&destination=-7.288465791966643,112.80169150994796&mode=walking&key=AIzaSyCu7ZP3tACUVSbS_tHCHfD3Ix76BRwz4IQ";
const int port = 443;
#include <TinyGsmClient.h>
#include <HttpClient.h>
TinyGsm modem(SerialAT);
TinyGsmClientSecure client(modem);
HttpClient http(client, server, port);
TaskHandle_t Task1;
TaskHandle_t GPStask;
// LED pins
const int led = LED_BUILTIN;
void setup() {
// Set console baud rate
SerialMon.begin(115200);
delay(10);
pinMode(led, OUTPUT);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
Task1code, /* Task function. */
"Task1", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
&Task1, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
//create a task that will be executed in the Task1code() function, with priority 1 and executed on core 0
xTaskCreatePinnedToCore(
GPSTask, /* Task function. */
"GPS Task", /* name of task. */
10000, /* Stack size of task */
NULL, /* parameter of the task */
0, /* priority of the task */
&GPStask, /* Task handle to keep track of created task */
0); /* pin task to core 0 */
delay(500);
// !!!!!!!!!!!
// Set your reset, enable, power pins here
// !!!!!!!!!!!
SerialMon.println("Wait...");
// Set GSM module baud rate
// TinyGsmAutoBaud(SerialAT, GSM_AUTOBAUD_MIN, GSM_AUTOBAUD_MAX);
SerialAT.begin(57600);
delay(6000);
// Restart takes quite some time
// To skip it, call init() instead of restart()
SerialMon.println("Initializing modem...");
modem.init();
if (GSM_PIN && modem.getSimStatus() != 3) { modem.simUnlock(GSM_PIN); }
}
void loop() {
if (!modem.gprsConnect(apn, gprsUser, gprsPass)) {
SerialMon.println(" fail");
delay(10000);
return;
}
SerialMon.print(F("Performing HTTPS GET request... "));
http.connectionKeepAlive(); // Currently, this is needed for HTTPS
int err = http.get(resource);
if (err != 0) {
SerialMon.println(F("failed to connect"));
SerialMon.println(err);
delay(10000);
return;
}
int status = http.responseStatusCode();
SerialMon.print(F("Response status code: "));
SerialMon.println(status);
if (!status) {
delay(10000);
return;
}
String body = http.responseBody();
String instruction= findHtmlInstructions(body);
SerialMon.println(F("Response:"));
SerialMon.println(instruction);
}
/// Util
String findHtmlInstructions(const String& jsonString) {
String target = "\"html_instructions\" : \"";
int startIndex = jsonString.indexOf(target);
if (startIndex != -1) {
startIndex += target.length();
int endIndex = jsonString.indexOf("\"", startIndex);
if (endIndex != -1) {
return jsonString.substring(startIndex, endIndex);
}
}
return ""; // Return an empty string if not found
}
//Task1code: blinks an LED every 1000 ms
void Task1code( void * pvParameters ){
Serial.print("Task1 running on core ");
Serial.println(xPortGetCoreID());
for(;;){
digitalWrite(led, HIGH);
delay(1000);
digitalWrite(led, LOW);
delay(1000);
}
}
void GPSTask( void * pvParameters) {
while(1){
if(!modem.enableGPS()){
SerialMon.println("Enabling GPS/GNSS/GLONASS and waiting 15s for warm-up");
vTaskDelay(15*1000/portTICK_RATE_MS);
}
float lat2 = 0;
float lon2 = 0;
float speed2 = 0;
float alt2 = 0;
int vsat2 = 0;
int usat2 = 0;
float accuracy2 = 0;
int year2 = 0;
int month2 = 0;
int day2 = 0;
int hour2 = 0;
int min2 = 0;
int sec2 = 0;
for (int8_t i = 15; i; i--) {
SerialMon.println("Requesting current GPS/GNSS/GLONASS location");
if (modem.getGPS(&lat2, &lon2, &speed2, &alt2, &vsat2, &usat2, &accuracy2,
&year2, &month2, &day2, &hour2, &min2, &sec2)) {
SerialMon.print("Latitude:");
SerialMon.println(String(lat2, 8));
SerialMon.print("Longitude:");
SerialMon.println(String(lon2, 8));
break;
} else {
SerialMon.println("Couldn't get GPS/GNSS/GLONASS location, retrying in 15s.");
vTaskDelay(15*1000/portTICK_RATE_MS);
}
}
vTaskDelay(5*1000/portTICK_RATE_MS);
}
}
I'm new to RTOS concept. I put the http request code at loop function because I read something about it has to be in core 1. I have tried to put it at core 0 but I got a lot of errors. So I put it at loop because loop function handled in core 1. I put GPS function to core 0, so I can multitask incase http request take a lot of stack to complete. What should I do to prevent http task and gps task interfering each other?
And are my assumption about http interfere with gps is correct?