Parsing Multiple Values & Assigning as Integers from Received Bluetooth Data

Hello programmer comrades. My code is half-working. Or maybe 30% working.

I am attempting to create an app which pairs with a device (based on NodeMCU ESP32) capable of controlling various atmospheric devices (air conditioners, heaters, etc). I have already created the atmospheric control device successfully (with ample help from this forum) in the past, so only the app portion is really new.

As far as I can tell, the app (made on MIT App Inventor), works properly. And this isn't really the right place to ask about that anyway. But all the app really needs to do is send a data string, which is appearing properly in Serial Monitor.

My issue is, once I successfully receive the data string over Bluetooth, nothing happens. Based on what I read and attempted to restructure from Serial Input Basics, particularly Example #5, it should detect that the incoming data uses the start & end characters < and > to identify the data as a desired string, parse the string for my 7 values separated by commas, and then print those 7 values into the Serial Monitor. It does none of this, and I'm not sure why.

I'll also say this is only my second-ever coding project and I have no former training/education and a "learn as I go" approach, so I may have missed something extremely obvious or tried to do something "illegal". I tried doing due diligence like reading the Serial Input Basics threads and many Bluetooth guides, and servo arm controls since that seems like the closest analog to what I'm doing here. But ultimately, new coder who needs help, and appreciates it.

To reiterate, my ultimate goal here is to receive a data string from an app over Bluetooth, parse that data string for 7 separate values, and assign those values to integers (or anything with the same effect) until the controller is updated next (possibly weeks or months). Then, use those integers in other applications not yet added to the code. Only the first step is happening.

Code attached, as well as an image of the relevant portion of my MIT App Inventor code but that's pretty straightforward and, as I said, seems to be working.

Controller Progress Code.txt (4.73 KB)

I think, this serial pass through code is consuming all the characters, so there are none left for recvWithStartEndMarkers() to work with.

