Need help performing multiple calculations with variables.

I need a bit of help performing calculations with different variables for my ECM to Arduino project. I am starting a new thread since I have solved the buffer problems and have moved into the next phase of the project with a different set of challenges. If you are interested in the previous discussion you can find it http://arduino.cc/forum/index.php/topic,96280.0.html

I am new to doing math and calculations with the arduino and I do not know how to set up the variables properly for some of the equations to work, so I need some help from you guys to get this working.

My code thus far:

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the TPS on the LCD screen and all data via serial monitor.
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
long unsigned TPS;
float ATemp;
float ADensity;
unsigned LastSpeed;
unsigned Speed;
long unsigned LastSpeedTimestamp;
long unsigned SpeedTimestamp;

unsigned RPM;
float Accel;
float Power;
int Torque;
int IterationNumber = 0;
int ByteNumber;
int Processing = 0;

void setup(){
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);
  ByteNumber = 0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum

  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD);
  requestData();
}

//Send data request to ECM
void requestData() {
  //lcd.setCursor(0,0);
  for (int i = 0; i<9; i+=1)
    mySerial.write(inArray[i]);
  //Do not place code here
}

//display the array in serial monitor
void displayData(){
  for (int j = 0; j<107; j+=1){
    Serial.println(outArray[j],HEX);
  }
  Serial.println("Data Printed");
  Processing = 0;
}

//Display the Throttle Position Sensor
void callTPS(){
  TPS = outArray[91] << 8 | outArray[90];
  lcd.setCursor(0,0); //right then down
  lcd.print("TPS: ");
  lcd.print(TPS); 
}

//Obtain Air Temp and Density
void callATemp(){
  ATemp = (outArray[33] << 8 | outArray[32]) * 0.18 -40;
  ADensity = (39.1282 / (ATemp + 460));
}

//Obtain Speed and Acceleration
void callSpeed(){
  LastSpeed = Speed;
  Speed = outArray[99];
  LastSpeedTimestamp = SpeedTimestamp;
  SpeedTimestamp = millis();
  Accel = (Speed - LastSpeed)*1000/(SpeedTimestamp-LastSpeedTimestamp);
}

//Obtain RPM
void callRPM(){
  RPM = outArray[12] << 8 | outArray[11];
}

//Calculate Horsepower and Torque
void callPower(){
  Power = (16.784*(Accel*1.467+0.018*32.174)+(0.5*ADensity*0.382*214.6*(Speed*1.467)^2))*Speed*1.467;
  Torque1 = Power 
}


void loop() {
  if (mySerial.available () > 0) {
    outArray[ByteNumber ++] = mySerial.read();
  }
  if (ByteNumber > 106){  // process it
    Serial.println("Data Stream Read");
    ByteNumber = 0;  // ready for next time
    //displayData();
    lcd.setCursor(1,1);
    callTPS();
    callATemp();
    requestData();  //restart data
    //Do not place code here
  }  // end if full
}  // end of loop

At the moment when I try to compile the code I get the error message

invalid operands of types 'double' and 'int' to binary 'operator^'

at the line:

Power = (16.784*(Accel*1.467+0.018*32.174)+(0.5*ADensity*0.382*214.6*(Speed*1.467)^2))*Speed*1.467;

This is the original equation:

It calculates the power from acceleration, rolling resistance, and drag of a vehicle at any given speed. The numbers are constants and unit conversions. I don't want to simplify them further because I won't be able to quickly change one variable without recalculating everything (like mass or cross sectional area)

What types of variables should should Accel ADensity and Speed be for the equation to work?

Caret (^) is exclusive-or not raise-to-the-power.

Pick the one you prefer...

Power = (16.784*(Accel1.467+0.01832.174)+(0.5ADensity0.382214.6(Speed1.467)(Speed*1.467)))Speed1.467;

Power = (16.784*(Accel1.467+0.01832.174)+(0.5ADensity0.382214.6pow(Speed*1.467,2)))Speed1.467;

