Using parsed data to call a function

I am trying to get data that has been received through bluetooth, and parsed to be used to call a function in the void loop(). I can see that the variable that I used when the parse happened is valued when I do a Serial.println(*raceType); but when I put *raceType == "Autocross" it doesnt start the function being called like I expected.

When I was not trying to send a group of data across from bluetooth, and I just sent Autocross, and had that stored in raceType (without the *) it would work prefectly. Now that I want to send a bigger group of data through to save into variables, I am running into some issues.

Here is the code that I am using

when I Serial.print() the variables that I have being set this is what the serial monitor shows.

[V][BluetoothSerial.cpp:307] esp_spp_cb(): ESP_SPP_DATA_IND_EVT len=31 handle=129
User ID: email@address.com
Race Type: Autocross
Starting Loc:

#include <Wire.h>
#include <SparkFun_LPS28DFW_Arduino_Library.h>
#include "ICM_20948.h"
#include <SparkFun_u-blox_GNSS_v3.h>
#include <MicroNMEA.h>
#include <BluetoothSerial.h>
#include "FS.h"
#include "SD.h"
#include "SPI.h"
#include <string.h>

#if !defined(CONFIG_BT_ENABLED) || !defined(CONFIG_BLUEDROID_ENABLED)
#error Bluetooth is not enabled! Please run `make menuconfig` to and enable it
#endif

BluetoothSerial SerialBT;


LPS28DFW pressureSensor;
uint8_t i2cAddress = LPS28DFW_I2C_ADDRESS_DEFAULT;
float degreesf;
float preshg;

SFE_UBLOX_GNSS myGNSS;
char nmeaBuffer[100];
MicroNMEA nmea(nmeaBuffer, sizeof(nmeaBuffer));

ICM_20948_I2C myICM;
#define AD0_VAL 1

//testing for message with parsing
const byte numChars = 64;
char receivedChars[numChars];
char tempChars[numChars];

char *userID[numChars] = {0};
char *raceType[numChars] = {0};
char *startingLoc[numChars] = {0};

boolean newData = false;


//timer for data
unsigned long previousMillis = 0;
const long interval = 500;

//sd card setup
File myFile;

void setup() {
  Serial.begin(115200);
  Wire.begin(21, 22);

  //BT initialize
  SerialBT.begin("IRP_Tracker");
  Serial.println("The device started, now you can pair it with bluetooth!");

  //SD Card initialize
  if (!SD.begin()) {
    Serial.println("Card Mount Failed");
    return;
  }
  uint8_t cardType = SD.cardType();

  if (cardType == CARD_NONE) {
    Serial.println("No SD card attached");
    return;
  }

  Serial.print("SD Card Type: ");
  if (cardType == CARD_MMC) {
    Serial.println("MMC");
  } else if (cardType == CARD_SD) {
    Serial.println("SDSC");
  } else if (cardType == CARD_SDHC) {
    Serial.println("SDHC");
  } else {
    Serial.println("UNKNOWN");
  }

  //accel initialize
  bool initializedAccel = false;
  while (!initializedAccel) {
    myICM.begin(Wire, AD0_VAL);

    Serial.print(F("Initialization of the sensor returned: "));
    Serial.println(myICM.statusString());
    if (myICM.status != ICM_20948_Stat_Ok) {
      Serial.println("Trying again...");
      delay(500);
    } else {
      initializedAccel = true;
    }
  }


  //  while (pressureSensor.begin(i2cAddress) != LPS28DFW_OK) {
  //    Serial.println("Error: LPS28DFW not connected, check wiring and I2C address!");
  //    delay(1000);
  //  }
  //  Serial.println("LPS28DFW connected!");

  //  if (myGNSS.begin() == false)
  //  {
  //    Serial.println(F("u-blox GNSS not detected at default I2C address. Please check wiring. Freezing."));
  //    while (1);
  //  }
}

void loop() {
  unsigned long currentMillis = millis();
  recvWithStartEndMarkers();
  if (newData == true) {
    strcpy(tempChars, receivedChars);
    parseData();
    showParsedData();
    newData = false;
  }

  if (*raceType == "Autocross" && (currentMillis - previousMillis >= interval)) {
    {
      previousMillis = currentMillis;
      Serial.println();
      Accel_Sensor();
    }
  } else if (*raceType == "DragRace" && (currentMillis - previousMillis >= interval)) {
    {
      previousMillis = currentMillis;
      Serial.println();
      Serial.print("Drag Racing Data");
    }
  } else if (*raceType == "Circuit" && (currentMillis - previousMillis >= interval)) {
      previousMillis = currentMillis;
      Serial.println();
      Serial.print("Circuit Racing Data");
  }


}