void loop()
{ if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  if (SerialBT.available()) {
    Serial.write(SerialBT.read());
  }

aarg:
I think, this serial pass through code is consuming all the characters, so there are none left for recvWithStartEndMarkers() to work with.

void loop()

{ if (Serial.available()) {
    SerialBT.write(Serial.read());
  }
  if (SerialBT.available()) {
    Serial.write(SerialBT.read());
  }

If so, how would you recommend I resolve that? I understand what some parts of the Serial Input Basics code mean enough to modify them, but I don't understand what that section means enough to understand why it would be a problem. It seems like it's saying - if a serial transmission is available, send the data via bluetooth which was read via serial input. Which, if so... I don't understand why that's there and seems like I could remove it? But again, only partial understanding so not 100% confident what I can modify without causing issue.

You have two Serial connections. There is "BluetoothSerial" to and from the bluetooth module on the ESP32 and the ESP32 processor. There is also "Serial" to and from the Serial Monitor of the IDE to the ESP32 processor. There is TX and RX on both the channels.

You can use the techniques of Serial Input Basics to read each of these channels. Do not use the pass thru echo methods of what looks like the Random Nerd ESP Bluetooth tutorial.

I would delete the pass through/echo block of code.

It sounds like you are want to receive messages from the phone to the bluetooth on the ESP32. In that case you will use the recvWithStartEndMarkers() on the BluetoothSerial channel. When you have received the complete message from the phone, you can echo it back out over Serial to the monitor like you do with showParsedData(). You could echo it back to the phone if you wanted as well.

The android app sending the message to the ESP32 will need to use the start and end markers.

Using the expressions of your code you need to change recvWithStartEndMarkers() like this

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

You have two Serial connections. There is "BluetoothSerial" to and from the bluetooth module on the ESP32 and the ESP32 processor. There is also "Serial" to and from the Serial Monitor of the IDE to the ESP32 processor. There is TX and RX on both the channels.

Makes sense.

I would delete the pass through/echo block of code.

I tried to do so. It compiled fine but now, instead of receiving a message and eliciting no response, it receives no message and elicits no response. Screenshots attached of Serial Monitor.

After removing the suggested portion, nothing would show up in the Serial Monitor, whether I sent it through my Serial Bluetooth Terminal or my MIT App Inventor controller app.

It sounds like you are want to receive messages from the phone to the bluetooth on the ESP32. In that case you will use the recvWithStartEndMarkers() on the BluetoothSerial channel. When you have received the complete message from the phone, you can echo it back out over Serial to the monitor like you do with showParsedData(). You could echo it back to the phone if you wanted as well.

All correct, and I should definitely echo it back to the phone, that'll be a future step.

The android app sending the message to the ESP32 will need to use the start and end markers.

I believe it did, but check my screenshot to confirm I'm using them properly please?

Using the expressions of your code you need to change recvWithStartEndMarkers() like this

Perhaps I misunderstood but I get the error 'rc' was not declared in this scope and I'm not sure where to put the bracket to fix that. Tried a few different spots.

void loop() {

  //DATA RECEIVAL AND PARSING
  {
    while (SerialBT.available() > 0 && newData == false) {
      rc = SerialBT.read();
      recvWithStartEndMarkers();
      if (newData == true) {
        strcpy(tempChars, receivedChars);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with \0
        parseData();
        showParsedData();
        newData = false;
      }
    }
  }
}

Appreciate the help, from you and/or anyone else who can offer it

Perhaps I misunderstood but I get the error 'rc' was not declared in this scope

Yes. I did not mean for you to just plunk those lines into the code, but rather to modify the recvWithStartEndMarkers function so that it was using the correct serial connection.

cattledog:
Yes. I did not mean for you to just plunk those lines into the code, but rather to modify the recvWithStartEndMarkers function so that it was using the correct serial connection.

Sounds like a good suggestion. Being as I have no complete idea how to go about doing so, is that something I would learn from the Serial Input Basics thread, or...

EDIT: Never mind, I think I get it now. Thank you. Will be back if I'm wrong lol

Well, it's definitely doing something now after I modified the recv function, but definitely not what I want it to do.

This was sending the same string from the MIT controller app as shown in my last screenshot, with start and end markers.

Code and serial monitor screenshot attached. At least now I have something new to look into and hopefully solve, but maybe one of you guys can point me in the right direction - this forum is good about that.

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x40056722  PS      : 0x00060130  A0      : 0x8005682e  A1      : 0x3ffc87e0  
A2      : 0x3ffbd8d0  A3      : 0x00000000  A4      : 0x00000000  A5      : 0x0000000a  
A6      : 0x00000000  A7      : 0x00000008  A8      : 0x8000be99  A9      : 0x3ffc87d0  
A10     : 0x3ffbd8d0  A11     : 0x00060123  A12     : 0x00060120  A13     : 0x0ccccccc  
A14     : 0x00000000  A15     : 0x00000004  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x4000142d  LEND    : 0x4000143a  LCOUNT  : 0xfffffffd  

Backtrace: 0x40056722:0x3ffc87e0 0x4005682b:0x3ffc8810 0x400566cd:0x3ffc8830 0x400d1923:0x3ffc8850 0x400d1af3:0x3ffc8870 0x400d2bed:0x3ffc8890 0x4008e0bd:0x3ffc88b0

Rebooting...

Controller Progress Code 1.1.txt (4.59 KB)

I'm not terribly familiar with the ESP32, but from google and the error message I think the code is crashing in parseData()when it gets to the pointer declaration char * strtokIndx; which because of the lack of an initial value points to memory location 0. This is OK in the AT328 architecture, but not for the esps.

Try to modify the parseData() function so that it begins like this

void parseData() {      // split the data into its parts

 // char * strtokIndx; // this is used by strtok() as an index

  char * strtokIndx = strtok(tempChars, ",");     // get the first part - the 
  string

cattledog:
I'm not terribly familiar with the ESP32, but from google and the error message I think the code is crashing in parseData()when it gets to the pointer declaration char * strtokIndx; which because of the lack of an initial value points to memory location 0. This is OK in the AT328 architecture, but not for the esps.

Try to modify the parseData() function so that it begins like this

void parseData() {      // split the data into its parts

// char * strtokIndx; // this is used by strtok() as an index

char * strtokIndx = strtok(tempChars, ",");     // get the first part - the
 string

It's definitely from a memory issue from what I've read on Google. Some people also suggested, with others confirming, that it's just a hardware issue that effects many - but not all - ESP32's. I have two others, so I guess I'll try that, but I sort of doubt that's the problem.

I tried your fix (I think - code below in case I misinterpreted again) and it still gives the same error. In case it narrows it down at all, I also realized it crashes even if you send something without the proper 7-integer format. I doubt it does though. More googling to do, hopefully.

void parseData() {      // split the data into its parts

  // char * strtokIndx; // this is used by strtok() as an index

  char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer

}

//============

void showParsedData() {
  Serial.print("Day Temp ");
  Serial.println(Tday);
  Serial.print("Day Humidity ");
  Serial.println(RHday);
  Serial.print("Night Temp ");
  Serial.println(Tnight);
  Serial.print("Night Humidity ");
  Serial.println(RHnight);
  Serial.print("Temperature Deadbar ");
  Serial.println(Tdeadbar);
  Serial.print("Emergency Temperature Deadbar ");
  Serial.println(Tedeadbar);
  Serial.print("Humidity Deadbar ");
  Serial.println(RHdeadbar);

  delay(20);
}

Installed ESPExceptionDecoder and got the following info:

PC: 0x40056722
EXCVADDR: 0x00000000

Decoding stack results
0x400d1911: parseData() at C:\Users\chans\Documents\Arduino\Controller with App\Controller_with_App/Controller_with_App.ino line 138
0x400d1af3: loop() at C:\Users\chans\Documents\Arduino\Controller with App\Controller_with_App/Controller_with_App.ino line 73
0x400d2bed: loopTask(void*) at C:\Users\chans\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 19
0x4008e0bd: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

Line 19 is blank so it sounds like line 73 (parse.Data), line 138 (converting the Tedeadbar value to integer), and maybe line 143 (closing bracket) are the issues. So, I tried removing the last two integer definitions just because I thought it was odd that 138, second-to-last integer, would be identified as the issue and wondered if I exceeded some limit for memory or such. Well, upon doing so, the crash was the same and ESPExceptionDecoder traced it back to Line 135 instead. So that didn't help.

Otherwise Google hasn't been fruitful for me so far in this issue. Will try different ESP's tomorrow probably.

I tried your fix (I think - code below in case I misinterpreted again) and it still gives the same error.

You got the correction correctly :slight_smile: . Is the error message exactly the same including the EXCVADDR 0x00000000 and EXCCAUSE 0x0000001c ?

I was hoping the error was a null pointer exception which is where Mr Google leads me.

In case it narrows it down at all, I also realized it crashes even if you send something without the proper 7-integer format. I doubt it does though.

Very interesting. If you don't send a message between < > and newData never gets set to true, the code can not be entering parseData().

If you go back to the original code with the serial monitor version of recvWithStartEndMarkers() and enter data from the keyboard, do you still see the crash?

This can help separate out the particular issues of the bluetooth channel from the standard serial interface to the monitor.

cattledog:
You got the correction correctly :slight_smile: . Is the error message exactly the same including the EXCVADDR 0x00000000 and EXCCAUSE 0x0000001c ?

I was hoping the error was a null pointer exception which is where Mr Google leads me.

Very interesting. If you don't send a message between < > and newData never gets set to true, the code can not be entering parseData().

If you go back to the original code with the serial monitor version of recvWithStartEndMarkers() and enter data from the keyboard, do you still see the crash?

This can help separate out the particular issues of the bluetooth channel from the standard serial interface to the monitor.

Hahahaha I just tried it again and it works now I think! I didn't change... anything at all... from the last time it failed but it works! I think - I need to set it up to test by LED's now, but it gave the proper output*, quoted below for posterity.

*Mostly. There's some weirdness going on - the numbers sent by the app don't sync properly with the numbers output by the app, but I'm sure I can figure that part out now that the connection works.

Thank you for all your help, seriously.

Day Temp 14
Day Humidity 34
Night Temp 24
Night Humidity 6
Temperature Deadbar 5
Emergency Temperature Deadbar 2
Humidity Deadbar 2

Nope. Premature celebration, but I think I found the cause of the problem.

If I have 5 integer-redefining atoi functions, the code works. If I have 7, it crashes. That sounds like a memory problem. Any suggestions on how I might handle that?

I'll post the full code tomorrow - had to be asleep forever ago - but here's the section I'm talking about.

FUNCTIONAL:

void parseData() {      // split the data into its parts

  // char * strtokIndx; // this is used by strtok() as an index

  char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer
}

NONFUNCTIONAL (but what I need to accomplish):

void parseData() {      // split the data into its parts

  // char * strtokIndx; // this is used by strtok() as an index

  char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer
}

If I have 5 integer-redefining atoi functions, the code works. If I have 7, it crashes. That sounds like a memory problem. Any suggestions on how I might handle that?

It appears that you are really zeroing in on a consistent definition of the problem.

Please post your current complete send and receive codes, and a typical message.

Are you certain that your receivedChars[] buffer is large enough for the longest message?

I have seen some issues in the past with strtok in the ESP environment with corrupted messages and missing terminators.

There can also be issues with lengthy operations triggering resets due to the wireless networking code not maintaining itself periodically, but I would not think this is your issue.

cattledog:
Are you certain that your receivedChars[] buffer is large enough for the longest message?

Not at all certain, no. Just learning from tutorials and modifying the aspects that don't work. How would I check something like that? I tried the probably-obvious-but-unsuccessful solution of,

const byte numChars = 32;

changed to

const byte numChars = 64;

or even, as I've seen in random posts,

const byte numChars = 1000;

but that didn't solve the crash.

I've attached the versions of the code which do and do not experience the crash error. The difference is removing these lines:

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer

but I suspect that removing any two lines would fix it. Although the really strange thing is, now, when I reboot, even if I reuse the exact "FUNCTIONAL" code snippet with 5 redefinitions I posted earlier in the thread, it still gives the crash. Maybe it really is a hardware issue?

Also, error information below:

aF⸮⸮`⸮&⸮Yke⸮H0The device started, now you can pair it with bluetooth!
This demo expects 3 pieces of data - text, an integer and a floating point value
Enter data in this style <HelloWorld, 12, 24.7>  

Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC      : 0x40056722  PS      : 0x00060130  A0      : 0x8005682e  A1      : 0x3ffc8840  
A2      : 0x3ffbd8d0  A3      : 0x00000000  A4      : 0x00000000  A5      : 0x0000000a  
A6      : 0x00000000  A7      : 0x00000008  A8      : 0x8000be99  A9      : 0x3ffc8830  
A10     : 0x3ffbd8d0  A11     : 0x00060123  A12     : 0x00060120  A13     : 0x0ccccccc  
A14     : 0x00000000  A15     : 0x00000004  SAR     : 0x00000018  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000000  LBEG    : 0x4000142d  LEND    : 0x4000143a  LCOUNT  : 0xfffffffd  

Backtrace: 0x40056722:0x3ffc8840 0x4005682b:0x3ffc8870 0x400566cd:0x3ffc8890 0x400d1923:0x3ffc88b0 0x400d1af3:0x3ffc88d0 0x400d2bed:0x3ffc88f0 0x4008e0bd:0x3ffc8910

Rebooting...

Which, when put into ESP Exception Decoder, gives the output

PC: 0x40056722
EXCVADDR: 0x00000000

Decoding stack results
0x400d1923: parseData() at C:\Users\chans\Documents\Arduino\Controller V2\Controller_V2/Controller_V2.ino line 144
0x400d1af3: loop() at C:\Users\chans\Documents\Arduino\Controller V2\Controller_V2/Controller_V2.ino line 76
0x400d2bed: loopTask(void*) at C:\Users\chans\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 19
0x4008e0bd: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

Progress - Code with Error.txt (4.47 KB)

Progress - Code without Error.txt (4.16 KB)

I just noticed a major error in parseData() which is likely the cause of all the issues we are seeing. There are seven entered values, but because of some inadvertant carry over from the original example ("message from pc"), we were parsing 8 times and getting into memory areas the program did not "own". You mentioned that the numbers didn't sometimes line up correctly, and that was also part of this. Lets see where we are when you fix parseData().

This is what you currently have. We call strtok 8 times and we run over the end of the data string.

void parseData() {      // split the data into its parts

  // char * strtokIndx; // this is used by strtok() as an index

  char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer
}

Eliminate the first strtok. Please verify that this is correct for the variables and the order in which they appear.

void parseData() {      // split the data into its parts

  //char * strtokIndx; // this is used by strtok() as an index
  //char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  //strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC
  //strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  
  char * strtokIndx = strtok(tempChars, ",");
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer

}

Please post your code in the future using the code tags like I have done.

New parseData() code with same old issue:

void parseData() {      // split the data into its parts

  // char * strtokIndx; // this is used by strtok() as an index

  //char * strtokIndx = strtok(tempChars, ",");     // get the first part - the string
  //strcpy(messageFromPC, strtokIndx); // copy it to messageFromPC

  //strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
   char * strtokIndx = strtok(tempChars, ",");
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer
}

Guru Meditation Error: Core 1 panic'ed (LoadProhibited). Exception was unhandled.
Core 1 register dump:
PC : 0x40056722 PS : 0x00060130 A0 : 0x8005682e A1 : 0x3ffc87e0
A2 : 0x3ffbd8d0 A3 : 0x00000000 A4 : 0x00000000 A5 : 0x0000000a
A6 : 0x00000000 A7 : 0x00000008 A8 : 0x8000be99 A9 : 0x3ffc87d0
A10 : 0x3ffbd8d0 A11 : 0x00060123 A12 : 0x00060120 A13 : 0x0ccccccc
A14 : 0x00000000 A15 : 0x00000004 SAR : 0x00000018 EXCCAUSE: 0x0000001c
EXCVADDR: 0x00000000 LBEG : 0x400013f9 LEND : 0x4000140d LCOUNT : 0xfffffffb

Backtrace: 0x40056722:0x3ffc87e0 0x4005682b:0x3ffc8810 0x400566cd:0x3ffc8830 0x400d18b3:0x3ffc8850 0x400d1adf:0x3ffc8870 0x400d2bd9:0x3ffc8890 0x4008e0bd:0x3ffc88b0

PC: 0x40056722
EXCVADDR: 0x00000000

Decoding stack results
0x400d18b3: parseData() at C:\Users\chans\Documents\Arduino\Controller V2\Controller_V2/Controller_V2.ino line 130
0x400d1adf: loop() at C:\Users\chans\Documents\Arduino\Controller V2\Controller_V2/VPD_Controller_V2.ino line 76
0x400d2bd9: loopTask(void*) at C:\Users\chans\Documents\ArduinoData\packages\esp32\hardware\esp32\1.0.4\cores\esp32\main.cpp line 19
0x4008e0bd: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143

It seems strange and possibly usefully indicative (granted I'm not sure indicative of WHAT) that the program now crashes even if I try the solution which made it half-work in the past (removing the last two redefinitions).

New parseData() code with same old issue:

Yuck. I really had my hopes up :frowning:
Still, you fixed a major bug, and have a more consistent failure which is good.

A few posts ago I suggested going back to the code with serial input from the monitor as a way of sorting out the bluetooth hardware issues from more general code issues. Can you please try that now.

//Define Atmospheric Parameters
int Tdeadbar = 1; // Accepted fluctuation of temperature to prevent rapid switching of heating/cooling
int RHdeadbar = 2; // Accepted fluctuation of RH to prevent rapid switching of humidifying/dehumidfying
int Tedeadbar = 2; // Emergency temperature deadbar value (how high the temp can rise above Tday before being considered an emergency temp)

// --- Day
int Tday = 28; // Desired temperature during the day
int RHday = 79; // Desired RH during the day

// --- Night
int Tnight = 24; // 20.5 + 1.6 Desired temperature during the night
int RHnight = 74; // Desired RH during the night

//BLUETOOTH

//#include "BluetoothSerial.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;

//DATA RECEIVAL AND PARSING

const byte numChars = 32;
char receivedChars[numChars];
char tempChars[numChars];        // temporary array for use when parsing

boolean newData = false;

//char messageFromPC[numChars] = {0};

void setup() {
  delay(15);

  //DATA RECEIVAL AND PARSING

  Serial.begin(9600);
  //SerialBT.begin("ESP32test"); //Bluetooth device name
  //Serial.println("The device started, now you can pair it with bluetooth!");
  //Serial.println("This demo expects 3 pieces of data - text, an integer and a floating //point value");
  Serial.println("Enter 7 comma separated values with start/end markers <>  ");
  Serial.println();
}

void loop() {

  //DATA RECEIVAL AND PARSING
  {
      recvWithStartEndMarkers();
      if (newData == true) {
        strcpy(tempChars, receivedChars);
        // this temporary copy is necessary to protect the original data
        //   because strtok() used in parseData() replaces the commas with
        parseData();
        showParsedData();
        newData = false;
      }
    }
  }
//============

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();

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

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

    else if (rc == startMarker) {
      recvInProgress = true;
    }
  }
}

//============
void parseData() {      // split the data into its parts

  char * strtokIndx = strtok(tempChars, ",");
  Tday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHday = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHnight = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tdeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  Tedeadbar = atoi(strtokIndx);     // convert this part to an integer

  strtokIndx = strtok(NULL, ","); // this continues where the previous call left off
  RHdeadbar = atoi(strtokIndx);     // convert this part to an integer
}
//============
void showParsedData() {
  Serial.print("Day Temp ");
  Serial.println(Tday);
  Serial.print("Day Humidity ");
  Serial.println(RHday);
  Serial.print("Night Temp ");
  Serial.println(Tnight);
  Serial.print("Night Humidity ");
  Serial.println(RHnight);
  Serial.print("Temperature Deadbar ");
  Serial.println(Tdeadbar);
  Serial.print("Emergency Temperature Deadbar ");
  Serial.println(Tedeadbar);
  Serial.print("Humidity Deadbar ");
  Serial.println(RHdeadbar);
  Serial.println();
  delay(20);
}

That code appears to work perfectly with all 7 values. It shows all 7 properly in Serial Monitor after I input them.