What types of variables should should Accel ADensity and Speed be for the equation to work?

float, float, and unsigned should be fine.

Thanks for the help, I was able to successfully compile it, hopefully the calculations will work out fine when I hook up the arduino when I get home this Friday.

Firstly I'd refactor the code so that the final line reads just like the equation you've got - use variables called Sv, Ad, Cd etc.

Rescale all your input values into the correct units first (I presume this mean SI units) - all the physics calculations should be in sensible consistent units, all the conversions to other units should be done on the input and output routines. Document the units for every variable anyway. This makes it much easier to avoid inconsistent units bugs. If you stick to SI then everything is easy and foolproof.

It's always wise to move constant values into #defines or "const float BLAH = ...;" declarations. Then each constant value is only in one place and is named. Naming is good, an anonymous "1.467" may mean nothing to the next person to come along and tinker with the code - it may mean nothing to you in a year's time too! Document the units for each constant too.

Thanks for the suggestions! I did rescale all my units, but I had to do it to English units, luckily I only had to do 3 rescales (which are the 1.467s you see in there). It took me a good 2 hours of writing down the equation by hand with units and figuring out how and what to convert to the units I needed. I documented all of the conversions and everything into Mathcad afterward which will essentially be the operator manual to the arduino code.

What are #defines? I have not seen that before. How is it structured?

The compiler works basically in two steps. First is the preprocessor which alters the code and prepares it for the compiler. Second step is translation to machine code by the compiler.

#define MAX_VALUE 100

This is a preprocessor statement. Every MAX_VALUE is replaced with whatever comes after the MAX_VALUE until the end of the line by the preprocessor. If you use MAX_VALUE constantly as a replacement for a constant value in your code, you only have to change the value in one place to modify your code. But you can use for a lot more...

Oh thats awesome! It makes total sense now. I will definitely use more #defines then. Can I place them anywhere in the code or do they need to stay near the top (outside of any functions)?

You can put them anywhere before the point where what they define is used

You have at least mixed your types, all the vaiables are floating point except "Speed," it appears to be an "unsigned" but not given a type. I only know of unsigned int, char, and long. You need to at least make Speed a float.

You should check your types as well, you have declared some variables as "long unsigned" when I think they should be "unsigned long." You have some that are just unsigned without a type, char, int, or long.

"Torgue1" appears to be undeclared.

When the unsigned keyword is used without a type, int is assumed.

Whether unsigned appears before or after the type doesn't matter. The actual type/processing is the same.

I added more #defines for the power equation, and also changed some of the variable types. I also added the adafruit datalogger shield for an SD card. I ran out of regular digital I/O pins so I had to switch the LCD screen to use the analog pins as digital I/O. I have to say, the arduino looks a lot more substantial with a shield plugged into the top of it.

I have yet to test the code on the motorcycle. I am going home today so I can do a lot of work on it this weekend. I am expecting it to not work the first time I plug it in with all of the additional code, seems like thats just how this project has been.

Here is the code now:

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the limited data on the LCD. Recent additions include air
 density, acceleration, power and torque calculations
 (untested). Datalogging capabilites have also been added
 (also untested).
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

#define SYNC_INTERVAL 2000
uint32_t syncTime = 0; //time of last sync()

RTC_DS1307 RTC;  //define the Real Time Clock object

// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;

//the logging file;
File logfile;

//print errors to Serial monitor
void error(char *str) {
  Serial.print("error: ");
  Serial.println(str);
  while(1);
}

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
LiquidCrystal lcd(A0, A1, A2, A3, A4, A5, A6);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
long unsigned TPS;
float ATemp;
float ADensity;
float LastSpeed;
float Speed;
long unsigned LastSpeedTimestamp;
long unsigned SpeedTimestamp;
unsigned RPM;
float Accel;
float Power;
float Torque1;
int IterationNumber = 0;
int ByteNumber;
int Processing = 0;

