Reading load cells, GPS, & saving it to SD card

Hello
I have used the code provided by Sparkfun.
I added my code to it. The problem is that when I added my code and wanted to save the results of downforce and drag force, it did not accept as it showed a declaration error. What I tried to do is that I added the load cells part to the byte part but then it stopped creating files completely, although there was no error.
So how can I save my load cell readings to the SD card the same way the GPS data is being stored?

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
long lastTime = 0;
long seconds = 0;
long minutes = 0;
long hours = 0;
int pinCS = 10;
// Create an LCD object. (Parameters)
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Sets the LCD I2C address
const float referenceVolts = 5; 
const int FrontLoadCell = A3;  
const int MidLoadCell = A1;   
const int RearLoadCell = A2;   
#define ARDUINO_USD_CS 10 
#define LOG_FILE_PREFIX "gpslog" 
#define MAX_LOG_FILES 100 
#define LOG_FILE_SUFFIX "csv" 
char logFileName[13]; 
#define LOG_COLUMN_COUNT 6
char * log_col_names[LOG_COLUMN_COUNT] = {
  "downforce", "dragforce","altitude", "speed", "date", "time"
}; // log_col_names is printed at the top of the file.
// Log Rate Control //
#define LOG_RATE 5000 // Log every 5 seconds
unsigned long lastLog = 0; // Global var to keep of last time we logged
TinyGPSPlus tinyGPS; 
#define GPS_BAUD 9600 
#include <SoftwareSerial.h>
#define ARDUINO_GPS_RX 9 
#define ARDUINO_GPS_TX 8 
SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX); // Create a SoftwareSerial
#define gpsPort ssGPS  // Alternatively, use Serial1 on the Leonardo
#define SerialMonitor Serial
{
  lcd.begin(20, 4); 
lcd.setCursor(0,0); 
lcd.print("Downforce ="); 
lcd.setCursor(0,1);
lcd.print("Dragforce =");
lcd.setCursor(0,2); 
lcd.print("Speed     =");
lcd.setCursor(0,3); 
lcd.print("Time="); 
  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);
  SerialMonitor.println("Setting up SD card.");
  if (!SD.begin(ARDUINO_USD_CS))
  {
    SerialMonitor.println("Error initializing SD card.");
  }
  updateFileName(); 
  printHeader(); 
}
void loop()
{
   if(millis()-lastTime > 1000)
  {
    seconds++;
    lastTime = millis();
  }
    if(seconds > 60){
    minutes++;
    seconds = 0;
    }
    if(minutes > 60){
    hours++;
    minutes = 0;
  }
  // wait a few seconds between measurements.
  delay(1000); // delay 1 second
  float flc = analogRead(FrontLoadCell); // reads the value from the sensor 
  float FLCvolts = ((flc / 1023.0) * referenceVolts)*26.082; // calculates the ratio
  
  float rlc = analogRead(RearLoadCell); // reads the value from the sensor 
  float RLCvolts = ((rlc / 1023.0) * referenceVolts)*34.014; // calculates the ratio
  
  float mlc = analogRead(MidLoadCell); // reads the value from the sensor 
  float MLCvolts = ((mlc / 1023.0) * referenceVolts)*17; // calculates the ratio

float downforce = FLCvolts + RLCvolts;
float dragforce = MLCvolts;

  if ((lastLog + LOG_RATE) <= millis())
  { // If it's been LOG_RATE milliseconds since the last log:
    if (tinyGPS.location.isUpdated()) 
    {
      if (logGPSData()) 
      {
        SerialMonitor.println("GPS logged."); 
        lastLog = millis(); // Update the lastLog variable
      }
      else 
      {
        SerialMonitor.println("Failed to log new GPS data.");
      }
    }
    else // If GPS data isn't valid
    {
      // Print a debug message. Maybe we don't have enough satellites yet.
      SerialMonitor.print("No GPS data. Sats: ");
      SerialMonitor.println(tinyGPS.satellites.value());
    }
  }
  while (gpsPort.available())
    tinyGPS.encode(gpsPort.read());
}
byte logGPSData()
{

  File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file
  if (logFile)
  { // Print longitude, latitude, altitude (in feet), speed (in kmph), course
    // in (degrees), date, time, and number of satellites.
    
    logFile.print(downforce);
    logFile.print(',');
    logFile.print(dragforce);
    logFile.print(',');
    logFile.print(tinyGPS.speed.kmph(), 1);
    logFile.print(',');
    logFile.print(tinyGPS.date.value());
    logFile.print(',');
    logFile.print(tinyGPS.time.value());
    logFile.println();
    logFile.close();
    return 1; 
  }
  return 0; 
}
void printHeader()
{
  File logFile = SD.open(logFileName, FILE_WRITE); 
  if (logFile) 
  {
    int i = 0;
    for (; i < LOG_COLUMN_COUNT; i++)
    {
      logFile.print(log_col_names[i]);
      if (i < LOG_COLUMN_COUNT - 1) 
       logFile.print(','); 
      else 
        logFile.println(); // print a new line
    }
    logFile.close(); // close the file
  }
}

