Serial Parsing into 2 Arrays for Steppers

Howdy all. I have been scratching my head too much recently and need to get some advice on this issue in front of me. Let me preface by saying that this is an example that is built from various online example. I probably am confusing a bunch of things in here.

What I am trying to do is take incoming serial data (from Max/MSP) and parse the message into two separate number arrays which are sent to two individual stepper motors. The style of message I am trying to send to the Arduino is as follows (ex. 0, 23 or 132, 293). I guess what I am so confused about is how to fill an array properly that will hold each number set and pass them correctly to each stepper motor. How do I pass the correct integers from Serial.read()?
What am I doing wrong here?

Currently it will print out the string of numbers but only as ptr_stepperarray[0] without being able to break it apart into other arrays. I am confusing myself now but essentially its a Serial.read() message parsed into two separate arrays for 2 steppers.

const int NUMBER_OF_FIELDS_1 = 4; // how many comma separated fields we expect
int stepper1index = 0; // the current field being received
int values1[NUMBER_OF_FIELDS_1]; // array holding values for all the fields

const int NUMBER_OF_FIELDS_2 = 4; // how many comma separated fields we expect
int stepper2index = 0; // the current field being received
int values2[NUMBER_OF_FIELDS_2]; // array holding values for all the fields

void setup()
{
  Serial.begin(9600); // Initialize serial port to send and receive at 9600 baud
}

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      // yes, accumulate the value
      values1[stepper1index] = (values1[stepper1index] * 10) + (ch - '0'); 
      //Serial.println(values1[stepper1index]);
    }
    else if (ch == ', ')  // comma is our separator, so move on to the next field
    {
      if(stepper1index < NUMBER_OF_FIELDS_1-1)
        stepper1index++;   // increment field index
      //  Serial.println(stepper1index++);
    }
    else
    {
      // any character not a digit or comma ends the acquisition of fields
      // in this example it's the newline character sent by the Serial Monitor
    
    //  Serial.print(stepper1index+1);
     // Serial.println(" fields1 received:");
      
      for(int i=0; i <= stepper1index; i++)
      {

       // Serial.println(values1[i]); 
     //  Serial.println(values1[0]);
      //Serial.println(values1[1]);  
       
       int a = values1[i];
       int stepperarray[] = {a};
       
        int *ptr_stepperarray;
       ptr_stepperarray = stepperarray;
       
       Serial.print("Number - > ");
       Serial.println(ptr_stepperarray[0]);
      // Serial.print("Number#2 - > ");       
       //Serial.println(ptr_stepperarray[1]);
        
   
       values1[i] = 0; // set the values to zero, ready for the next message
      
    }
      stepper1index = 0;  // ready to start over
    }
  }
}

(ex. 0, 23 or 132, 293)

whats the data format? is every other one going to list 2? or is it a chunk of 4 into list 1 then the next 4 into list two?

personally I would keep it all in a single array and stride the values

for(int i = 0, i < 5, i += 2)

would give you 0,2,4, and

for(int i = 1, i < 5, i+= 2)

would give you 1, 3

Will your input string 132, 293 contain spaces as well (after the comma?). You probably need to think of the number as the pattern .

Also, think of using a small structure that contains the numbers so that the array index remains the same

struct values
{
  int value1;
  int value2;
}

values v[NUMBER_OF_FIELDS];

you then access the individual elements as

v[i].value1 = x
v[i].value2 = y

Fewer indices to keep track of and a more logical grouping of values.

Edit - realised that array subscript caused italics :frowning:

Osgeld:

(ex. 0, 23 or 132, 293)

whats the data format? is every other one going to list 2? or is it a chunk of 4 into list 1 then the next 4 into list two?

personally I would keep it all in a single array and stride the values

for(int i = 0, i < 5, i += 2)

would give you 0,2,4, and

for(int i = 1, i < 5, i+= 2)

would give you 1, 3

It would be so that in Max/MSP when I type in 0, 30 it will take the number before the comma and insert it into a list and the second number at the the comma do the same. I really don’t want it to be like that but with Max/Arduino communication this is the easiest format, I could use a period too. But in general, 2 lists.

marco_c:
Will your input string 132, 293 contain spaces as well (after the comma?). You probably need to think of the number as the pattern .

Also, think of using a small structure that contains the numbers so that the array index remains the same

struct values

{
  int value1;
  int value2;
}

values v[NUMBER_OF_FIELDS];