void setup(void){
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);

  //initialize the SD card
  lcd.println("Initializing SD ");
  lcd.print("card...");
  Serial.print("Initializing SD card...");
  pinMode(10,OUTPUT);

  //see if the card is present and can be initialized
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  }
  Serial.println("card initialized.");
  lcd.clear();
  lcd.println("...Card");
  lcd.print("initialized");

  //create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }

  if (!logfile) {
    error("couldn't create file");
  }

  lcd.clear();
  lcd.println("Logging to:");
  lcd.print(filename);
  Serial.print("Logging to: ");
  Serial.println(filename);

  //connect to RTC
  Wire.begin();
  if (!RTC.begin()) {
    logfile.println("RTC failed");
    Serial.println("RTC failed");
  }

  //create header for the log file
  logfile.println("millis,Date Time,TPS,RPM,Power");
  logfile.flush();

  ByteNumber = 0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum
  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD); //unsure on correcy syntax
  requestData();
}

//Send data request to ECM
void requestData() {
  //lcd.setCursor(0,0);
  for (int i = 0; i<9; i+=1)
    mySerial.write(inArray[i]);
  //Do not place code here
}

//display the array in serial monitor currently. this breaks the program
void displayData(){
  for (int j = 0; j<107; j+=1){
    Serial.println(outArray[j],HEX);
  }
  Serial.println("Data Printed");
}

//Display the Throttle Position Sensor
void callTPS(){
  TPS = outArray[91] << 8 | outArray[90];
  lcd.setCursor(0,0); //right then down
  lcd.print("TPS");
  lcd.print(TPS); 
}

//Obtain Air Temp and Density
void callATemp(){
  ATemp = (outArray[33] << 8 | outArray[32]) * 0.18 -40;
  ADensity = (39.1282 / (ATemp + 460));
}

//Obtain Speed and Acceleration
void callSpeed(){
  LastSpeed = Speed;
  Speed = outArray[99];
  LastSpeedTimestamp = SpeedTimestamp;
  SpeedTimestamp = millis();
  Accel = (Speed - LastSpeed)*1000/(SpeedTimestamp-LastSpeedTimestamp);
  lcd.setCursor(9,1); //right then down
  lcd.print("Speed");
  lcd.print(Speed); 
}

//Obtain RPM
void callRPM(){
  RPM = outArray[12] << 8 | outArray[11];
  lcd.setCursor(9,0); //right then down
  lcd.print("RPM");
  lcd.print(RPM); 
}

//Calculate Horsepower and Torque
void callPower(){
  //defining constants in the power equation
#define Slugs 16.784  //mass of bike with 150lb rider
#define SpeedConvert 1.467  //mile/hour to feet/sec conversion
#define Crr 0.018  //coefficient of rolling resistance of tire
#define Gravity 32.174  //acceleration of gravity in Engilish
#define Cd 0.382 //Coefficient of drag of the bike
#define Av 1.49 //Cross sectional area of bike in ft^2
  Power = (Slugs*(Accel*SpeedConvert+Crr*Gravity)+(0.5*ADensity*Cd*Av*pow(Speed*SpeedConvert,2)))*Speed*SpeedConvert;
  Torque1 = Power*5252/RPM;
  lcd.setCursor(0,1); //right then down
  lcd.print("Power");
  lcd.print(Power); 
}


