coding data logger ... first time coding

Hi,

My compute key board is still in one piece, but is looking at me very nervously, although I hope the answer is, "your almost there, just a few newbie errors"

This is my code - it is supposed to be a date logger for a small sensor array I am building, but I am receiving an error message regarding the "if (commandFile)" statement. I suspect I have an unresolved problem regarding the readings from the sensors?

Any help at this stage would be just great!

#include <SD.h>           //SD Card Library

//SPI SD Card Pins
//MOSI, MISO, SCLK set by default
int CS_pin = 10;
int pow_pin = 8;

//Flex Sensor Pins
int FS1_pin = 1;
int FS2_pin = 2;
int FS3_pin = 3;
int FS4_pin = 4;

float refresh_rate = 0.0;   //Datalogger Refresh Rate
long id = 1;                //ID# for readings

void setup()
{
  Serial.begin(9600);
  Serial.print("Initialising SD card");
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin,HIGH);
  //Intialise Card
  if (!SD.begin(CS_pin)) 
  {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialised");
}
//Read the Configuration inforation (COMMANDS.txt) stored on SD
File commandFile = SD.open("COMMANDS.txt");
if (commandFile}
{
  Serial.println("Reading Command File");

  float decade = pow(10, (commandFile.available() - 1));
  while(commandFile.available())
  {
    float temp = (commandFile.read() -'0');
    refresh_rate = temp*decade+refresh_rate;
    decade = decade/10;
  }
  Serial.print("Refresh Rate = ");
  Serial.print(refresh_rate);
  Serial.println("ms");
}
else
{
  Serial.println("Could not read command file.");
}

//Write Log File Header
File logFile = SD.open ("LOG.csv", FILE_WRITE);
if (logFile) {
  logFile.println(",,,,");
  String header = "Flex 1, Flex 2, Flex 3, Flex 4";
  logFile.println(header);
  logFile.close();
  Serial.println(header);}

else 
{
  Serial.println("Error opening Log.csv");
}


void loop()
{
  //Read Flex Sensors
  FS1_val = analogRead(FS1_pin);
  FS2_val = analogRead(FS2_pin);
  FS3_val = analogRead(FS3_pin);
  FS4_val = analogRead(FS4_pin);  
}
  //Create Data String for storing to SD card using CSV format
  String dataString = String(FS1_pin) + "," + String(FS2_pin) + "," String(FS3_pin) + "," String(FS4_pin);
  
  //Open a file
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logfile)
{
  logFile.println(dataString);
  logFile.close();
  Serial.println(dataString);
  }    
  else
{
  Serial.println("Couldn't open log file");
}

//Inrement ID number
id++;

delay(refresh_rate);
}

All code needs to be inside a function body. You have a lot of code between the end of setup() and the beginning of loop, that needs to be moved (probably into setup()).

Funkymonkey:
My compute key board is still in one piece, but is looking at me very nervously, although I hope the answer is, "your almost there, just a few newbie errors"

Well, not too bad but it looks like you need to learn some of the basics - the only way I could sort your problem was to run it thru the compiler myself. You have a problem with open/close brackets where they really don't need to be.

You also need to declare all your variables.

I've modified your code so it will compile. Please do yourself a favor and understand why this code compiles and the code you posted doesn't. BTW you should probably drop the String library as well, but I think that's a different post.

#include <SD.h>           //SD Card Library

//SPI SD Card Pins
//MOSI, MISO, SCLK set by default
int CS_pin = 10;
int pow_pin = 8;

//Flex Sensor Pins
int FS1_pin = 1;
int FS2_pin = 2;
int FS3_pin = 3;
int FS4_pin = 4;

float refresh_rate = 0.0;   //Datalogger Refresh Rate
long id = 1;                //ID# for readings

void setup()
{
  Serial.begin(9600);
  Serial.print("Initialising SD card");
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin,HIGH);
  //Intialise Card
  if (!SD.begin(CS_pin)) 
  {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialised");

  //Read the Configuration inforation (COMMANDS.txt) stored on SD
  File commandFile = SD.open("COMMANDS.txt");
  if (commandFile)
  {
    Serial.println("Reading Command File");

    float decade = pow(10, (commandFile.available() - 1));
    while(commandFile.available())
    {
      float temp = (commandFile.read() -'0');
      refresh_rate = temp*decade+refresh_rate;
      decade = decade/10;
    }
    Serial.print("Refresh Rate = ");
    Serial.print(refresh_rate);
    Serial.println("ms");
  }
  else
  {
    Serial.println("Could not read command file.");
  }

  //Write Log File Header
  File logFile = SD.open ("LOG.csv", FILE_WRITE);
  if (logFile) 
  {
    logFile.println(",,,,");
    String header = "Flex 1, Flex 2, Flex 3, Flex 4";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else 
    Serial.println("Error opening Log.csv");
}


void loop()
{
  //Read Flex Sensors
  int FS1_val = analogRead(FS1_pin);
  int FS2_val = analogRead(FS2_pin);
  int FS3_val = analogRead(FS3_pin);
  int FS4_val = analogRead(FS4_pin);  

  //Create Data String for storing to SD card using CSV format
  String dataString = String(FS1_pin) + "," + String(FS2_pin) + "," + String(FS3_pin) + "," + String(FS4_pin);

  //Open a file
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
  }    
  else
  {
    Serial.println("Couldn't open log file");
  }

  //Inrement ID number
  id++;

  delay(refresh_rate);
}