you then access the individual elements as v_.value1 and v*.value2.*_
_*Fewer indices to kepe track of and a more logical grouping of values.*_
_*[/quote]*_
_*The string would be "0, 12" so 0, comma, space, 12. But now after reading the other reply I may just use a period. Thanks for the advice about the structs! I am fairly weak at working with structs, is it possible you could help me out or inform me with another example? This has been an experiment in how do I know and it seems that it may be very little :~*_

Forgot to mention that as you maybe saw in the code I need to convert ASCII to integers so it will interact with the steppers correctly. It was probably apparent but mainly mentioning since it is vital to track the stepper movements within Max.

I figured out how to get the two needed integers to print within Max but I am still confused. ptr_stepperarray[0] seems like it is the holder of both incoming integers from the Serial Monitor but how can break it apart? If I were to run this code within MaxMSP or through the Arduino serial monitor and type two random integers (lets say 4, 123), I will get this

Number#1 → 4
Number#1 → 123

So by deduction it seems like the ptr_stepperarray[0] contains these two numbers but how can I parse it out so they are two separate int’s? I just want each number, in this case 4 and 123, to be route individually if that is at all possible.

please need help! =(

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      // yes, accumulate the value
      values1[stepper1index] = (values1[stepper1index] * 10) + (ch - '0'); 
      
    }
    else if (ch == '.')  // comma is our separator, so move on to the next field
    {
      if(stepper1index < NUMBER_OF_FIELDS_1-1)
      {
        stepper1index++;   // increment field index
        //Serial.println(stepper1index++);
      }
    }
    else
    {
      // any character not a digit or comma ends the acquisition of fields
      // in this example it's the newline character sent by the Serial Monitor
        
        
        
        int i;
      for(int i=0; i < 1; i++)
      {
          int a = values1[stepper1index]; 
          int b = values1[stepper1index++];    
          int stepperarray[] = {a, b};
          int *ptr_stepperarray = stepperarray;
          
          ptr_stepperarray[0] = ch;

          Serial.print("Number#1 - > ");
          Serial.println(ptr_stepperarray[0]);   
      
        }
               values1[i] = 0; // set the values to zero, ready for the next message    
stepper1index = 0;  // ready to start over
      }
    }
    }

I'd suggest that you learn to do a couple of things. First, learn to post code correctly. Use the # icon when posting code. That way, the code we see looks like the code you see. You can't say that about the mess you posted.

If that code looks like what you see, that would explain your problem, so I'll assume that it was mangled due to not be posted properly.

Second, read the reference documentation, and use functions correctly. The Serial.available() method returns the number of characters in the buffer. It does not return true/false to indicate whether or not there is data to read. Don't use the function as though it did. Make it clear that you know what it returns.

    else if (ch == '.')  // comma is our separator, so move on to the next field

When the code and the comments don't match, guess which one the compiler pays attention to.

First off, bare with me please, i’m new to posting and in general I know its mashed together as it was specified above. What is more important is how to resolve the problem, it is now posted properly.

]:smiley:

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      // yes, accumulate the value
      values1[stepper1index] = (values1[stepper1index] * 10) + (ch - '0'); 
      
    }
    else if (ch == '.')  
    {
      if(stepper1index < NUMBER_OF_FIELDS_1-1)
      {
        stepper1index++;   // increment field index
  
      }
    }
    else
    {
     
   // any character not a digit or PERIOD ends the acquisition of fields
      // in this example it's the newline character sent by the Serial Monitor   
        
        int i;
      for(int i=0; i < 1; i++)
      {
          int a = values1[stepper1index]; 
          int b = values1[stepper1index++];    
          int stepperarray[] = {a, b};
          int *ptr_stepperarray = stepperarray;
          
          ptr_stepperarray[0] = ch;

          Serial.print("Number#1 - > ");
          Serial.println(ptr_stepperarray[0]);   
      
        }
               values1 = 0; // set the values to zero, ready for the next message    
               stepper1index = 0;  // ready to start over
      }
    }
    }

What is more important is how to resolve the problem

Are the values in the string separated by commas, as you said, or by periods as you coded?

PaulS:

What is more important is how to resolve the problem

Are the values in the string separated by commas, as you said, or by periods as you coded?

It is coded as '.' within the Arduino code. But what is odd, when I type it into the Serial monitor with a period (ex. 32.12) it does not work but with a comma instead it works (ex 54, 32).

I've narrowed it down to this piece of code i've figured out to be the one that seems to be creating this issue and there are a few examples below of various results

     //    ptr_stepperarray[0] = ch;

[u]When this piece of code is eliminated[/u]

[u]Example A1 -- ex. 32.12[/u]