void recvWithStartEndMarkers() {
  static boolean recvInProgress = false;
  static byte ndx = 0;
  char startMarker = '<';
  char endMarker = '>';
  char rc;

  while (SerialBT.available() > 0 && newData == false) {
    rc = SerialBT.read();

    if (recvInProgress == true) {
      if (rc != endMarker) {
        receivedChars[ndx] = rc;
        ndx++;
        if (ndx >= numChars){
          ndx = numChars -1;
        }
      }
      else {
        receivedChars[ndx] = '\0';
        recvInProgress = false;
        ndx = 0;
        newData = true;
      }
    }
    else if (rc == startMarker) {
      recvInProgress = true;
    } 
  }
}

void parseData() {
  
  *userID = strtok(tempChars, ",");
  *raceType = strtok(NULL, ",");
  *startingLoc = strtok(NULL, ",");

}

void showParsedData() {
  Serial.print("User ID: ");
  Serial.println(*userID);
  Serial.print("Race Type: ");
  Serial.println(*raceType);
  Serial.print("Starting Loc: ");
  Serial.println(*startingLoc);

}


void P_Sensor() {

  pressureSensor.getSensorData();

  degreesf = ((pressureSensor.data.heat.deg_c) * 1.8) + 32;
  preshg = (pressureSensor.data.pressure.hpa) * 0.0295;
  Serial.print("Temp(F),");
  Serial.print(degreesf);
  Serial.print(",");
  Serial.print("Pres(hg),");
  Serial.print(preshg);
  Serial.print(",");
}

void Accel_Sensor() {

  if (myICM.dataReady()) {
    myICM.getAGMT();          // The values are only updated when you call 'getAGMT'
                              //    printRawAGMT( myICM.agmt );     // Uncomment this to see the raw values, taken directly from the agmt structure
    printScaledAGMT(&myICM);  // This function takes into account the scale settings from when the measurement was made to calculate the values with units
    //delay(500);
  } else {
    Serial.println("Waiting for data");
    delay(500);
  }
}


the above is testing if *raceType holds the value of the address that particular string is located at in memory.

in your parseData() you set raceType to a location within the received string.

try

  if  (! strcmp (raceType, "Autocross")

to see if the (sub) string pointed to by raceType matches (has the same values) as "Autocross").

  • don't understand why you make detection of the string also conditional on time

I tried what you suggested, and in the compile I got back the below error.

The millis in that line is to set how often data gets printed out. When I can get this issue you are giving suggestions on solved it wont just print out "Autocross", it will be showing sensor data. I didnt want it to spit things out super fast, I wanted to be able to control how fast that data is being printed.

