Breaking up CSVs

Le Sun 27 October 2013

The following two sketches demonstrate breaking a CSV stream from the Serial Monitor into a series of numbers in an array. This process is an essential element in the HWC timer project. In their original form both of these examples suffer from a limitation of ONLY 15bits of numerical data because of the use of INT for the value array. The largest number that int variables can handle is 32767. This would have been a problem for the large numbers used in the dates that we want to read off the SD Card. This limitation was overcome by defining the value array as unsigned long. This increases the maximum to a 2 x 32bit limit because we steal the bit that would otherwise be used for indicating the sign.

Method One

The method shown below is able to be used in older Aduino IDEs and is relatively understandable as it does not use too many high level commands. For this one turn on the Send Newline in the Serial Monitor. It is known that ''strings'' are glitchy in Arduinos and this can lead to weird problems. The second method described below is more memory efficient and because it avoids the use of ''strings'' it is more robust. You can download this sketch from here: CSVBreaker01.ino

/*
* Method one of breaking out a CSV text stream into an array of numbers
* The method here is designed for older Arduino IDEs, and is a bit more
* understandable.
* SerialReceiveMultipleFieldssketch.
* This code expects a message in the form: 12,345,241
* A new line character is required to indicate the end of the data.
* Set the serial monitor to send new line characters.
* The sketch has been modified from the original by using an unsigned long
* for the array. This allows us to successfully handle the very large
* numbers that will be required for the dates and times.
*/

const int NUMBER_OF_FIELDS = 3;  //How many comma separated fields are expected.
int fieldIndex = 0;  //The current field being received
unsigned long values[NUMBER_OF_FIELDS];  //This is the array to hold the values.

void setup()
{
  Serial.begin(9600);  // Initialise the serial port to send and receive
}

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 if the fieldIndex is within range
      //additional fields are not stored.
      if(fieldIndex<NUMBER_OF_FIELDS)
      {
         values[fieldIndex]=(values[fieldIndex]*10)+(ch-'0');  //
      }
    }
    else if(ch==',')
    {  //If the character is a comma continue to the next field
      fieldIndex++;  //increment the fieldIndex
    }
    else {
       //any character other than a digit or a comma end the capture of fields
       //in this example new line character sent by the Serial Monitor
       //will stop the capture process.
       //Print each of the stored numbers from the array
      for(int i=0;i<min(NUMBER_OF_FIELDS,fieldIndex+1);i++)
      {
        Serial.println(values[i]);
        values[i]=0; //Set the values to zero, ready for the next message
      }
      fieldIndex=0;  //ready to start over.
    }
  }
}

Another method

This method is for Arduino 1.0 IDEs and uses some higher level processes. For this one turn off the Send Newline in the Serial Monitor.
See CSV Array Loader for this in use. This method is more memory conservative and also less prone to weirdness that the string based previous method is. You can download this sketch from here: CSVBreaker02.ino

/*
* Method two of breaking out a CSV text stream into an array of numbers
* The method here is designed for Arduino 1.0 IDEs, and is a bit more
* sophisticated with higher level commands.
* SerialReceiveMultipleFieldssketch using Arduino 1.0 Stream Parsing.
* This code expects a message in the form: 12,345,241
* A new line character is required to indicate the end of the data.
* Set the serial monitor to send new line characters.
* The sketch has been modified from the original by using an unsigned long
* for the array. This allows us to successfully handle the very large
* numbers that will be required for the dates and times.
*/

const int NUMBER_OF_FIELDS = 3;  //How many comma separated fields are expected.
int fieldIndex = 0;  //The current field being received
unsigned long values[NUMBER_OF_FIELDS];  //This is the array to hold the values.

void setup()
{
  Serial.begin(9600);  // Initialise the serial port to send and receive
}

void loop()
{
  if(Serial.available())
  {
    for(fieldIndex=0;fieldIndex<3;fieldIndex++)
    {
      values[fieldIndex]=Serial.parseInt();  //get a numercial value
    }
    Serial.print(fieldIndex);
    Serial.println(" fields received:");
    for(int i=0;i<fieldIndex;i++)
    {
      Serial.println(values[i]);
    }
    fieldIndex = 0;  //ready to start over

  }
}

Par Hamish Trolove, Cat├ęgorie : Tech Projects

Tags : Arduino / Communication / CSV /