prints as follows inside Arduino Serial Monitor = Number#1 - > 12 (second integer is lost) prints as follows inside MaxMSP from the Serial Monitor = Number#1 -> 0 (second integer is lost)

[u]Example A2 -- 32,12[/u]

prints as follows inside Arduino Serial Monitor Number#1 - > 32 Number#1 - > 12

b]prints as follows inside MaxMSP from the Serial Monitor[/b] = Number#1 - > 0 Number#1 - > 0


[u]When this piece of code is uploaded[/u]

[u]Example B1 -- ex. 32.12[/u]

prints as follows inside Arduino Serial Monitor = Number#1 - > 10 (second integer is lost) prints as follows inside MaxMSP from the Serial Monitor = Number#1 -> 32 (second integer is lost)

[u]Example B2 -- 32,12[/u]

prints as follows inside Arduino Serial Monitor Number#1 - > 44 Number#1 - > 10

b]prints as follows inside MaxMSP from the Serial Monitor[/b] = Number#1 - > 32 Number#1 - > 12

So pretty much it seems that when this piece of code is uploaded, the one specified above, I can acquire the correct data. Still, I am trying to separate these two number fields from "ptr_stepperarray[0] = ch" so I can send these two individual integers to 2 different stepper motors.

          int a = values1[stepper1index]; 
          int b = values1[stepper1index++];

There are postfix operators and prefix operators. They do different things. The prefix version increments (in the case of ++) and then the value is used. The postfix version uses the value, then increments it.

So, in this code, the same value is being stored in a and b. And, it is likely to be the wrong value, as it is the index to the last value stored in the array. I suspect that what you want here are 0 and 1, not stepper1index and stepper1index that is then incremented.

PaulS:           int a = values1[stepper1index];           int b = values1[stepper1index++];

There are postfix operators and prefix operators. They do different things. The prefix version increments (in the case of ++) and then the value is used. The postfix version uses the value, then increments it.

So, in this code, the same value is being stored in a and b. And, it is likely to be the wrong value, as it is the index to the last value stored in the array. I suspect that what you want here are 0 and 1, not stepper1index and stepper1index that is then incremented.

When I make the change below, nothing is printed within values1[1]. Everything seems to be stuck in value within the values[0] part of the array. ptr_stepperarray[0] will always yield both integers that are typed in. Totally bewildered and pondering how to split up the array, maybe make it a pointer to do that?

          int a = values1[0]; 
          int b = values1[1];    
          int stepperarray[] = {a, b};
          int *ptr_stepperarray = stepperarray;
          
        ptr_stepperarray[0] = ch;

// *ptr_stepperarray = ch; This was another piece I just figured out so that this pointer now holds the input, how to 
// split it?

          Serial.print("Number#1 - > ");
          Serial.println(ptr_stepperarray[0]);
            Serial.print("Number#2 - > ");
          Serial.println(ptr_stepperarray[1]);

Totally bewildered and pondering how to split up the array, maybe make it a pointer to do that?

I don’t think a pointer is the solution. More Serial.print()s to see what you are really receiving would be good. Knowing when you increment stepper1index would be good, too.

        ptr_stepperarray[0] = ch;