esp32.ino: In function 'void loop()':
esp32.ino:124:37: error: cannot convert 'char**' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'
if (! strcmp(raceType, "Autocross") && (currentMillis - previousMillis >= interval)) {
^
esp32.ino:130:43: error: cannot convert 'char**' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'
} else if (! strcmp(raceType, "DragRace") && (currentMillis - previousMillis >= interval)) {
^
esp32.ino:136:42: error: cannot convert 'char**' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'
} else if (! strcmp(raceType, "Circuit") && (currentMillis - previousMillis >= interval)) {
^

exit status 1

Compilation error: cannot convert 'char**' to 'const char*' for argument '1' to 'int strcmp(const char*, const char*)'

  if (! strcmp(raceType, "Autocross") && (currentMillis - previousMillis >= interval)) {
    {
      previousMillis = currentMillis;
      Serial.println();
      Serial.print("Autocross Data");
    }
  } else if (! strcmp(raceType, "DragRace") && (currentMillis - previousMillis >= interval)) {
    {
      previousMillis = currentMillis;
      Serial.println();
      Serial.print("Drag Racing Data");
    }
  } else if (! strcmp(raceType, "Circuit") && (currentMillis - previousMillis >= interval)) {
      previousMillis = currentMillis;
      Serial.println();
      Serial.print("Circuit Racing Data");
  }

you defined raceType as an array of c-string pointers, not an array of chars (i.e. c-string)

just make it

char raceType[numChars];

same probably applies to other variables defined as char *

seems there are several things you don't want to do before a timer expires. why not put them all under one cond

    if (currentMillis - previousMillis >= interval) {
        previousMillis = currentMillis;

        Serial.println();

        if (! strcmp(raceType, "Autocross")
            Accel_Sensor();

        if (! strcmp(raceType, "Drag Racing Data")
            Serial.print("Drag Racing Data");

        if (! strcmp(raceType, "Circuit")
            Serial.print("Circuit Racing Data");
    }

and have recvWithStartEndMarkers () return the state of newData so it's result can be tested to process the input

    if (recvWithStartEndMarkers ()) {
        strcpy(tempChars, receivedChars);
        parseData();
        showParsedData();
        newData = false;
    }

I made the update, and when it compiles its giving an invalid conversion error

char userID[numChars];
char raceType[numChars];
char startingLoc[numChars];

esp32.ino: In function 'void parseData()':
esp32.ino:178:19: error: invalid conversion from 'char*' to 'char' [-fpermissive]
userID = strtok(tempChars, ",");
^
esp32.ino:179:21: error: invalid conversion from 'char
' to 'char' [-fpermissive]
raceType = strtok(NULL, ",");
^
esp32.ino:180:24: error: invalid conversion from 'char
' to 'char' [-fpermissive]
*startingLoc = strtok(NULL, ",");
^

exit status 1

Compilation error: invalid conversion from 'char*' to 'char' [-fpermissive]

Its highlighting these lines under void parseData()

  *userID = strtok(tempChars, ",");
  *raceType = strtok(NULL, ",");
  *startingLoc = strtok(NULL, ",");

sorry. my mistake. those variables need to be defined as char pointers

char *userID;
char *raceType;
char *startingLoc;

and should be

  userID = strtok(tempChars, ",");
  raceType = strtok(NULL, ",");
  startingLoc = strtok(NULL, ",");

So I made those tweaks, and it compiles without issues. After I connect with bluetooth and send data the esp32 reboots giving the below error

<email@address.com,Autocross> - this is the data that I am passing through the serial bluetooth app

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x4000142d PS : 0x00060530 A0 : 0x800d17c1 A1 : 0x3ffc7e00
A2 : 0x3ffc3cf5 A3 : 0x00000000 A4 : 0x000000ff A5 : 0x0000ff00
A6 : 0x00ff0000 A7 : 0xff000000 A8 : 0x00000000 A9 : 0x3ffc7dd0
A10 : 0x3ffc3cf5 A11 : 0x3f40014c A12 : 0x3ffe211c A13 : 0x00000001
A14 : 0x3ffbab08 A15 : 0x3ffc5f00 SAR : 0x0000000a EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x4000142d LEND : 0x4000143a LCOUNT : 0xffffffff

ELF file SHA256: 0000000000000000

Backtrace: 0x4000142d:0x3ffc7e00 0x400d17be:0x3ffc7e10 0x400d1a6f:0x3ffc7e30 0x400d9bc8:0x3ffc7e50 0x400909ca:0x3ffc7e70

Rebooting...

ets Jul 29 2019 12:21:46

The ones that you had suggested.

char userID[numChars] = {0};
char raceType[numChars] = {0};
char startingLoc[numChars] = {0};
  char* ptr;

  ptr = strtok(tempChars, ",");
  strcpy(userID, ptr);

  ptr = strtok(NULL, ",");
  strcpy(raceType, ptr);

  ptr = strtok(NULL, ",");
  strcpy(startingLoc, ptr);

This is what the void loop() looks like as well

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;

    if (! strcmp(raceType, "Autocross"))
    Serial.print("Autocross Data");

    if (! strcmp(raceType, "DragRace"))
    Serial.print("Drag Racing Data");

    if (! strcmp(raceType, "Circuit"))
    Serial.print("Circuit Racing Data");
  }

touching something that does not exists..
strtok can return a nullptr..

sorry.. ~q

ahh okay. Thats where I messed up, I wasnt sending data for all 3 values that it was looking for.

Thank you everyone for the help. Its much appreciated.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.