void loop(void) {
  if (mySerial.available () > 0) {
    //fill the data array
    outArray[ByteNumber ++] = mySerial.read();
  } 
  else {
    //retry requesting data
    mySerial.flush();
    requestData();
    ByteNumber = 0;
  }
  if (ByteNumber > 106){  // process it
    Serial.println("Data Stream Read");
    ByteNumber = 0;  // ready for next time

    callTPS();
    callATemp();
    callSpeed();
    callRPM();
    callPower();

    DateTime now;
    uint32_t m = millis();
    logfile.print(m);
    logfile.print(", ");
    now = RTC.now();
    logfile.print(now.year(), DEC);
    logfile.print(now.month(), DEC);
    logfile.print(now.day(), DEC);
    logfile.print("_");
    logfile.print(now.hour(), DEC);
    logfile.print(now.minute(), DEC);
    logfile.print(now.second(), DEC);
    logfile.print(", ");
    logfile.print(TPS, DEC);
    logfile.print(", ");
    logfile.print(RPM, DEC);
    logfile.print(", ");
    logfile.print(Power, DEC);
    logfile.println();

    //Write to disk
    if ((millis() - syncTime) < SYNC_INTERVAL){
      logfile.flush();
      syncTime = millis();
    }

    lcd.setCursor(1,1);
    callTPS();
    callATemp();
    callSpeed();
    callRPM();
    callPower();

    requestData();  //restart data
    //Do not place code here
  }  // end if full
}  // end of loop
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

What is connected to these two pins? Why does the instance name not reflect that? Clearly, you didn't connect a mySerial to the pins. If you are using this to talk to the ECM, name the instance to reflect that. It makes reading the code make a lot more sense.

// set up a new serial port
SoftwareSerial mySerial =  SoftwareSerial(rxPin, txPin);

This is an unnecessary assignment. Try:

// set up a new serial port
SoftwareSerial mySerial (rxPin, txPin);

Thanks for the suggestions.

I was working on the my program today and got it hooked up to the bike again. The arduino communicates with the ECM and logs all the data correctly on the SD card, but the LCD screen is having some major issues. I know it is connected properly, because I tested it with an older version of my code, and it displays TPS just fine and is nice and fast.

Now when I hook up the arduino to the ECM, the screen shows initial "initializing SD card" and that. The next step is supposed to display Logging to (and then the file name). That works sort of correctly, but it shows some japanese characters before the file name......I just realized that might be because I used lcd.println(), instead of lcd.print()

The next part is the real trouble with the LCD - it displays this:

It pops up 1 symbol at a time from left to right and fills up the screen in a few seconds.

It SHOULD show TPS160 SPEED00, etc. I tried using just callTPS by itself and the LCD is blank. I found that callSpeed, callRPM and, callPower all cause this strange symbol.

The same callTPS command worked just fine in the previous version of the program. All of the data is good because the data is being recorded on the SD card and shows up in Excel, the LCD just doesn't want to display it for whatever reason.

/*  
 This program is used for an Arduino to request and retrieve
 data from an 07 Buell XB9SX Lightning ECM DDFI-2,
 EEPROM Version: BUEIB
 
 Currently the Arduino successfully sends a request code and
 receives all 107 bytes of Real-time data, and displays
 on the limited data on the LCD. Recent additions include air
 density, acceleration, power and torque calculations
 (untested). Datalogging capabilites have also been added
 (also untested).
 
 Created by Michael Blaylock
 */

// include the library code:
#include <LiquidCrystal.h>
#include <SoftwareSerial.h>
#include <SD.h>
#include <Wire.h>
#include "RTClib.h"

//new serial pins for ECM, 0 and 1 caused interferance from PC
#define rxPin 2
#define txPin 3

//defining constants in the power equation
#define Slugs 16.784  //mass of bike with 150lb rider
#define SpeedConvert 1.467  //mile/hour to feet/sec conversion
#define Crr 0.018  //coefficient of rolling resistance of tire
#define Gravity 32.174  //acceleration of gravity in English
#define Cd 0.382 //Coefficient of drag of the bike
#define Av 1.49 //Cross sectional area of bike in ft^2

#define SYNC_INTERVAL 5000
uint32_t syncTime = 0; //time of last sync()

RTC_DS1307 RTC;  //define the Real Time Clock object

// for the data logging shield, we use digital pin 10 for the SD cs line
const int chipSelect = 10;

