GPS function not working

I'm using 3 functions/ task using RTOS on esp32 . two tasks are working fine but the one which contains code for gps (on raftar change )is not working.

#include "arduino_secrets.h"
// TridentTD_EasyFreeRTOS32 - Version: Latest 


// FreeRTOS - Version: Latest 

/* 
  Sketch generated by the Arduino IoT Cloud Thing "Untitled"
  https://create.arduino.cc/cloud/things/adce9b5f-8b55-4f05-8c9b-a92bc44c94d2 

  Arduino IoT Cloud Variables description

  The following variables are automatically generated and updated when changes are made to the Thing

  String dig;
  int rftar;
  CloudLocation loc;
  bool btn;

  Variables which are marked as READ/WRITE in the Cloud Thing will also have functions
  which are called when their values are changed from the Dashboard.
  These functions are generated with the Thing and added at the end of this sketch.
*/
#include "thingProperties.h"
#include <Wire.h>
#include <TinyGPS++.h>
#include <SoftwareSerial.h>

float LAT;
float LONG;
int spd;
int pushbutton = 5;
int bzr = 2;



static const int RXPin = 16, TXPin = 17;   // GPIO 4=D2(conneect Tx of GPS) and GPIO 5=D1(Connect Rx of GPS
static const uint32_t GPSBaud = 9600; //if Baud rate 9600 didn't work in your case then use 4800

TinyGPSPlus gps; // The TinyGPS++ object
SoftwareSerial ss(RXPin, TXPin);  // The serial connection to the GPS device

//unsigned int move_index;         // moving index, to be used later
unsigned int move_index = 1;       // fixed location for now

 const int MPU_addr = 0x68; // I2C address of the MPU-6050
 int16_t AcX, AcY, AcZ, Tmp, GyX, GyY, GyZ;
 float ax = 0, ay = 0, az = 0, gx = 0, gy = 0, gz = 0;
 boolean fall = false; //stores if a fall has occurred
 boolean trigger1 = false; //stores if first trigger (lower threshold) has occurred
 boolean trigger2 = false; //stores if second trigger (upper threshold) has occurred
 boolean trigger3 = false; //stores if third trigger (orientation change) has occurred
 byte trigger1count = 0; //stores the counts past since trigger 1 was set true
 byte trigger2count = 0; //stores the counts past since trigger 2 was set true
 byte trigger3count = 0; //stores the counts past since trigger 3 was set true
 int angleChange = 0;
 

// Uncomment your board, or configure a custom board in Settings.h
//#define USE_WROVER_BOARD
//#define USE_TTGO_T7


void setup() {
  // Initialize serial and wait for port to open:
  
   Serial.begin(9600);
   pinMode(bzr, OUTPUT);
pinMode(pushbutton, INPUT_PULLUP);

  Serial.println();
  ss.begin(GPSBaud);
  checkGPS();
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
 
  
   Wire.begin();
   Wire.beginTransmission(MPU_addr);
   Wire.write(0x6B);  // PWR_MGMT_1 register
   Wire.write(0);     // set to zero (wakes up the MPU-6050)
   Wire.endTransmission(true);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  
  xTaskCreate(
  FELL,
  "pehla task",
  10000,
  NULL,
  1,
  NULL
  );
  
  xTaskCreate(
  WEAR,
  "2ra task",
  10000,
  NULL,
  1,
  NULL
  );
  
  xTaskCreate(
  LOCAT,
  "3ra task",
  10000,
  NULL,
  1,
  NULL
  );
 

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);
  
 
  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  // Your code here 

}

void mpu_read() {
   Wire.beginTransmission(MPU_addr);
   Wire.write(0x3B);  // starting with register 0x3B (ACCEL_XOUT_H)
   Wire.endTransmission(false);
   Wire.requestFrom(MPU_addr, 14, true); // request a total of 14 registers
   AcX = Wire.read() << 8 | Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
   AcY = Wire.read() << 8 | Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
   AcZ = Wire.read() << 8 | Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
   Tmp = Wire.read() << 8 | Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
   GyX = Wire.read() << 8 | Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
   GyY = Wire.read() << 8 | Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
   GyZ = Wire.read() << 8 | Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
 }

void checkGPS()                           //check GPS
{
  if (gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
     
  }
}


