Saturday, October 20, 2012

Reading the Fake Sensor Data

Now that we have created the fake sensor data and put it into a CSV file, we can now re-use the sensor data to help troubleshoot and debug the rest of your system. The first step is to download Processing (if using a Windows system, get the 32 bit version or you won't be able to use its Serial features).

The Processing environment is almost the same as that for the Arduino. Processing will be responsible for reading the CSV file and sending it over the serial connection to the Arduino.

While running the Processing Serial connection, you WILL NOT be able to use the Serial Monitor on the Arduino or upload updated sketches to the micro controller.

However, you can have Processing display any Serial.print() output from the Arduino.

When you need to upload a sketch to the Arduino, just make sure you press the STOP button on the Processing IDE prior to uploading.

The biggest advantage with this is that you can test your much cooler code quickly and easily with a predicable test environment. When you are ready to move to testing with real sensors (which will have to be done anyway later on) it will be trivial to get the input from the sensors themselves rather than from the serial connection.

Enjoy!

Processing Sketch

import processing.serial.*;
String myFile = "c:/mydata.csv";   //note the direction of the slash
String arduinoResponse;            //for displaying Arduino Serial.print() data
Serial myPort;
int delayTime = 25;    
//How long between each byte being transferred. If there isn't enough of a pause
//you could have some unpredictable results.
void setup() {
  //Replace COM3 with your actual serial port
  myPort = new Serial(this, "COM3", 9600);
  
  //The entire csv file will be stored in a string array.
  //One line of the csv per array element
  String lines[] = loadStrings(myFile);

  //Write each line to the serial port, one character at a time
  for (int i =0; i < lines.length; i++) {

    for (int j = 0; j < lines[i].length(); j++) {
      //print (lines[i].charAt(j));
      myPort.write (lines[i].charAt(j));
      delay(delayTime);
    }

    delay(delayTime); 

    //Read any output the Arduino sends over Serial. Great for debugging.
    arduinoResponse = myPort.readString();
    println (arduinoResponse);
  }
}

Arduino Sketch
//Global Variables and Constants

int NUMCOL = 5;    //Number of columns in the sensor data

//Input pins
const int TS = 0;       //time stamp, not really a pin, but...
const int brake = A1;   //Arduino Analog Pin 1
const int BRAKE = 1;    //Column 1 in the array
const int reverse = A2;
const int REVERSE = 2;
const int left = A3;
const int LEFT = 3;
const int right = A4;
const int RIGHT = 4;

//Array that holds sensor readings
const int HISTORY = 100;
//Length of the reading history (set to 1 if only only need the current dataset)
const int CURR = 0;      //0th row is the current reading
long int sensorReading[HISTORY][NUMCOL];    //Sensor readings stored here.

void setup() {
  //Initialize historical arrays to -1 (a reading that is always invalid)

  for (int i = 0; i < HISTORY; i++) { 
    for (int j = 0; j < NUMCOL; j++) {
      wheelSensor[i][j] = -1;
    }
  }

  //Open serial connection to Processing sketch
  Serial.begin(9600); //Make sure Processing and Arduino agree on this number
}


void loop () { 
  readSensor();
  //DoCoolStuffWithSensorReadings(). Your other code goes here.
}



void readSensor () {

  //Get the current reading from the wheel sensors, place them in
  //the current line.

  char currByte;      //Current incoming byte
  int currDigit;      //Convert char to digits
  int currColumn = 0;  //Current column we are working on
  long int currNumber = 0;  //Current number we are builing one byte at a time
  boolean readComplete = false;  //Have we read a full row yet?
  const char SEP = ',';  //Separator character
  const char END_FILE ='@'; //End of file character


  /*Shift the sensor reading array one row down to make room 
  for the current reading. Picture the most recent readings being 
  at the top of the array, and older ones at the bottom*/

  for (int i = HISTORY -1 ; i >=0; i--) { 
    for (int j = 0; j < NUMCOL; j++) {
      wheelSensor[i][j] = wheelSensor[i-1][j];
    }
  }

  //Get the next reading

  while (!readComplete) {

    if (Serial.available())  {

      currByte = Serial.read(); //Next byte on the serial line

      if (currByte >='0' && currByte <='9') {
        /*Get a number, convert it to an int, then put it in the one's place
         in the number we are building. Eg if the entry in the CSV is 654
         we will get 6, then 65, finally 654.*/
        currDigit = currByte - '0';
        currNumber = (currNumber * 10) + currDigit;
      }


      else if (currByte == SEP) {
        //Got a separater, number is complete, add it to the sensor array
        //We always add to the CURR row
        sensorReading[CURR][currColumn] = currNumber;

        //Reset the number we are building to make it ready for the next column
        currNumber = 0;

        if (currColumn == NUMCOL -1) {  
          //Last Column, reading is complete
          currColumn = 0;        
          readComplete = true;
        }

        else {
          //Move to the next column
          currColumn++;
        }

      }//End of Separator stuff

      else if (currByte == END_FILE) {

        Serial.end();
        break;  //Break out of while and close connection

      }

      else {
        //Invalid character
        //You can add your own error handling here if desired.
      }

    }// end of serial reading

  } // end of while loop

} // end of readSensor() function
Creative Commons License
Making a Better Wheelchair is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

No comments:

Post a Comment