[SOLVED]Strtok not producing output

Hi,
I am trying to make a terminal-monitor.
Its receiving this data format (123.45,678.90)
This is the code:

// (c) Harry H.Arends
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
char inData[15];  // Allocate some space for the string
char inChar;      // Where to store the character read
byte index = 0;   // Index into array; where to store the character
char *AXpos;
char *EYpos;
const char *delimiter = ",";
char *posX;
char *posY;
String serialResponse = "";

LiquidCrystal_I2C lcd(0x27, 20, 4);  // set the LCD address to 0x27 for a 16 chars and 2 line display

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

}

void loop() {
  while (Serial.available() > 0) {
    if (index < 14)  // One less than the size of the array
    {

      inData[index] = Serial.read();  // Store it
                                      //       Serial.println(inChar);
      index++;                        // Increment where to write next
      inData[index] = '\0';           // Null terminate the string
                                      //    Serial.print(index);
                                      //    Serial.print("=");
                                      //    Serial.println(inData);
    }
    AXpos = strtok(inData, delimiter);
    EYpos = strtok(NULL, delimiter);
    Serial.print("AX=");
    Serial.println(AXpos);
    Serial.print("EY=");
    Serial.println(EYpos);
  }
}

The program produces AXpo but NOT EYpos.
What could be wrong??

What does the program print out, for both?

You might try this example, which should help you guess what went wrong:

// parse a C-string

char array[] = "(123.45,678.90)";
char *ptr = NULL;

void setup()
{
    Serial.begin(115200);
    Serial.println();
    Serial.println("strtok example");
    ptr = strtok(array, ",");  // delimiter = comma
    while(ptr != NULL)
    {
        Serial.println(ptr);
        ptr = strtok(NULL, ",");  // delimiter = comma
    }
}

void loop()
{
}

Hint: try something like this for the delimiters:

    ptr = strtok(array, ",()");

Topic moved !! Please do not post in "Uncategorized"; see the sticky topics in Uncategorized - Arduino Forum.

Print inData before these lines to see what you are feeding.

    AXpos = strtok(inData, delimiter);
    EYpos = strtok(NULL, delimiter);

Also, are parentheses part of the format? I guessed not as you don't take in enough characters, maybe you were using them like we would normally use quotes as @jremington has

char array[] = "(123.45,678.90)";

temporarily skip the reading of input and just make inData be some plausible known correct input in the same manner.

a7

char inData[] = "54.321,109.876";
const char *delimiter = ",";

char *AXpos;
char *EYpos;

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

  AXpos = strtok(inData, delimiter);
  EYpos = strtok(NULL, delimiter);

  Serial.print("AX=\"");
  Serial.print(AXpos);
  Serial.println("\"  ");
  Serial.print("EY=\"");
  Serial.print(EYpos);
  Serial.println("\"  ");
}

void loop() {}

output

AX="54.321"  
EY="109.876" 

Nothing to do with *strtok*()

a7

Moved to??

The program produces using serialmonutor,
input=123.45,678.90
output:
06:53:57.872 -> EY=
06:53:57.872 -> AX=123.45
06:53:57.872 -> EY=
06:53:57.906 -> AX=123.45
06:53:57.906 -> EY=
06:53:57.906 -> AX=123.45
06:53:57.906 -> EY=
06:53:57.937 -> AX=123.45
06:53:57.937 -> EY=
06:53:57.937 -> AX=123.45
06:53:57.937 -> EY=
as you see EY stays empty

You try to parse the string every time you get a new character. Shouldn't you wait until you've received the full payload before doing so ?

I would suggest to study Serial Input Basics to handle the data input.

So I studyed the input-basics and used a example and addapted to my needs:

// (c) Harry H.Arends
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

char inChar;     // Where to store the character read
byte index = 0;  // Index into array; where to store the character
char *AXpos;
char *EYpos;
const char *delimiter = ",";
const byte numChars = 15;
char inData[numChars];  // an array to store the received data

boolean newData = false;

