How to Serial.parseInt();

Ive googled, Ive gone through the reference page but can find no tutorial dealing with Serial.parseInt();

I have a serial input giving 16 lines of data like so:

PID 0xA046
FW  116
SER#    HQ15242CRVD
V   13310
I   0
VPV 10
PPV 0
CS  0
ERR 0
H19 2662
H20 0
H21 0
H22 41
H23 559
HSDS    23
Checksum

I would like to store some of these numbers.

How is it done please?

Entries don't seem too long so read a full line into a char buffer (i.e. Read character by character until you hit the new line, don't use higher level functions which can time out). Ignore the \r character if you receive it and. Once you read the \n put a \0 instead at the current position of your char array so that you can use some char array manipulation functions such as strcmp, atoi, strtok,...

Once you have read a full line, you know you have a label, some spaces or tabs and a value.

Use the functions mentioned above to do the parsing.

Northland: Ive googled, Ive gone through the reference page but can find no tutorial dealing with Serial.parseInt(); How is it done please?

You better avoid all of the "Serial.parseBullshit" functions, including Serial.parseInt(); in your sketches! They'd lead to heavy delays in your code!

Reason: Those are "blocking" functions with a default timeout of one second. This means: If there is not data arriving the moment you are calling the funtion, that function has the same effect as "delay(1000) in your code.

If your data lines are ending with carriage return and linefeed control characters ("\r\n") it would be better to provide a task in your code which collects incoming characters to lines, and each time a line isreceived completely (after receiving line ending character '\n'); your code can do further line processing.

Serial input basics has examples of non-blocking serial receive and parsing code.

Yes I read example 5 but does it work without a start marker? If no, what is the start marker?

The first 3 lines contain letters and numbers, but these lines I dont need.

How do I modify this part

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
    integerFromPC = atoi(strtokIndx);     // convert this part to an integer

to assign the numbers to variables matching the input? eg var V = 13310

Well ignore the first 3 lines altogether - or compare the label you extract to see if it is one you want, in that case read it as above, if not just don't deal with that line and go read the next line

Northland: to assign the numbers to variables matching the input? eg var V = 13310

Can you provide an example of the data you want to parse and the names of the variables to which you want to store the parsed values?

...R

As per OP

PID 0xA046 FW 116 SER# HQ15242CRVD V 13310 I 0 VPV 10 PPV 0 CS 0 ERR 0 H19 2662 H20 0 H21 0 H22 41 H23 559 HSDS 23 Checksum

A little more explanation would be great - I can't read your mind.

Is each of those lines a single message or is the whole thing a single message?