void onDigChange()  {
  // Add your code here to act upon Dig change
  
    //code for function 1
    mpu_read();
   ax = (AcX - 2050) / 16384.00;
   ay = (AcY - 77) / 16384.00;
   az = (AcZ - 1947) / 16384.00;
   gx = (GyX + 270) / 131.07;
   gy = (GyY - 351) / 131.07;
   gz = (GyZ + 136) / 131.07;
   // calculating Amplitute vactor for 3 axis
   float Raw_Amp = pow(pow(ax, 2) + pow(ay, 2) + pow(az, 2), 0.5);
   int Amp = Raw_Amp * 10;  // Mulitiplied by 10 bcz values are between 0 to 1
   Serial.println(Amp);
   
   
if (Amp <= 2 && trigger2 == false) { //if AM breaks lower threshold (0.4g)     
trigger1 = true;     
Serial.println("TRIGGER 1 ACTIVATED");   
}   
if (trigger1 == true) {     
trigger1count++;     
if (Amp >= 12) { //if AM breaks upper threshold (3g)
       trigger2 = true;
       Serial.println("TRIGGER 2 ACTIVATED");
      
       trigger1 = false; trigger1count = 0;
     }
   }
   if (trigger2 == true) {
     trigger2count++;
     angleChange = pow(pow(gx, 2) + pow(gy, 2) + pow(gz, 2), 0.5); Serial.println(angleChange);
     if (angleChange >= 30 && angleChange <= 400) { //if orientation changes by between 80-100 degrees       
trigger3 = true; trigger2 = false; trigger2count = 0;       
Serial.println(angleChange);  

Serial.println("TRIGGER 3 ACTIVATED");   
   
}   
}   
if (trigger3 == true) {     
trigger3count++;     
if (trigger3count >= 10) {
       angleChange = pow(pow(gx, 2) + pow(gy, 2) + pow(gz, 2), 0.5);
       //delay(10);
       Serial.println(angleChange);
       
       if ((angleChange >= 0) && (angleChange <= 10)) { //if orientation changes remains between 0-10 degrees         
fall = true; trigger3 = false; trigger3count = 0;         
Serial.println(angleChange);  

}       
else { //user regained normal orientation         
trigger3 = false; trigger3count = 0;         
Serial.println("TRIGGER 3 DEACTIVATED");   
     
}     
} 

}
   
if (fall == true) { //in event of a fall detection     
Serial.println("FALL DETECTED"); 
digitalWrite(bzr,HIGH); 
dig = "Rider fell";                                      //STRING
delay (1000);
fall = false;
digitalWrite(bzr,LOW);
}   
if (trigger2count >= 6) { //allow 0.5s for orientation change
     trigger2 = false; trigger2count = 0;
     Serial.println("TRIGGER 2 DECACTIVATED");
     
   }
   if (trigger1count >= 6) { //allow 0.5s for AM to break upper threshold
     trigger1 = false; trigger1count = 0;
     Serial.println("TRIGGER 1 DECACTIVATED");
     
   }
    
}


void onBtnChange()  {
  // Add your code here to act upon Btn change
 
    //code for function 2
    int buttonstate = digitalRead(pushbutton);
 //Serial.println(buttonstate);
 
 if (buttonstate == HIGH){
    btn = false;
    Serial.print(btn);
    }
   else if (buttonstate == LOW)
  { btn = true;
  
 }
}


void onRftarChange()  {
  // Add your code here to act upon Rftar change
 //code for function 1
    if (gps.location.isValid() ) 
  {    
    LAT = (gps.location.lat());     //Storing the Lat. and Lon. 
    LONG = (gps.location.lng()); 
    
    Serial.print("LAT:  ");
    Serial.println(LAT, 6);  // float to x decimal places
    Serial.print("LONG: ");
    Serial.println(LONG, 6);
    
    spd = gps.speed.kmph();               //get speed
    Serial.print("speed (kmph):  ");
     Serial.println(spd);
     
  
     rftar = spd;
     loc = {LAT,LONG};
     }
}


/*******************TASKS************************/

void FELL(void*parameters)  {
  // Add your code here to act upon Dig change
  for(;;){
    //code for function 1
    onDigChange();
     Serial.println( );
    vTaskDelay(1000/portTICK_PERIOD_MS);
  }
}
/*-------------------TASK BTN------------------------*/

void WEAR(void*parameters)  {
  // Add your code here to act upon Btn change
  for(;;){
    //code for function 2
    onBtnChange();
     Serial.println( );
    vTaskDelay(1000/portTICK_PERIOD_MS);
  }
}

/*------------------TASK SPD/LOCATION-------------------------*/

