michalmonday / CSV-Parser-for-Arduino

It turns CSV string into an associative array (like dict in python)
MIT License
58 stars 12 forks source link

How to access parsed CSV values outside of setup() ? #15

Closed ERUllmanV closed 2 years ago

ERUllmanV commented 2 years ago

Hi,

I am having trouble accessing the values which I have parsed from a CSV file outside of setup(). I am unsure how I can access these parsed values within in the loop() of the program or within any other program function. It is my understanding that the values parsed from the CSV files are stored in an array which represents each column. As such, I attempted to access the values stored in a specific row by referencing the identifier of the column as an array with a pointer which indicates which row to access the value from (ex: Serial.print(strings[1]); This however was unsuccessful.

Thank you in advance for any help or advice on how to go about accessing the values obtained from the CSV parser.

michalmonday commented 2 years ago

Hello, you could create the CSV_Parser object as a global variable. Example below shows how it can be done. After using cp << csv_str and cp.parseLeftover(), all parsed values can be retrieved anywhere, in setup and in loop functions (or any other functions called afterwards).

#include <CSV_Parser.h>

CSV_Parser cp(/*format*/ "sL");

void setup() {
  char * csv_str = "my_strings,my_numbers\n"
                   "hello,5\n"
                   "world,10\n";
  cp << csv_str;
  cp.parseLeftover(); // just in case if the csv_str didn't end with "\n"
}

void loop() {

}
ERUllmanV commented 2 years ago

Thank you for the expedient response,

Your solution seems to work great! I did end up tweaking where some of the components of the program were located. I eliminated the need for the bitwise shift and cp.parseLeftover() by putting the .csv file in the beginning of the program. I also made the column array assignments global variables so I could retrieve the column and row outside of setup().

char * csv_str ="my_strings,my_numbers\n"
                   "hello,5\n"
                   "world,10\n";

   CSV_Parser cp(csv_str, /*format*/ "sL");

   char **strings = (char**)cp["my_strings"];
  int32_t *numbers = (int32_t*)cp["my_numbers"];

void setup() {
  Serial.begin(115200);
  delay(2000);

  //cp.print();

}

void loop() {
Serial.println(strings[1]);
delay(500);
}

Program Output: world world world

ERUllmanV commented 2 years ago

I was also curious if parsed values could be retrieved based on the value stored within a specific row and column. In my case, I am trying to compare my current GPS Coordinates to a database of GPS waypoints, so it would be convenient to retrieve a GPS waypoint based on its latitude/longitude and compare it to my current GPS latitude/longitude. For example, if my current GPS coordinate is (43.0,-90.0) I would like to search for the GPS waypoint that is nearest to that latitude and longitude value say (42.5,-89.7) and retrieve the row for the GPS waypoint which contains those coordinates.

Thank you in advance for your help!

michalmonday commented 2 years ago

It is very specific task so the library itself doesn't have any built-in functions for it. But here's what you could have:

#include <CSV_Parser.h>

int closest_row(float x, float y, float *x_array, float *y_array, int rows_count) {
    float min_dist = 3.4028235E+38; // initialized to maximum possible float value
    int min_row = 0;
    for (int i = 0; i < rows_count; i++) {
        float dist = sqrt(pow(x_array[i] - x,2.0) + pow(y_array[i] - y,2.0));
        if (dist < min_dist) {
            min_dist = dist;
            min_row = i;
        }
    }
    return min_row;
}

void setup() {
  Serial.begin(115200);
  delay(5000);

  char * csv_str = "x,y\n"
                   "100,100\n"
                   "200,200\n"
                   "300,300\n";

  CSV_Parser cp(csv_str, /*format*/ "ff");

  float *x_array = (float*)cp["x"];
  float *y_array = (float*)cp["y"];

  int i = closest_row(149.99999, 150, x_array, y_array, cp.getRowsCount());
  int j = closest_row(150.00001, 150, x_array, y_array, cp.getRowsCount());
  int k = closest_row(310.0, 310.0, x_array, y_array, cp.getRowsCount());

  Serial.println(i, DEC);
  Serial.println(j, DEC);
  Serial.println(k, DEC);
}

void loop() {

}

It outputs the following:

0
1
2

The closest_row function returns row index. It compares euclidean distance.

ERUllmanV commented 2 years ago

That solution works perfectly! Thank you again for all your help and for developing such a useful and intuitive library for CSV Parsing.