//the logging file;
File logfile;

//print errors to Serial monitor
void error(char *str) {
  Serial.print("error: ");
  Serial.println(str);
  while(1);
}

// set up a new serial port for ECM while connected to PC
SoftwareSerial mySerial (rxPin, txPin);

// initialize the library with the numbers of the interface pins
//LiquidCrystal lcd(7, 8, 9, 10, 11, 12);
LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);
byte inArray[9]; //request code for real-time data
byte outArray[107]; //real-time data series from ECM
long unsigned TPS;
float ATemp;
float ADensity;
float LastSpeed;
float Speed;
long unsigned LastSpeedTimestamp;
long unsigned SpeedTimestamp;
unsigned RPM;
float Accel;
float Power;
float Torque1;
int IterationNumber = 0;
int ByteNumber;
int Processing = 0;

void setup(void){
  lcd.begin(16, 2);  // set up the LCD's number of columns and rows: 
  mySerial.begin(9600);  // baud rate for the ECM is 9600
  Serial.begin(9600);

  //initialize the SD card
  lcd.println("Initializing SD ");
  lcd.print("card...");
  Serial.print("Initializing SD card...");
  pinMode(10,OUTPUT);

  //see if the card is present and can be initialized
  if (!SD.begin(chipSelect)) {
    error("Card failed, or not present");
  }
  Serial.println("card initialized.");
  lcd.clear();
  lcd.println("...Card");
  lcd.print("initialized");

  //create a new file
  char filename[] = "LOGGER00.CSV";
  for (uint8_t i = 0; i < 100; i++) {
    filename[6] = i/10 + '0';
    filename[7] = i%10 + '0';
    if (! SD.exists(filename)) {
      // only open a new file if it doesn't exist
      logfile = SD.open(filename, FILE_WRITE); 
      break;  // leave the loop!
    }
  }

  if (!logfile) {
    error("couldn't create file");
  }

  lcd.clear();
  lcd.println("Logging to: ");
  lcd.print(filename);
  Serial.print("Logging to: ");
  Serial.println(filename);

  //connect to RTC
  Wire.begin();
  if (!RTC.begin()) {
    logfile.println("RTC failed");
    Serial.println("RTC failed");
  }

  //create header for the log file
  logfile.println("millis,Date Time,TPS,RPM,Power");
  logfile.flush();
  lcd.clear();

  ByteNumber = 0;
  inArray[0]=0x01; //SOH
  inArray[1]=0x00; //Emittend
  inArray[2]=0x42; //Recipient
  inArray[3]=0x02; //Data Size
  inArray[4]=0xFF; //EOH
  inArray[5]=0x02; //SOT
  inArray[6]=0x43; //Data 1 //0x56 = Get version, 0x43 = Get runttime data
  inArray[7]=0x03; //EOT
  inArray[8]=0xFD; //Checksum
  //mySerial.write(0x01 0x00 0x43 0x02 0xFF 0x02 0x43 0x03 0xFD); //unsure on correcy syntax

  requestData();
}

//Send data request to ECM
void requestData(void) {
  //lcd.setCursor(0,0);
  for (int i = 0; i<9; i+=1)
    mySerial.write(inArray[i]);
  //Do not place code here
}

//Display the Throttle Position Sensor
void callTPS(void){
  TPS = outArray[91] << 8 | outArray[90];
  lcd.setCursor(0,0); //right then down
  lcd.print("TPS");
  lcd.print(TPS); 
}

//Obtain Air Temp and Density
void callATemp(void){
  ATemp = (outArray[33] << 8 | outArray[32]) * 0.18 -40;
  ADensity = (39.1282 / (ATemp + 460));
}

//Obtain Speed and Acceleration
void callSpeed(void){
  LastSpeed = Speed;
  Speed = outArray[99];
  LastSpeedTimestamp = SpeedTimestamp;
  SpeedTimestamp = millis();
  Accel = (Speed - LastSpeed)*1000/(SpeedTimestamp-LastSpeedTimestamp);
  lcd.setCursor(9,1); //right then down
  lcd.print("Speed");
  lcd.print(Speed); 
}