Using the line "SER# HQ15242CRVD" as an example, do you want to store the characters "HQ15242CRVD" in a variable called "SER#"? If not, what do you want to do? (Is the # character valid in variable names?)

What does the data represent? What produces the data? Could the data be sent as a message like this 0xA046, 116, HQ15242CRVD, 13310, 0, 0, 10, 0, 0, 0, 2662, 0, 0, 41, 559, 23

...R

It's a single message. If it were separate messages it would be easy, I would just break down the strings. But it throws 16 lines once per second. It needs to be parsed so I can use the values.

I don't need the first 3 lines so the # question is redundant. I gave an example before: int V = 13310

The values I need are V, I, VPV, PPV, CE

It's output values from a solar controller.

There are 3 controllers to parse. I guess the easiest way is to use a mega, have 3 sets of loops, one on each serial port?

Well if IT is 16 LINES then you can Track the \n as discussed to build a line

16 lines per second is not a pb to parse arduino speed.

Just set the communication in baud to be fast. Don't use 9600 if you can decide the speed of the solar controller

Northland: It's a single message. If it were separate messages it would be easy, I would just break down the strings. But it throws 16 lines once per second. It needs to be parsed so I can use the values.

What separates each line - a linefeed character? What marks the end of the message?

This info is essential to being able to parse the data.

Am I correct to assume that each complete message can have different numbers of characters depending on the data it contains?

Have a good look at the 2nd example in Serial Input Basics. I suspect it is very close to what you need. You could count the lines as they are received and reset the counter when all 16 have arrived. You could also parse each after it arrives. If they are always in the same order you can just parse, for example, #5, #7, #8 etc

...R

I found some code, as it was it didnt work, just gave zeros. I have modified but it still doesnt work (works intermittently or gives zeros. First problem is there are 2 variables starting with V

char p_buffer[80];
#define P(str) (strcpy_P(p_buffer, PSTR(str)), p_buffer)
char c;
String V_buffer;  // Buffer to hold data from the Serial1 monitor
int Current;
int Voltage;
int PPV;
int VPV;
int CE;
void setup()
{
  Serial.begin(19200);
  Serial1.begin(19200);
}
void loop() {
  while (Serial1.available()) {
    c = Serial1.read();
    if (V_buffer.length() < 32) {
      V_buffer += c;
    }
    if (c == '\n') {  // New line.
      if (V_buffer.startsWith("V ")) {
        String temp_string = V_buffer.substring(V_buffer.indexOf("\t") + 1);
        int temp_int = temp_string.toInt();
        Voltage = (int) temp_int;
      }
      if (V_buffer.startsWith("I")) {
        String temp_string = V_buffer.substring(V_buffer.indexOf("\t") + 1);
        int temp_int = temp_string.toInt();
        Current = (int) temp_int;
      }
      if (V_buffer.startsWith("VPV")) {
        String temp_string = V_buffer.substring(V_buffer.indexOf("\t") + 1);
        int temp_int = temp_string.toInt();
        VPV = (int) temp_int;
      }
      if (V_buffer.startsWith("PPV")) {
        String temp_string = V_buffer.substring(V_buffer.indexOf("\t") + 1);
        int temp_int = temp_string.toInt();
        PPV = (int) temp_int;
      }
      if (V_buffer.startsWith("CE")) {
        String temp_string = V_buffer.substring(V_buffer.indexOf("\t") + 1);
        int temp_int = temp_string.toInt();
        CE = (int) temp_int;
      }
      V_buffer = "";
    }
  }
  Serial.print("V = ");
  Serial.print(Voltage);
  Serial.print("  I = ");
  Serial.print(Current);
  Serial.print("  VPV = ");
  Serial.print(VPV);
  Serial.print("  PPV = ");
  Serial.print(PPV);
  Serial.print("  CE = ");
  Serial.println(CE);
}

Don't use Strings - that will get you in trouble.

Why don't you want to just build a char array with the serial input until you get a new line and use functions as suggested in answer #1?

Northland: I found some code,

It would be much easier to help if you follow through with answers to questions rather than jumping on something new.

Solving problems with a computer program requires a careful methodical step-by-step approach.

If you want my involvement please respond to Reply #11.

...R

I'm "jumping on something new" because you continue to ask for information I've already provided. I provided not one, but two examples of variables and values. Then you quote the example, and ask me for an example? In your lingo, that's an infinite loop.

I used the "multiserialmega" example to find out what the solar controller is spitting out. I pasted this in the opening post, as it appeared in the serial window. There is no information being withheld. That's it. I fail to see how I as a novice have some insight an experienced person doesn't have, when we both have the same data.

"What separates each line - a linefeed character?"

The post after that contains code that shows \n new line, so it would appear this question has been answered. The code is for another product from the same manufacturer but a different model which has different variables, hence the need to modify the code.

"What marks the end of the message?"

Well as you can see, it ends with "Checksum" but is there some invisible character after that? How can I know this? Is there possible modifications to the multiserialmega example that can tell me?

"Am I correct to assume that each complete message can have different numbers of characters depending on the data it contains?"

The variables I suspect are fixed. The values would range between single digit 0 and 5 digits, so yes.

Robin2: Have a good look at the 2nd example in Serial Input Basics.

But you say just before example 4 that those are for text only. It's numbers I'm trying to store

Robin2:
Could the data be sent as a message like this
0xA046, 116, HQ15242CRVD, 13310, 0, 0, 10, 0, 0, 0, 2662, 0, 0, 41, 559, 23

…R

I didn’t ask about sending it, I asked about storing the values. But if I did, yes it could. If you mean from the solar controller, no it cannot be sent in a custom format.

Why don’t you want to just build a char array with the serial input until you get a new line and use functions as suggested in answer #1?

Is still my question? And post 3 links you to a great article taking you step by step to understand how to deal with Serial input.

Once you have acquired 1 line in a buffer, you parse it: extract the label, extract the value, check the label against those of interest and transform the value according to its format to suit your need.

There is zero rocket science there. Really give it a try…

Because I don't know how? Because https://www.arduino.cc/en/Reference/Char doesn't explain it. Because after reading https://www.arduino.cc/en/Reference/String I still don't quite understand. It might be simple to you. It is not simple to me.

And without a tutorial or example, I'm unlikely to ever understand.