void updateFileName()
{
  int i = 0;
  for (; i < MAX_LOG_FILES; i++)
  {
    memset(logFileName, 0, strlen(logFileName)); 
    sprintf(logFileName, "%s%d.%s", LOG_FILE_PREFIX, i, LOG_FILE_SUFFIX);
    if (!SD.exists(logFileName)) 
    {
      break; 
    }
    else 
    {
+      SerialMonitor.print(logFileName);
      SerialMonitor.println(" exists"); 
    }
  }
  SerialMonitor.print("File name: ");
  SerialMonitor.println(logFileName); 
}

What is the error? There is a handy little button in the IDE "copy error messages" that you can use to paste your error message here, inside code tags since not everyone has all your libraries loaded, etc.

exit status 1

'downforce' was not declared in this scope

As I previously mentioned, I have overcome this problem by declaring it inside the byte part. But this resulting in no errors but it stopped creating files completely.
So am I doing it wrong? Is there another way to do so? What can be a solution?

There is more to the error message than that. You did not copy the entire message.

You are declaring that variable inside of loop() so it is only visible/available inside that function. You are trying to use it inside the LogGPSData() function. You need to declare this variable outside of all your functions to make it global. This is usually done at the top of the sketch, after all the #includes.

#include <stuff>
float downforce;  // global

void setup() {
...
}
void loop() {
....
downforce = FLCvolts + RLCvolts;  // do not use 'float' here or you will create a different variable - just assign to global
}

void logGPSData() {
...
print(downforce);
....
}

you will have to do this with all the variables you want to write into the log file.

Great, I fixed them all based on your suggested solution.
But now only files are being created with empty content inside. Totally empty.

mihranser:
But now only files are being created with empty content inside. Totally empty.

Perhaps provide some detail as to what that actually means ?
Most would assume that if a file has, as you say 'content' it is not empty.

Inside the SD card excel files are being created/generated but when I open the excel files on my PC they are empty.

Further details: If you see the code which I posted, it is supposed to write inside the file statements, results, but it is being completely empty. Going back to the original code provided by Sparkfun, I tried the original code again, and works well. It's only when my part is added it all stops writing into the file.

But you have changed the that you originally posted so you need to reply and include the NEW code that is not working. Making people guess what is wrong is a terrible way to debug code

Dear I have only changed what @srnet suggested me to do. It's not that I came up with something totally different than what I posted and let you do the guessing. I have made it clear in my previous reply.
The following is the adjusted based on @srnet