void setup() {
  LiquidCrystal_I2C lcd(0x27, 20, 4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
  Serial.begin(9600);
}

void loop() {
  recvWithEndMarker();
  processNewData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

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

    if (rc != endMarker) {
      inData[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
      Serial.print("Received= ");
      Serial.println(inData);
    } else {
      Serial.println("Done");
      inData[ndx] = '\0';  // terminate the string
      ndx = 0;
      newData = true;
    }
    //Serial.println(ndx);
  }
}

void processNewData() {
  if (newData == true) {
    //Serial.println();//terminate starsline
    Serial.print("This just in ... ");
    Serial.println(inData);
    newData = false;
  } else {
    //Serial.print("*");//max.14 stars
  }
}

But newData never gets true, why??

Maybe you do not send a '\n'? There are settings in the Serial Monitor that define the line ending. For the code you provided it should be set to LF (Line Feed).

So I added this:

      Serial.print(ndx);
       Serial.print("-");
      Serial.print("Received= ");
      Serial.println(inData);

and the output is as follows:

09:50:09.857 -> 4-Received= 123.
09:50:09.857 -> 5-Received= 123.4
09:50:09.891 -> 6-Received= 123.45
09:50:09.925 -> 7-Received= 123.45,
09:50:09.925 -> 8-Received= 123.45,6
09:50:09.957 -> 9-Received= 123.45,67
09:50:09.989 -> 10-Received= 123.45,678
09:50:09.989 -> 11-Received= 123.45,678.
09:50:10.022 -> 12-Received= 123.45,678.9
09:50:10.056 -> 13-Received= 123.45,678.90
09:50:10.088 -> 14-Received= 123.45,678.90
It does receive a CR

What program? Please state the post # where it is hiding from me.

I see no code that actually prints the string that you are feeding to strtok.

a7

maybe you need a '\r' carriage return instead of '\n' newline??

good luck.. ~q

How is your serial monitor set?

Thnx for all the advice so I have rewritten the code:

// (c) Harry H.Arends
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

char inChar;     // Where to store the character read
byte index = 0;  // Index into array; where to store the character
char *AXpos;
char *EYpos;
const char *delimiter = ",";
const byte numChars = 15;
char inData[numChars];  // an array to store the received data

boolean newData = false;

void setup() {
  LiquidCrystal_I2C lcd(0x27, 20, 4);  // set the LCD address to 0x27 for a 16 chars and 2 line display
  Serial.begin(9600);
}

void loop() {
  recvWithEndMarker();
  processNewData();
  extractData();
}

void recvWithEndMarker() {
  static byte ndx = 0;
  char endMarker = '\n';
  char rc;

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

    if (rc != endMarker) {
      inData[ndx] = rc;
      ndx++;
      if (ndx >= numChars) {
        ndx = numChars - 1;
      }
      Serial.print(ndx);
      Serial.print("-");
      Serial.print("Received= ");
      Serial.println(inData);
    } else {
      Serial.println("Done");
      inData[ndx] = '\0';  // terminate the string
      ndx = 0;
      newData = true;
    }
    //Serial.println(ndx);
  }
}

void processNewData() {
  if (newData == true) {
    //Serial.println();//terminate starsline
    Serial.print("This just in ... ");
    Serial.println(inData);
    //    newData = false;
  } else {
    //Serial.print("*");//max.14 stars
  }
}

void extractData() {
  //Extract two numbers from received data
  if (newData == true) {
    AXpos = strtok(inData, delimiter);
    EYpos = strtok(NULL, delimiter);
    Serial.print("AX= ");
    Serial.println(AXpos);
    Serial.print("EY= ");
    Serial.println(EYpos);
    newData = false;
  }
}

And it produces the correct output/result:

22:20:40.418 -> 1-Received= 1
22:20:40.418 -> 2-Received= 12
22:20:40.452 -> 3-Received= 123
22:20:40.452 -> 4-Received= 123.
22:20:40.487 -> 5-Received= 123.4
22:20:40.487 -> 6-Received= 123.45
22:20:40.521 -> 7-Received= 123.45,
22:20:40.521 -> 8-Received= 123.45,6
22:20:40.556 -> 9-Received= 123.45,67
22:20:40.589 -> 10-Received= 123.45,678
22:20:40.621 -> 11-Received= 123.45,678.
22:20:40.621 -> 12-Received= 123.45,678.9
22:20:40.656 -> 13-Received= 123.45,678.90
22:20:40.690 -> Done
22:20:40.690 -> This just in ... 123.45,678.90
22:20:40.724 -> AX= 123.45
22:20:40.762 -> EY= 678.90

So again thanks for all the input and till next time

Well done !

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