//Obtain RPM
void callRPM(void){
  RPM = outArray[12] << 8 | outArray[11];
  lcd.setCursor(9,0); //right then down
  lcd.print("RPM");
  lcd.print(RPM); 
}

//Calculate Horsepower and Torque
void callPower(void){
  Power = (Slugs*(Accel*SpeedConvert+Crr*Gravity)+(0.5*ADensity*Cd*Av*pow(Speed*SpeedConvert,2)))*Speed*SpeedConvert;
  Torque1 = Power*5252/RPM;
  lcd.setCursor(0,1); //right then down
  lcd.print("Power");
  lcd.print(Power); 
}


void loop(void) {
  if (mySerial.available () > 0) {
    //fill the data array
    outArray[ByteNumber ++] = mySerial.read();
  } 

  if (ByteNumber > 106){  // process it
    Serial.println("Data Stream Read");
    ByteNumber = 0;  // ready for next time

    uint32_t m = millis();
    logfile.print(m);
    logfile.print(", ");
    DateTime now = RTC.now();
    logfile.print(now.year(), DEC);
    logfile.print(now.month(), DEC);
    logfile.print(now.day(), DEC);
    logfile.print("_");
    logfile.print(now.hour(), DEC);
    logfile.print(now.minute(), DEC);
    logfile.print(now.second(), DEC);
    logfile.print(", ");
    logfile.print(TPS, DEC);
    logfile.print(", ");
    logfile.print(RPM, DEC);
    logfile.print(", ");
    logfile.print(Power, DEC);
    logfile.println();

    callTPS();
    callATemp();
    callSpeed();
    callRPM();
    callPower();

    //Write to disk
    if ((millis() - syncTime) < SYNC_INTERVAL){
      logfile.flush();
      syncTime = millis();
      Serial.println("data saved");
    }

    requestData();  //restart data
    //Do not place code here
  }  // end if full
}  // end of loop

Do you guys see any problems in my code with displaying data on the screen? Thanks for the help!

What Arduino board are you using? And what version of the IDE?

I am using an Arduino Uno R3 and the IDE is Arduino 1.0.

Right. Well in that case:

LiquidCrystal lcd(A5, A4, A3, A2, A1, A0);

I2C uses A4 and A5 (for the DS1307 clock). So you can't exactly use the same pins for the LCD.

Oh, right. I completely forgot that it uses those. That makes sense why the screen was getting all screwy. I will swap those 2 back to the digital pins.

If I got an LCD screen that also used I2C, would it be plugged into A4 and A5 as well? My understanding of I2C is that it is meant for connecting multiple components without using more pins.

Yes an I2C screen would be plugged into A4 and A5.

Thanks for all the help so far. I got it working and recording data, displaying to the LCD and saving on the SD card.

Here is a quick video:

I have a few small issues. The first one is that the Arduino seems to randomly freeze while recording. The numbers on the screen freeze and no more data is recorded. I don't know if this is because it failed to receive a stream from the ECM and it just waits forever for the next one that isn't coming....or if I might be hitting the maximum RAM limit. How do I tell which one it might be?

The second issue is the speed of the program. When I was testing it to just show the data and not record or perform any big calculations, it was lightning fast. I added all this data logger stuff and a lot more functions now. I expected it to be slower, but not this slow. It seems to run at like 4 or 5Hz. Any ideas on how to speed this thing up? I suppose putting all of the logfile.print commands in a function maybe. I hadn't tried it because I was afraid it would cause problems, and didn't get time to experiment much.

I would post my code but it now exceeds the maximum length allowed in a message.
You can see my code on my project blog page here: Buell ECM to Arduino: Arduino Code R7 Datalogger Accel