#include <SPI.h>
#include <SD.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <SoftwareSerial.h>
#include <TinyGPS++.h>
float downforce;
float dragforce;
float flc;
float FLCvolts;
float rlc;
float RLCvolts;
float mlc;
float MLCvolts;
long lastTime = 0;
long seconds = 0;
long minutes = 0;
long hours = 0;
int pinCS = 10;
// Create an LCD object. (Parameters)
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Sets the LCD I2C address
const float referenceVolts = 5;
const int FrontLoadCell = A3; 
const int MidLoadCell = A1;   
const int RearLoadCell = A2;   
#define ARDUINO_USD_CS 10
#define LOG_FILE_PREFIX "gpslog"
#define MAX_LOG_FILES 100
#define LOG_FILE_SUFFIX "csv"
char logFileName[13];
#define LOG_COLUMN_COUNT 5
char * log_col_names[LOG_COLUMN_COUNT] = {
  "longitude", "latitude", "speed", "date", "time"
}; // log_col_names is printed at the top of the file.
// Log Rate Control //
#define LOG_RATE 1000 // Log every 1 seconds
unsigned long lastLog = 0; // Global var to keep of last time we logged
TinyGPSPlus tinyGPS;
#define GPS_BAUD 9600
#include <SoftwareSerial.h>
#define ARDUINO_GPS_RX 9
#define ARDUINO_GPS_TX 8
SoftwareSerial ssGPS(ARDUINO_GPS_TX, ARDUINO_GPS_RX); // Create a SoftwareSerial
#define gpsPort ssGPS  // Alternatively, use Serial1 on the Leonardo
#define SerialMonitor Serial
void setup()
{
  lcd.begin(20, 4);
lcd.setCursor(0,0);
lcd.print("Downforce =");
lcd.setCursor(0,1);
lcd.print("Dragforce =");
lcd.setCursor(0,2);
lcd.print("Speed     =");
lcd.setCursor(0,3);
lcd.print("Time=");
  SerialMonitor.begin(9600);
  gpsPort.begin(GPS_BAUD);
  SerialMonitor.println("Setting up SD card.");
  if (!SD.begin(ARDUINO_USD_CS))
  {
    SerialMonitor.println("Error initializing SD card.");
  }
  updateFileName();
  printHeader();
}
void loop()
{
  if ((lastLog + LOG_RATE) <= millis())

  { // If it's been LOG_RATE milliseconds since the last log:

    if (tinyGPS.location.isUpdated()) // If the GPS data is vaild

    {

      if (logGPSData()) // Log the GPS data

      {

        SerialMonitor.println("GPS logged."); // Print a debug message

        lastLog = millis(); // Update the lastLog variable

      }

      else // If we failed to log GPS

      { // Print an error, don't update lastLog

        SerialMonitor.println("Failed to log new GPS data.");

      }

    }

    else // If GPS data isn't valid

    {

      // Print a debug message. Maybe we don't have enough satellites yet.

      SerialMonitor.print("No GPS data. Sats: ");

      SerialMonitor.println(tinyGPS.satellites.value());

    }

  }

 

  // If we're not logging, continue to "feed" the tinyGPS object:

  while (gpsPort.available())

    tinyGPS.encode(gpsPort.read());

   if(millis()-lastTime > 1000)
  {
    seconds++;
    lastTime = millis();
  }
    if(seconds > 60){
    minutes++;
    seconds = 0;
    }
    if(minutes > 60){
    hours++;
    minutes = 0;
  }
  // wait a few seconds between measurements.

flc = analogRead(FrontLoadCell); // reads the value from the sensor
FLCvolts = ((flc / 1023.0) * referenceVolts)*26.082; // calculates the ratio
 
rlc = analogRead(RearLoadCell); // reads the value from the sensor
RLCvolts = ((rlc / 1023.0) * referenceVolts)*34.014; // calculates the ratio
 
mlc = analogRead(MidLoadCell); // reads the value from the sensor
MLCvolts = ((mlc / 1023.0) * referenceVolts)*17; // calculates the ratio

downforce = FLCvolts + RLCvolts;
dragforce = MLCvolts;

}

byte logGPSData()
{

  File logFile = SD.open(logFileName, FILE_WRITE); // Open the log file
  if (logFile)
  { // Print longitude, latitude, altitude (in feet), speed (in kmph), course
    // in (degrees), date, time, and number of satellites.
   
    logFile.print(downforce);
    logFile.print(',');
    logFile.print(dragforce);
    logFile.print(',');
    logFile.print(tinyGPS.speed.kmph(), 1);
    logFile.print(',');
    logFile.print(tinyGPS.date.value());
    logFile.print(',');
    logFile.print(tinyGPS.time.value());
    logFile.println();
    logFile.close();
    return 1;
  }
  return 0;
}
void printHeader()
{
  File logFile = SD.open(logFileName, FILE_WRITE);
  if (logFile)
  {
    int i = 0;
    for (; i < LOG_COLUMN_COUNT; i++)
    {
      logFile.print(log_col_names[i]);
      if (i < LOG_COLUMN_COUNT - 1)
       logFile.print(',');
      else
        logFile.println(); // print a new line
    }
    logFile.close(); // close the file
  }
}

void updateFileName()
{
  int i = 0;
  for (; i < MAX_LOG_FILES; i++)
  {
    memset(logFileName, 0, strlen(logFileName));
    sprintf(logFileName, "%s%d.%s", LOG_FILE_PREFIX, i, LOG_FILE_SUFFIX);
    if (!SD.exists(logFileName))
    {
      break;
    }
    else
    {
+      SerialMonitor.print(logFileName);
      SerialMonitor.println(" exists");
    }
  }
  SerialMonitor.print("File name: ");
  SerialMonitor.println(logFileName);
}

If your file is empty, then LogGPSData() must not be called which means tinyGPS.location.isUpdated() must be false. Maybe your are not getting any GPS data? Read this article about how to add some error checking...

Yes, I assumed that can be a reason, but the next thing I tried was the original code removing my part for the loadcells (just to check if there is anything wrong with the GPS detection) and it worked very well. So this is what I can't understand, how come it works very well and later when I add my part, the files that are being generated in the SD card are empty inside (no content)?

Can you post both the original, working code and your code? A side by side comparison would be helpful.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.