I hope this helps,

Brad.

Wow - thank you for your help guys!

I was just about to post this code, so I was getting there!

#include <SD.h>           //SD Card Library

//SPI SD Card Pins
//MOSI, MISO, SCLK set by default
int CS_pin = 10;
int pow_pin = 8;

//Flex Sensor Pins
int FS1_pin = 1;
int FS2_pin = 2;
int FS3_pin = 3;
int FS4_pin = 4;

float refresh_rate = 0.0;   //Datalogger Refresh Rate
long id = 1;                //ID# for readings

void setup()
{
  Serial.begin(9600);
  Serial.print("Initialising SD card...");
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin,HIGH);
  //Intialise Card
  
  if (!SD.begin(CS_pin)) {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialised");

  //Read the Configuration inforation (COMMANDS.txt) stored on SD
  File commandFile = SD.open("COMMANDS.txt", FILE_READ);
  
  if (commandFile) {
    Serial.println("Reading Command File");

  float decade = pow(10, (commandFile.available() - 1));
  while(commandFile.available())
  {
    float temp = (commandFile.read() -'0');
    refresh_rate = temp*decade+refresh_rate;
    decade = decade/10;
  }
  Serial.print("Refresh Rate = ");
  Serial.print(refresh_rate);
  Serial.println("ms");
  }
  else  {
  Serial.println("Could not read command file.");
  }

  //Write Log File Header
  File logFile = SD.open ("LOG.csv", FILE_WRITE);
  if (logFile) {
    logFile.println(",,,,");
    String header = "Flex 1, Flex 2, Flex 3, Flex 4";
    logFile.println(header);
    logFile.close();
    Serial.println(header); }
  
  else  {
  Serial.println("Error opening Log.csv");
}

I'm starting to encounter problems with the string code, so I have been looking at this: http://arduino.cc/en/Tutorial/Datalogger, but I'll need to read more before I can adapt it.

While some people argue that the { goes on the same line as the if, for, or while statement, I think it is easier for beginners to follow code like:

while(someCondition)
{
   if(anotherCondition)
   {
      // Do something
   }
   else
   {
      // Do something else
   }
}

Proper indentation can be obtained by using the Tools + Auto format menu option.

Paul, thanks, this helps a lot!

So this code appears to be working - I haven't physically built the unit, however I am reading the values you would expect - between 280 and 320, representing voltage/signal fluctuations? Learning not to think of it a code, but maths with words appeared to help a lot.

I don't know if I should be thinking about this http://arduino.cc/en/Tutorial/Calibration. Accuracy is important, but my code is already starting a likely bulky. Are there things I can do to trim this code - pointer or links would be appreciated!

#include <SD.h>           //SD Card Library

//SPI SD Card Pins
//MOSI, MISO, SCLK set by default
int CS_pin = 10;
int pow_pin = 8;

//Flex Sensor Pins
int FS1_pin = A0;
int FS1Value = 0;
int FS2_pin = A1;
int FS2Value = 0;
int FS3_pin = A2;
int FS3Value = 0;
int FS4_pin = A3;
int FS4Value = 0;

float refresh_rate = 0.0;   //Datalogger Refresh Rate
long id = 1;                //ID# for readings

void setup()
{
  Serial.begin(9600);
  Serial.print("Initialising SD card");
  pinMode(CS_pin, OUTPUT);
  pinMode(pow_pin, OUTPUT);
  digitalWrite(pow_pin,HIGH);
  //Intialise Card
  if (!SD.begin(CS_pin)) 
  {
    Serial.println("Card failed, or not present");
    return;
  }
  Serial.println("Card initialised");

  //Read the Configuration inforation (COMMANDS.txt) stored on SD
  File commandFile = SD.open("COMMANDS.txt");
  if (commandFile)
  {
    Serial.println("Reading Command File");

    float decade = pow(10, (commandFile.available() - 1));
    while(commandFile.available())
    {
      float temp = (commandFile.read() -'0');
      refresh_rate = temp*decade+refresh_rate;
      decade = decade/10;
    }
    Serial.print("Refresh Rate = ");
    Serial.print(refresh_rate);
    Serial.println("ms");
  }
  else
  {
    Serial.println("Could not read command file.");
  }

  //Write Log File Header
  File logFile = SD.open ("LOG.csv", FILE_WRITE);
  if (logFile) 
  {
    logFile.println(",,,,");
    String header = "Flex 1, Flex 2, Flex 3, Flex 4";
    logFile.println(header);
    logFile.close();
    Serial.println(header);
  }
  else 
    Serial.println("Error opening Log.csv");
}


void loop()
{
  //Read Flex Sensors
  FS1Value = analogRead(FS1_pin);
  FS2Value = analogRead(FS2_pin);
  FS3Value = analogRead(FS3_pin);
  FS4Value = analogRead(FS4_pin);  

  //Create Data String for storing to SD card using CSV format
  String dataString = String(FS1Value) + "," + String(FS2Value) + "," + String(FS3Value) + "," + String(FS4Value);

  //Open a file
  File logFile = SD.open("LOG.csv", FILE_WRITE);
  if (logFile)
  {
    logFile.println(dataString);
    logFile.close();
    Serial.println(dataString);
  }    
  else
  {
    Serial.println("Couldn't open log file");
  }

  //Inrement ID number
  id++;

  delay(refresh_rate);
}

Funkymonkey:
Are there things I can do to trim this code - pointer or links would be appreciated!

I'd suggest taking a look at how arrays work (see http://arduino.cc/it/Reference/Array) and think about how you could create a pair of arrays - one for your analog pins, and one for the values you've read.

(I suggest two arrays instead of a single 2-dimensional array since the array of pins should be 'const')

That will make it much easier to cycle thru the pins you want to use and the values you're trying to process (also makes it only a dozen or so lines to implement calibration).

I hope this gives you a start,

Brad.

There's is a lot of copy and paste in my code at the moment, but I will look again a 'arrays'. I will read more over the weekend, but now I have something that it working, I can start to build. I'm trying to get my head around this at the moment: http://arduino.cc/forum/index.php/topic,60666.0.html and whether it is critical function or not ... how do I decide?

Ok, first off, since I did this for you but didn't post it, here is a quick look at how arrays could work for you

const int sensorPins[] = {0, 1, 2, 3};
const int noPins = 4;
int sensorValues[noPins];

...

// in setup()... 

// don't forget to setup the pins
for (int indx=0; indx < noPins; indx++)
   pinMode(sensorPins[indx], INPUT);

...

// in loop()

for (indx=0; indx < noPins; indx++)
{
   sensorValues[indx] = analogRead(sensorPins[indx]);
}

Note in your case, you don't really need the 'sensorPins' array - you could simply use the value of 'indx' instead (since the analog pins you're using are sequential). The advantage would be if you were to add another sensor on A5, for example, skipping A4.

As far as calibration goes, I'll leave that to those who've done it but I will say it's fairly trivial to implement the original link you supplied, something like this:

int sensorMin = 1023;        // minimum sensor value
int sensorMax = 0;           // maximum sensor value

...

void setup() 
{
  ...

  // calibrate during the first five seconds 
  while (millis() < 5000) {
     sensorValue = analogRead(sensorPin);
 
    // record the maximum sensor value
     if (sensorValue > sensorMax) {
       sensorMax = sensorValue;
     }
 
    // record the minimum sensor value
     if (sensorValue < sensorMin) {
       sensorMin = sensorValue;
     }
   }
}  


...

void loop()
{
...

  for (indx = 0; indx < noPins; indx++) 
  {
     // read the analog pin
     sensorValue = analogRead(sensorPins[indx]);

     // apply the calibration to the sensor reading
     sensorValue = map(sensorValue, sensorMin, sensorMax, 0, 255);
 
     // in case the sensor value is outside the range seen during calibration
     sensorValue = constrain(sensorValue, 0, 255);

     sensorValues[indx] = sensorValue;
  }

I hope this helps,

Brad.

PS perhaps the name choices weren't the best here ('sensorValue' vs. 'sensorValues') but that's what I get for combining code fragments on the fly.

It sure does! I will need to read a bit more to understand it fully. Is it possible to use all the pins within an array, provided the digital pin is assigned as noPins?

Funkymonkey:
It sure does! I will need to read a bit more to understand it fully. Is it possible to use all the pins within an array, provided the digital pin is assigned as noPins?

There should be no problem using the array for either digital or analog pins - it should just work. Of course you may have to be careful how you use the pins (not sure what happens if you try to 'analogRead' w/ a digital pin for example).

And note that 'noPins' is actually the number of elements in the array (probably 'numberOfPins' would be a better name), just to be clear :slight_smile:

So if you add a new pin to the array you'll want to increment 'noPins' as well.

I hope this makes sense,

Brad.

MUCH appreciated!