I don’t understand why you have this here (or anywhere, for that matter). You are stepping on the value in stepperarray[0] when you do this. Why?

      for(int i=0; i < 1; i++)
      {

How may times is this loop going to iterate?

PaulS:

        ptr_stepperarray[0] = ch;

I don’t understand why you have this here (or anywhere, for that matter). You are stepping on the value in stepperarray[0] when you do this. Why?

Thanks for you patience with this problem, you have no idea how much walking through this helps. I do not know why I was doing that, I don’t have a lot of experience so many of the things I have used are random examples. Pointers and multiple arrays are still fairly new to me.

      for(int i=0; i < 1; i++)

{




How may times is this loop going to iterate?

As of the moment, the code loops every time I input a set of integers. As of the moment it seems like it is working as I want it.

Totally bewildered and pondering how to split up the array, maybe make it a pointer to do that?

I don’t think a pointer is the solution. More Serial.print()s to see what you are really receiving would be good. Knowing when you increment stepper1index would be good, too.

Below is the code with more print statements and I also supplied an example print so you don’t have to run it. The example number input I used was “47, 13”.

void loop()
{
  if( Serial.available())
  {
    char ch = Serial.read();
    
    Serial.print("ch (Serial.read) -> ");
    Serial.print(ch); 
    Serial.println(" ");  

    if(ch >= '0' && ch <= '9') // is this an ascii digit between 0 and 9?
    {
      values1[stepper1index] = (values1[stepper1index] * 10) + (ch - '0'); 
      
      Serial.print("values1[stepper1index] -> ");
      Serial.print(values1[stepper1index]);
      Serial.println(" ");   
    }
    else if (ch == '.')  // comma is our separator, so move on to the next field
    {
      if(stepper1index < NUMBER_OF_FIELDS_1-1)
      {
        stepper1index++;   // increment field index
              
        Serial.print("stepper1index++ -> ");
        Serial.print(stepper1index++);
        Serial.println(" ");
      }
    }
    else
    {
        
      int i;
      
      for(int i=0; i < 1; i++)
      {
          int a = values1[0]; 
                        
          Serial.print("a or values1[0] -> ");
          Serial.print(a);
          Serial.println(" ");
          
          int stepperarray[] = {a};
                        
          int *ptr_stepperarray = stepperarray;

          Serial.print("Number#1 -> ");
          Serial.println(*ptr_stepperarray);
          Serial.println(" ");
      }
        
         values1[i] = 0; // set the values to zero, ready for the next message    
        stepper1index = 0;  // ready to start over
    } 
  }
}

ch (Serial.read) → 4
values1[stepper1index] → 4
ch (Serial.read) → 7
values1[stepper1index] → 47
ch (Serial.read) → ,
a or values1[0] → 47
Number#1 → 47

ch (Serial.read) →
a or values1[0] → 0
Number#1 → 0

ch (Serial.read) → 1
values1[stepper1index] → 1
ch (Serial.read) → 3
values1[stepper1index] → 13
ch (Serial.read) →

a or values1[0] → 13
Number#1 → 13

This:

The example number input I used was “47, 13”.

and this:

    else if (ch == '.')  // comma is our separator, so move on to the next field

still do not go together.

You probably also need to deal with space as a special character, too. Otherwise the space will cause the same problem the comma is now causing.

PaulS: This:

The example number input I used was "47, 13".

and this:

    else if (ch == '.')  // comma is our separator, so move on to the next field

still do not go together.

You probably also need to deal with space as a special character, too. Otherwise the space will cause the same problem the comma is now causing.

I understand they are not the same but for some reason when I upload my code and type in integer sets within MaxMSP, anything with a period does not work. That is what was mentioned in the examples a few posts back. Even if I code it with a '.' and no space, it takes a comma and a space for max to properly translate it to MaxMSP.

Even if I code it with a '.' and no space, it takes a comma and a space for max to properly translate it to MaxMSP.

So why the blankitty-blank-blank don't you make the code expect what you are getting?

This is getting nowhere when you keep trying to modify the Arduino code in ways that do not match what you are ACTUALLY getting as input.

Especially, when you keep insisting that somehow the Arduino is then at fault.

PaulS:

Even if I code it with a ‘.’ and no space, it takes a comma and a space for max to properly translate it to MaxMSP.

So why the blankitty-blank-blank don’t you make the code expect what you are getting?

This is getting nowhere when you keep trying to modify the Arduino code in ways that do not match what you are ACTUALLY getting as input.

Especially, when you keep insisting that somehow the Arduino is then at fault.

Its been resolved and it was easy. If we didn’t focus so much on the concept of a period and a comma, and realized it was routed through MaxMSP, then we may have resolved it.

… I’ve mentioned it before. For some reason, when the data is routed THROUGH MaxMSP, it is interpreted differently than how it would respond in the Arduino Serial Monitor. I am trying to get it to communicate correctly, and now it does. I apologize if I annoyed you but I do not think you were getting my idea from the beginning. Even know I type in “.”, when I go and type a number set in MaxMSP with the period, it doesn’t respond correctly. For some reason, when I type a set with a comma, it works, even though it is coded within the Arduino as a period.

Its a communication relay issue between the both of them. I don’t know if you have used MaxMSP but sometimes they communicate and then sometimes they communicate and they unrelate.

Thank you for taking the time out to help me though, I apologize for confusion. I am going to make a video so you can see what I am talking about.

PaulS:

Even if I code it with a '.' and no space, it takes a comma and a space for max to properly translate it to MaxMSP.

So why the blankitty-blank-blank don't you make the code expect what you are getting?

This is getting nowhere when you keep trying to modify the Arduino code in ways that do not match what you are ACTUALLY getting as input.

Especially, when you keep insisting that somehow the Arduino is then at fault.

Video of uploading the code with the period and how MaxMSP does not understand how to react. Yet when I used a comma, it prints it properly.

https://www.dropbox.com/s/9zh3yojgp3znch3/Screen%20Capture%20Tool_2012-10-17%2015.44.03.mov