void LOCAT(void*parameters)  {
  // Add your code here to act upon Rftar change
  for(;;){
     while (ss.available() > 0) 
    {// sketch displays information every time a new sentence is correctly encoded.
      if (gps.encode(ss.read()))
    {
    onRftarChange();
    
     Serial.println( );
    vTaskDelay(1000/portTICK_PERIOD_MS);
  }
}
}

"raftar"?

Define "not working". Explain what you expect to happen, and what happens instead.

For hints on posting, see the "How to get the best out of the forum" post, linked at the head of every forum category.

void onRftarChange

Did you get the GPS working using a task first without all the other stuff or just put everything in at once?

Why are you using SoftwareSerial for the GPS when ESP32 has multiple hardware serial ports?

NO I haven't tried gps alone , that's the issue. I've problem converting the gps example code into a task.

Get the GPS working alone first. There are countless examples on line.

I'm trying to merge different sensors using multitasking on esp32. BUt task for GPS is not working;


#include <TinyGPS++.h>
#include <SoftwareSerial.h>

static const int RXPin = 16, TXPin = 17;   // GPIO 4=D2(conneect Tx of GPS) and GPIO 5=D1(Connect Rx of GPS
static const uint32_t GPSBaud = 9600; //if Baud rate 9600 didn't work in your case then use 4800

TinyGPSPlus gps; // The TinyGPS++ object

SoftwareSerial ss(RXPin, TXPin);  // The serial connection to the GPS device
int spd;       //Variable  to store the speed
                           
//unsigned int move_index;         // moving index, to be used later
unsigned int move_index = 1;       // fixed location for now

void loc(void*parameters){
  for(;;){
      
    //code for function 1
   while (ss.available() > 0) 
    {
      // sketch displays information every time a new sentence is correctly encoded.
      if (gps.encode(ss.read()))
        displayInfo();
  }
     Serial.println( );
    vTaskDelay(1000/portTICK_PERIOD_MS);
  }
}

void checkGPS(){
  if (gps.charsProcessed() < 10)
  {
    Serial.println(F("No GPS detected: check wiring."));
     
  }
}

void setup() {
  Serial.begin(9600);
  Serial.println();
  ss.begin(GPSBaud);
  checkGPS();
  // put your setup code here, to run once:
xTaskCreate(
  loc,
  "pehla task",
  100000,
  NULL,
  1,
  NULL
  );
}

void displayInfo()
{
  if (gps.location.isValid() ) 
  {    
    float latitude = (gps.location.lat());     //Storing the Lat. and Lon. 
    float longitude = (gps.location.lng()); 
    
    Serial.print("LAT:  ");
    Serial.println(latitude, 6);  // float to x decimal places
    Serial.print("LONG: ");
    Serial.println(longitude, 6);
    

    spd = gps.speed.kmph();               //get speed
    Serial.print("speed (kmph):  ");
     Serial.println(spd);
                    
  }
  
 Serial.println();
}

void loop() {
  // put your main code here, to run repeatedly:

}

Please do not crosspost

I have merged the two topics since it seems that the previous discussion, even though about a more complex version of the sketch, still might provide useful context for the helpers.

Best wishes for success with your project @farhan74

1 Like

Yes, we know that. It would help us to know if:

  1. Your GPS works in a simple GPS sketch.
  2. Your GPS task works when it is the only task.

Does your GPS have a clear view of the sky? You can't always get enough satellite signals when you are not outdoors or up against an exterior window.

It's working

Great. Please post your working code so others can benefit.

Sure, here I've converted the GPS example into a task (for multitasking on ESP32). The previous code had a software serial while this one doesn't. By creating different task like this, we can add different sensors and run them simultaneously without blocking each other.

#include <TinyGPSPlus.h>
// The TinyGPSPlus object
float LAT, LONG;
int spd;
TinyGPSPlus gps;
void loc(void*parameters) {
  for (;;) {
    //updateSerial();
    while (Serial2.available() > 0)
      if (gps.encode(Serial2.read()))
        displayInfo();
    if (millis() > 5000 && gps.charsProcessed() < 10)
    {
      Serial.println(F("No GPS detected: check wiring."));
      while (true);
    }
    Serial.println( );
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}

void setup() {
  Serial.begin(9600);
  Serial2.begin(9600);

  delay(3000);
  xTaskCreate(
    loc,
    "pehla task",
    10000,
    NULL,
    1,
    NULL
  );

}

void loop() {
}


void displayInfo()
{
  if (gps.location.isValid()) {
    LAT = (gps.location.lat());     //Storing the Lat. and Lon. 
    LONG = (gps.location.lng()); 
    
    Serial.print("LAT:  ");
    Serial.println(LAT, 6);  // float to x decimal places
    Serial.print("LONG: ");
    Serial.println(LONG, 6);
    
    spd = gps.speed.kmph();               //get speed
    Serial.print("speed (kmph):  ");
     Serial.println(spd);
      Serial.println();
     
  }
  else
  {
  Serial.print(F("INVALID"));
  }
}

One second may be too long a delay. At baud 9600, that's up to 960 characters arriving during that second. Do you know how large the Serial1 receive buffer is? You will get invalid NMEA sentences if you miss characters due to the buffer being full.

Also, look into vTaskDelayUntil to set a more accurate repetition period.

how much delay is suitable?

Experiment with it. Print the characters as they're received. Confirm that you always get complete NMEA sentences.

I was getting complete sentences but I changed the delay as you suggested, here's the result and the code:

void loc( void * pvParameters )
 {
 TickType_t xLastWakeTime;
 const TickType_t xFrequency = 1000;

     // Initialise the xLastWakeTime variable with the current time.
     xLastWakeTime = xTaskGetTickCount();

     for( ;; )
     {
         // Wait for the next cycle.
         vTaskDelayUntil( &xLastWakeTime, xFrequency );

         // Perform action here.
          while (Serial2.available() > 0)
      if (gps.encode(Serial2.read()))
        displayInfo();
    if (millis() > 5000 && gps.charsProcessed() < 10)
    {
      Serial.println(F("No GPS detected: check wiring."));
      while (true);
    }
    Serial.println( );
     }
 }
 

Capture

I meant print the actual characters that make up each sentence, not the resulting position / speed values that were computed from them.

Aren't we just concerned with just the values?