sti robot project (robotmeter project)-see post #461 if you want to test a setup out! - Subaru Impreza WRX STI Forums: IWSTI.com
STI Forum
Join
STI Products
Start New Thread Create Account Advertise FAQ Members List Contact
Go Back   STI Forums > GD Series STi Discussion (2003/4-2007) > GD-General > GD-Interior > sti robot project (robotmeter project)-see post #461 if you want to test a setup out!
Welcome to IWSTI - The world's largest Subaru Impreza WRX STI forum!
Welcome to the IWSTI.com Subaru Impreza WRX STI forum.

You are currently viewing IWSTI.com as a guest, which limits your ability to access discussions, ask technical questions, and learn more about the Subaru Impreza WRX STi models. Join for free today and unlock full access to post topics, communicate privately with other members (PM), respond to polls, share content, and access many other special features. Join our community today!

If you have any problems with the registration process or your account login, please contact us.
* Registered users of the site do not see this welcome message.
View Poll Results: What should I work on next (choose multiples if you'd like)?
Lap timer 30 24.19%
Temp gauges (low temps: intake, intercooler, ambient, underhood, etc.) 61 49.19%
boost (w/peak, etc.) 56 45.16%
boost ref ic spray 34 27.42%
EGT/Oil temp - mess with off the shelf senders (egauges sells them by themselves) 46 37.10%
Something else 16 12.90%
Multiple Choice Poll. Voters: 124. You may not vote on this poll

Reply
 
Thread Tools
Old 02-26-07, 10:06 AM   #1
Advanced Mastery Level II
Feedback Score: 3 reviews
 
Fav Mod: a garage
My Subaru Parts for sale

Join Date: Sep 2005
Location: San Diego
sti robot is on a distinguished road
Default sti robot project (robotmeter project)-see post #461 if you want to test a setup out!

Project website and wiki: http://robotmeter.com/dokuwiki/

All details will be better organized in the wiki.

Project completion % 90:
|----------|----------|----------|----------|----------|----------|---------|-------->|__________|

[Disclaimer sort of thing]
Please understand that all code and info provided is on a experimental only basis. I do not guarantee any of my work as this is a personal project (at this time and subject to change) and in a developmental phase. I am not responsible for any damage to you or your personal property if you choose to use the code provided or follow my examples. As always, work within your skill level, ask for help when necessary, and keep your eyes on the road when driving.

[Consolidated info]
What it is: A kitchen sink digital gauge multi-gauge solution built on the open source arduino platform. It has a focus on in car display and car related sensors however, the code could be easily adapted for other applications (experimental purposes, weather monitoring, pet monitoring, personal health meter, RC car telemetry, robot telemetry, etc.). This is not a an OBD II reader, nor do I intend to hook it into the ECU. However, with this hardware and the proper knowledge it should be possible for a skilled person to tap into the ECU to get info like RPM, speed, etc.

What it does:
-Powers off of the car's 12V power supply.
-Logging mode-logs all parameters via usb to a computer (any os) in a comma delimited text format for easy excel, OO-calc, matlab, etc. consumption.
-Oil temperature
-Oil temperature warmup-starts up in oil temp mode. When the oil temp reaches a set point (ie the car is warmed up) the unit switches to the default mode (default mode is the accelerometer display)
-2 axis 2g accelerometer (I'm using a 1.2g but plan to switch) with a lateral bar graph and discrete display.
-2 x Misc temperature sensors-useful for cabin temp, ambient temp, and various underhood temps. Could also be setup for you to jump out of the car in between laps and test tire temps.
-lap timer with 2 laps/lines-this is persistent and will continue to run even if you switch modes. However, it has a 9 hour time limit based on a limit in the microcontroller used in the arduino.
-turbo (boost) pressure
-peak hold/reset for most sensors
-several types of displays (in code configurable for now). A two sensor display with peaks. A single sensor display with bar graph and peaks. A specialized accelerometer display. (A 4 sensor non-peak display is also a possibility, but has not been coded yet).
-temporary peak bar hold on the accelerometer (looks like a VU meter on a stereo system)
-Warnings-currently setup to flash the line of the sensor that has gone over a set point. In addition (though not currently configured) a warning light could go on or a buzzer could sound. This could be configured at multiple step levels (in code, and not written yet).
-boost referenced (or more generically, sensor referenced) Intercooler water spray. (Planned, not yet implemented).

An older demo video: http://randomcrap.us/otherjustin/modes_demo.mov

The code (v 0.3.0):
A good version/usable. All sensors are set up correctly. Global warn (in every mode it checks all the sensors periodically and warns when necessary) is currently turned off for most sensors (ie commented out). Piezo code is also commented out. Oil temp sensor code has not been checked...but should be close.

Code:
/* Copyright (c) 2008, Justin
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*     * Redistributions of source code must retain the above copyright
*       notice, this list of conditions and the following disclaimer.
*     * Redistributions in binary form must reproduce the above copyright
*       notice, this list of conditions and the following disclaimer in the
*       documentation and/or other materials provided with the distribution.
*     * Use of this software for commercial gain without written consent of 
*       above mentioned copyright holder is NOT permitted.  This includes, but 
*       is not limited to products which do not contain/or are not distributed 
*       with the software but are built with the purpose of using this software.
*
* THIS SOFTWARE IS PROVIDED BY Justin N ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <copyright holder> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */


//also a replacement for gauges
//set up for 2 display
//also set up for 1 and bar graph display

//multi mode selection via the "A" button
//"B" button clears peaks and operates the usb logging as well as the timer function
#include <SoftwareSerial.h> 
#define rxPin 4
#define txPin 5

SoftwareSerial LCDSerial =  SoftwareSerial(rxPin, txPin);
byte pinState = 0;

int logfilecount = 0;

int xval = 4;
int yval = 5;
int negpeak = 0;
int pospeak = 0;
int pospeakcount = 0;
int negpeakcount = 0;
int zerogy = 512;
int zerogx = 512;

unsigned long T1 = 0;
unsigned long T2 = 0;

int mode = 1; 
int buttonApin = 10;
int buttonBpin = 13;
int buttonBval = HIGH;

int sprayTriggerPin = 11;

int t1pin = 2;
int t2pin = 3;
int tempPin = 1;
int boostPin = 0;

int timer_state = 0;
long tempmillisT1 = 0;
long tempmillisT2 = 0;

boolean startuptempswitch = false;

//global peaks...so that you can switch modes and preserve peaks
long boost_peak = 0;
long temp_peak = 0;
long temp1_peak = 0;
long temp2_peak = 0;

  
void setup(){
  //delay(10000);
  //setup the accelerometer and screen
  Serial.begin(9600); 
  Serial.print("IPA"); //to vdip logger
  Serial.print(13, BYTE); //to vdip logger
  //delay(10000);
  pinMode(rxPin, INPUT);
  pinMode(txPin, OUTPUT);
  pinMode(sprayTriggerPin, OUTPUT);
  digitalWrite(sprayTriggerPin, LOW);
  LCDSerial.begin(9600);
  //put wait code to look and see if there is a
  //response from the VDIP1.  If there isn't try connecting again
  
  //read the root dir in the memstick to set the 
  //log file's name/number (its sequential)
  //Serial.print("DIR");
  //Serial.print(13, BYTE);
  //LCDSerial.print(0xFE, BYTE);   //command flag
   //LCDSerial.print(128, BYTE); 
  //while(Serial.available() > 0){
   //LCDSerial.print(Serial.read()); 
  //}
  
  //LCDSerial.print(0xFE, BYTE);   //command flag
   //LCDSerial.print(128, BYTE); 
  //LCDSerial.print("initialized");
  //read
  int tfilenum = 0;
  /*if(Serial.available() > 0){
    //look for "LOG"
    int input = Serial.read();
    Serial.print(input);
    if (input == 76){  //L
      input = Serial.read();
       if (input == 79){ //O
       input = Serial.read();
        if (input == 71){ //G
          //get the numers after "LOG"
          input = Serial.read();
          tfilenum = input - 48;
          input = Serial.read();
          while (input > 48 && input < 58){
            input = Serial.read();
            tfilenum = tfilenum * 10 + input - 48;
          }
        } 
      }
    }
  }*/
  
  //logfilecount = tfilenum + 1;
  Serial.print("OPW LOG555");
  Serial.print(13, BYTE);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
  //LCDSerial.print("file write");
  Serial.print("CFL LOG555");
  Serial.print(13,BYTE);
  
  //this next line for debug only
  //delay(10000);
    LCDSerial.print(0x7C, BYTE);  
    LCDSerial.print(150, BYTE); 
   //LCDSerial.print(0xFE, BYTE);   
   //LCDSerial.print(0x01, BYTE);
  //zero the accelerometer...but only for small tilts
  int tempreading = analogRead(yval);
  if ((tempreading < 600) && (tempreading > 400)){
    zerogy = tempreading;

  }
  else {
    zerogy = 512;
  }
  tempreading = analogRead(xval);
  if ((tempreading < 600) && (tempreading > 400)){
    zerogx = tempreading;
  }
  else {
    zerogx = 512;
  }
  //setup the buttons as inputs
  pinMode(buttonApin, INPUT);
  pinMode(buttonBpin, INPUT);
}

void loop (){
  //WHAT MODE
  if (digitalRead(buttonApin) == LOW){
    while (digitalRead(buttonApin)){
     //avoids flipping modes rapidly 
    }
     if (mode == 1){mode=2;}
     else if (mode == 2){mode=3;}
     else if (mode == 3){mode=4;}
     else if (mode == 4){mode=5;}
     else if (mode == 5){mode=6;}
     else if (mode == 6){mode=7;}
     else mode = 1;
  }
  //ACCELEROMETER
 if (mode == 2) {
    accelerometer();
 }
 //LAP TIMER 
 if (mode == 6){
   runTimer();
 } 
 if (mode == 1){
  temp_meter(); 
 }
 if (mode == 3){
  boost_meter(); 
 }
 if (mode == 4){
  temp_boost_meter(); 
 }
 if (mode == 5){
   two_temp_meter();
 }
 if (mode == 7){
   usb_logger();
 }
 
}

void test_all_meters(){
/* if ((analogRead(tempPin) > 512) && (mode != 1)){ //oil temp
   mode = 1;
   temp_meter();
 } 
 if ((analogRead(t1pin) > 512) && (mode != 6)){ //temp1
   mode = 6;
   two_temp_meter();
 }
 if ((analogRead(t2pin) > 512) && (mode != 6)){ //temp2
   mode = 6;
   two_temp_meter();
 }*/
 if (( (lookup_boost(analogRead(boostPin))) >  140) && (mode != 3)){ //boost
   mode = 3;
   boost_peak=lookup_boost(analogRead(boostPin));
   spray();
   boost_meter();
 }
 return;
}

//trigger something on pin x via the 
void spray(){
  digitalWrite(sprayTriggerPin, HIGH);
  delay(3000); //how long the spray lasts...spray will always last a little longer due to the built in timer in the car
  digitalWrite(sprayTriggerPin, LOW);
}

void accelerometer(){
    if (startuptempswitch == true){
     while (digitalRead(buttonApin) == LOW){}
    }
    test_all_meters();
    startuptempswitch = true;
    int accelx = ( getAccelerometerData (xval) );
    int accely = ( getAccelerometerData (yval) );
 
    pospeakcount++;
    negpeakcount++;
  
    peak(accely);
    LCDSerial.print(0xFE, BYTE);   //command flag
    LCDSerial.print(128, BYTE); 
    delay(60);
    printBarGraph(accely);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
    delay(60);
    LCDSerial.print("x:");
    printAccelerometerReadout(accelx);
    LCDSerial.print(" y: ");
    printAccelerometerReadout(accely);
}

void runTimer(){
  while (digitalRead(buttonApin) == LOW){
   }
  test_all_meters();
  if (timer_state == 0){
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
    LCDSerial.print(0xFE, BYTE);   //command flag
    LCDSerial.print(128, BYTE);  
    delay(20);
    LCDSerial.print("T1: 00:00:00.00");
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
    LCDSerial.print("T2: 00:00:00.00"); 
    T1 = 0;
    T2 = 0;
    while (digitalRead(buttonBpin) == HIGH){
     //wait for start
     if (digitalRead(buttonApin) == LOW){
       return;
     } 
    }
    while (digitalRead(buttonBpin) == LOW){
      //we don't want to skip the start if you hold the button too long
     //timing actually happens on button release 
     timer_state = 1;
     tempmillisT1 = millis();
    }
  }
  if (timer_state == 1){
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
    LCDSerial.print(0xFE, BYTE);   
    LCDSerial.print(128, BYTE); 
    while (digitalRead(buttonBpin) == HIGH){
      test_all_meters();
      //timing
      if (digitalRead(buttonApin) == LOW){
        return;
      }
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
      T1 = millis() - tempmillisT1;
      //printing to the screen
      print_T1();
      //a short pause
      delay(50);
    }
    while (digitalRead(buttonBpin) == LOW){
      //stop T1 timing
      test_all_meters();
      timer_state = 2;
    }
  }
  if (timer_state == 2){ //timed shown on T1 and zeros on T2 waiting to start T2
    //display T1 if we cycle through modes and reach this
    //---
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
      //printing to the screen
      print_T1();
      //a short pause
      delay(50);
      
      //display T2 as zeros
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
      LCDSerial.print("T2: 00:00:00.00"); 
    //---
    
    while (digitalRead(buttonBpin) == HIGH){
     //wait for timing T2
     if (digitalRead(buttonApin) == LOW){
      return;
     } 
     test_all_meters();
    }
    while (digitalRead(buttonBpin) == LOW){
     //clicking to start T2 
      timer_state = 3;
      tempmillisT2 = millis();
    }
  }
  if (timer_state == 3){ //T1 is displayed and T2 is running
    //display T1 if this mode is reache durring mode switching
    //--
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
      //printing to the screen
      print_T1();
      
    //--
    
    delay(10);

    while (digitalRead(buttonBpin) == HIGH){
      test_all_meters();
      if (digitalRead(buttonApin) == LOW){
        return;
       }
      //T2 timing 
      T2 = millis() - tempmillisT2;
      //printing to the screen
      print_T2();
      //a short pause
      delay(50);
    }
    while (digitalRead(buttonBpin) == LOW){
      //click to stop
      timer_state = 4;
    }
  }
  if (timer_state == 4){
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
    while (digitalRead(buttonBpin) == HIGH){ 
      //what to do if we've reached this direct thru mode switching
      //---
        //printing to the screen
        print_T1();
        //a short pause
        delay(50);
      
        //display T2
        print_T2();
        //a short pause
        delay(50);
       
    //---
      test_all_meters();
      if (digitalRead(buttonApin) == LOW){
        return;
      }
    }
    while (digitalRead(buttonBpin) == LOW){}
    //on release return to main loop
    timer_state = 0;
  }
  return;
}

void print_T1 (){
     //printing to the screen
     LCDSerial.print(0xFE, BYTE);   
     LCDSerial.print(128, BYTE); 
     unsigned long T1millis = T1%1000/10;
     unsigned long T1seconds = T1%60000/1000;
     unsigned long T1minutes = T1%3600000/60000;
     unsigned long T1hours = T1/3600000;
     LCDSerial.print("T1: ");
     printInTens(T1hours);
     LCDSerial.print(":");
     printInTens(T1minutes);
     LCDSerial.print(":");
     printInTens(T1seconds);
     LCDSerial.print(".");
     printInTens(T1millis);
}

void print_T2 (){
     //printing to the screen
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
     unsigned long T2millis = T2%1000/10;
     unsigned long T2seconds = T2%60000/1000;
     unsigned long T2minutes = T2%3600000/60000;
     unsigned long T2hours = T2/3600000;
     LCDSerial.print("T2: ");
     printInTens(T2hours);
     LCDSerial.print(":");
     printInTens(T2minutes);
     LCDSerial.print(":");
     printInTens(T2seconds);
     LCDSerial.print(".");
     printInTens(T2millis);
}

void boost_meter(){ 
 while (digitalRead(buttonApin) == LOW){}
   meter_splash("Boost", "     Meter");
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(128, BYTE); 
   LCDSerial.print("Boost Meter");
 delay(1000);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
 long reading = 0;
 while (digitalRead(buttonApin) == HIGH){
  test_all_meters();
  if (digitalRead(buttonBpin) == LOW) {
    boost_peak = 0;
  }  
  //non sensor code
  //reading = reading + 1;
  //real reading code
  //0 psi = 12 Vcount;
  reading = lookup_boost( long(analogRead(boostPin)) );
  boost_peak = max (reading, boost_peak); 
  generic_bar_display ("psi", 170, reading, boost_peak, 145);
  delay(50);    
 }
 return;
}

void temp_meter(){ 
 if (startuptempswitch == false){
  while (digitalRead(buttonApin) == LOW){}
 }
   meter_splash("Oil Temp", "     Meter");
 long reading = 0;
 while (digitalRead(buttonApin) == HIGH){
  test_all_meters(); 
  if (digitalRead(buttonBpin) == LOW) {
    temp_peak = 0;
  }
  //reading = reading + 1;
  reading = lookup_oil_temp(analogRead(tempPin));

  if ((startuptempswitch == false) && (reading > 145)){
    mode = 2;
    return;
  }
  temp_peak = max (temp_peak, reading);
  generic_bar_display ("oil", 3500, reading, temp_peak, 2600);
  delay(50);    
 }
 return;
}

void temp_boost_meter(){ 
 while (digitalRead(buttonApin) == LOW){}
  meter_splash("Temp/Boost Meter","");
 long reading1 = 0;
 long reading2 = 0;
 while (digitalRead(buttonApin) == HIGH){
  test_all_meters();
  if (digitalRead(buttonBpin) == LOW) {
    temp_peak = 0;
    boost_peak = 0;
  }
  //reading1 = random(100,350);
  reading1 = lookup_oil_temp(analogRead(tempPin));
  reading2 = lookup_boost( long(analogRead(boostPin)) );
  temp_peak = max (temp_peak, reading1);
  boost_peak = max (boost_peak, reading2); 
  generic_dual_display ("tmp", 3500, reading1, temp_peak, 2000, "psi", 210, reading2, boost_peak, 140);
  delay(50);    
 }
 return;
}

void two_temp_meter(){ 
 while (digitalRead(buttonApin) == LOW){}
   meter_splash("2 Temp Meter", "");
 long reading1 = 0;
 long reading2 = 0;
 while (digitalRead(buttonApin) == HIGH){
  test_all_meters();
  if (digitalRead(buttonBpin) == LOW) {
    temp1_peak = 0;
    temp2_peak = 0;
  }
  reading2 = lookup_temp((long)analogRead(t2pin));
  reading1 = lookup_temp((long)analogRead(t1pin));
  //reading1 = analogRead(t1pin);
  temp1_peak = max (temp1_peak, reading1);
  temp2_peak = max (temp2_peak, reading2); 
  generic_dual_display ("F 1", 1024, reading1, temp1_peak, 9999, "F 2", 3500, reading2, temp2_peak, 1000);
  delay(20);    
 }
 return;
}

void printInTens(int Tvar){
    if (Tvar < 10){
      LCDSerial.print("0");
      LCDSerial.print(Tvar);
    }
    else LCDSerial.print(Tvar);
    return;
}

void printBarGraph(int y) { 
  //clear the 1st 8 spacesb
  if ( y >= 0){
    LCDSerial.print("        ");  
    for(int i=1; i <= y/16; i++){
       LCDSerial.print(0xFF, BYTE);
    }
    //fill the rest with spacesloo
    for(int i=1; i <= (8-y/16); i++){ 
      LCDSerial.print(" "); 
    }
  }
  if (y < 0) {
    //1 - print spaces at the beginning
    for (int i=1; i <= (8-abs(y/16)); i++){
      LCDSerial.print(" "); 
    }
    //2 - print blocks till the middle
    for (int i=1; i <= abs(y/16); i++){
      LCDSerial.print(0xFF, BYTE);
    }
    //3 - print spaces till the end
    for (int i=1; i<=8; i++){
      LCDSerial.print(" ");
    }
  }
 
 //print the peaks if there are any
 //negative
 LCDSerial.print(0xFE, BYTE);  
 LCDSerial.print(128, BYTE);
 if (negpeak/16 < 0){
   LCDSerial.print(0xFE, BYTE);
   int npos = 128 + (8 - abs(negpeak/16));
   LCDSerial.print(npos, BYTE);
   LCDSerial.print(0xFF, BYTE);
 }
 
 //positive
 if (pospeak/16 > 0){
   LCDSerial.print(0xFE, BYTE);
   int ppos = 128 + (8 + (pospeak/16));
   LCDSerial.print(ppos, BYTE);
   LCDSerial.print(0xFF, BYTE);
 }
  
}

long lookup_boost(long boost){
  //boost = ( (boost-106000) / 259000 );
  // boost = ( (( boost * 398) / 1000) + 2); //2 is the y intercept
  //398 changed to 378 for slope...because slope was too steep
  boost = ( (( boost * 378) / 1000) - 4); ///10; //get rid of the divide by ten when adding decimals on display
  return boost;
}

long lookup_oil_temp(long tval){
  tval = tval * 1000; //added an extra 0
  if (tval <= 11500){
    return (9999); 
  }
  if (tval >= 68100){
    return (0);
  }
  if ((tval <= 68000)&&(tval > 39600)){
    return (long)(((tval-134266)*10)/(-473));
  }
  if ((tval <= 39600)&&(tval > 28200)){
    return (long)(((tval-115600)*10)/(-380));
  }
  if ((tval <= 28200)&&(tval > 19700)){
    return (long)(((tval-93366)*10)/(-283));
  }  
  if ((tval <= 19700)&&(tval > 11600)){
    return (long)(((tval-54800)*10)/(-135));
  }  
}

long lookup_temp(long tval){
  tval = tval * 100;
  //tval = (long)(tval - (long)117588);
  //return tval;
  if (tval < 8900){
   return (9999); 
  }
  if (tval > 96000){
    return (0);
  }
  if ((tval <= 96000)&&(tval > 93221)){
    return (((tval-101577)*10)/(-172));
  }
  if ((tval <= 93221)&&(tval > 89610)){
    return (((tval-104201)*10)/(-226));
  }
  if ((tval <= 89610)&&(tval > 85125)){
    return (((tval-107738)*10)/(-280));
  }
  if ((tval <= 85125)&&(tval > 79139)){
    return (((tval-112264)*10)/(-335));
  }

  if ((tval <= 79139)&&(tval > 70799)){
    return (((tval-117588)*10)/(-388));
  }
  if ((tval <= 70799)&&(tval > 62470)){
    return (((tval-121441)*10)/(-421));
  }
  if ((tval <= 62470)&&(tval > 53230)){
    return (((tval-122367)*10)/(-428));
  }
  if ((tval <= 53230)&&(tval > 43707)){
    return (((tval-118651)*10)/(-405));
  }
  if ((tval <= 43707)&&(tval > 36471)){
    return (((tval-111349)*10)/(-366));
  }
  if ((tval <= 36471)&&(tval > 30685)){
    return (((tval-102232)*10)/(-321));
  }
  if ((tval <= 30685)&&(tval > 24800)){
    return (((tval-9078)*10)/(-270));
  }
  if ((tval <= 24800)&&(tval > 20000)){
    return (((tval-78575)*10)/(-220));
  }
  if ((tval <= 20000)&&(tval > 15851)){
    return (((tval-66507)*10)/(-175));
  }
  if ((tval <= 15851)&&(tval > 12380)){
    return (((tval-55300)*10)/(-137));
  }
  if ((tval <= 12380)&&(tval > 9085)){
    return (((tval-41752)*10)/(-94));
  }
}

void printAccelerometerReadout(int reading){
  if (reading >= 0 ) {
    LCDSerial.print("+");
  }
  if (reading < 0) {
    LCDSerial.print("-");
  }
  
  int afterdecimal = reading % 100;
  LCDSerial.print(abs(reading/100));
  if ( (afterdecimal > 9) || (afterdecimal < -9) ){
    LCDSerial.print(".");
  }
  else {
    LCDSerial.print(".0");
  }
  LCDSerial.print(abs(afterdecimal));
}

int getAccelerometerData (int axis){
  int zerog = 512;
  if (axis == 5){
   zerog = zerogy;
  }
  if (axis == 3){
   zerog = zerogx; 
  }
    
  int rc = analogRead(axis);
  int top =( (zerog - rc) ) ; 
  float frtrn = (((float)top/(float)158)*100);  //158Vint jumps are 1g
  int rtrn = (int)frtrn;
  return rtrn;
}

void peak(int val){
  
  if ( (val > 0) && (val > pospeak) ){       //pos peak compare and set
      pospeak = val;
      pospeakcount = 0;
  }
 
  if ( (val < 0) && (val < negpeak) ) {     //neg peak compare and set 
       negpeak = val;
       negpeakcount = 0;
  }
  
  else {                                    //peak mark expires after x time
    if (pospeakcount >= 20){
      pospeakcount = 0;
      pospeak = 0;
    }
    if (negpeakcount >= 20){
      negpeakcount = 0;
      negpeak = 0;
    }
  }
}

int numberofdigits(long value){
 
 int digits = 1;
 while (value/10 > 0){
  value = value/10;
  digits++; 
 }
 
 if (value < 0){digits ++;}
 return digits; 
}

//positive only value 0 to X
//only 4 char titles (should be changed soon)
//1234567890123456
//TMP 134.5/ 314.5
//psi 14.5 /  14.5 
//oil 1.0  /   1.4
//oil 0.3  /   0.4
void generic_bar_display(char title[ ], long high, long cur_value, long peak, long warn){
 LCDSerial.print(0xFE, BYTE);  
 LCDSerial.print(128, BYTE);
  LCDSerial.print(title);
  LCDSerial.print(" ");
  LCDSerial.print(cur_value/10);
  LCDSerial.print(".");
  LCDSerial.print(cur_value%10);
  int ndigits = numberofdigits(cur_value) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 5 - ndigits; i++) {
   LCDSerial.print(" "); 
  }
  LCDSerial.print("/");
  ndigits = numberofdigits(peak) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 6 - ndigits; i++){
   LCDSerial.print(" "); 
  }
  LCDSerial.print(peak/10);
  LCDSerial.print(".");
  LCDSerial.print(peak%10);
  if (cur_value > warn){ //blink if warning threshold is met
    warn_flash();
  }
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
  unsigned long abar = high/16;
  unsigned long n_bars = cur_value/abar;
  if (cur_value <= 0){n_bars=0;}
  for(int i=1; i< n_bars; i++){ 
     LCDSerial.print(0xFF, BYTE);
  }
  for (int i=1; i < (16 - n_bars); i++){
     LCDSerial.print(" "); 
  }
  delay(60);
}

//use only 4 char titles (should be changed soon)
void generic_dual_display (char title1[ ], long high1, long cur_value1, long peak1, long warn1, char title2[ ], long high2, long cur_value2, long peak2, long warn2){
 LCDSerial.print(0xFE, BYTE);  
 LCDSerial.print(128, BYTE);
  LCDSerial.print(title1);
  LCDSerial.print(" ");
  LCDSerial.print(cur_value1/10);
  LCDSerial.print(".");
  LCDSerial.print(cur_value1%10);
  int ndigits = numberofdigits(cur_value1) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 5 - ndigits; i++) {
   LCDSerial.print(" "); 
  }
  LCDSerial.print("/");
  ndigits = numberofdigits(peak1) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 6 - ndigits; i++){
   LCDSerial.print(" "); 
  }
  LCDSerial.print(peak1/10);
  LCDSerial.print(".");
  LCDSerial.print(peak1%10);
  if (cur_value1 > warn1){ //blink if warning threshold is met
    warn_flash();
  }
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
  LCDSerial.print(title2);
  LCDSerial.print(" ");
  LCDSerial.print(cur_value2/10);
  LCDSerial.print(".");
  LCDSerial.print(cur_value2%10);
  ndigits = numberofdigits(cur_value2) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 5 - ndigits; i++) {
   LCDSerial.print(" "); 
  }
  LCDSerial.print("/");
  ndigits = numberofdigits(peak2) + 1;
  if (ndigits <= 2){ ndigits = ndigits + 1;}
  for (int i = 0; i < 6 - ndigits; i++){
   LCDSerial.print(" "); 
  }
  LCDSerial.print(peak2/10);
  LCDSerial.print(".");
  LCDSerial.print(peak2%10);
  if (cur_value2 > warn2){ //blink if warning threshold is met
     warn_flash();
  }
  delay(60);
}

//quad display -- mus use 4 char (incl ":") for each title...ex "PSI:", "TEMP", "POOP", " ETC"
//void generic_quad_display(char title1[], unsigned long reading1, unsigned long warn1, char title2[], unsigned long reading2, unsigned long warn2, char title3[], unsigned long reading3, unsigned long warn3, char title4[], unsigned long reading4, unsigned long warn4){
 //LCDSerial.print(0xFE, BYTE);  
 //LCDSerial.print(128, BYTE);
//  LCDSerial.print(title1);
  
//}

//changed from the regular v4 to log to a serial logging device not
//to usb on a laptop

void usb_logger(){
 while (digitalRead(buttonApin) == LOW){}
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
   LCDSerial.print(0xFE, BYTE);  
   LCDSerial.print(128, BYTE);
   LCDSerial.print("USB Logging");
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  
   LCDSerial.print("Press B"); 
 while (digitalRead(buttonBpin) == HIGH){
   if (digitalRead(buttonApin)==LOW){
     return;
   }
 }
 delay(500);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE);
 LCDSerial.print("Logging");   //command flag
 //LCDSerial.print(0x08, BYTE);   //turn off visual display
 //LCDSerial.print("Data logger: \n");
 //open a new file based on a millis timestamp, give it a header and start writting
 Serial.print("OPW log");
 Serial.print(logfilecount);
 Serial.print(".txt");
 Serial.print(13, BYTE);
 Serial.print("WRF ");
 Serial.print(42);
 Serial.print("T1, T2, Oil Temp, Boost, x accel, y accel\n"); 
 Serial.print(13, BYTE);
 
 while (digitalRead(buttonBpin) == LOW){}
 while ( (digitalRead(buttonApin) == HIGH) && (digitalRead(buttonBpin) == HIGH) ){
   //logging output
   Serial.print("WRF ");

   long t1 = ( (lookup_temp(analogRead(t1pin))) );
   long t2 = ( (lookup_temp(analogRead(t2pin))) );
   long oil = ( lookup_oil_temp(analogRead(tempPin))); 
   long press =  lookup_boost(analogRead(boostPin));
   long ax = getAccelerometerData (xval);
   long ay = getAccelerometerData (yval);
   
   //calc the number of characters
   int linelen = 5 + numberofdigits(t1) + numberofdigits(t2) + numberofdigits(oil) + numberofdigits(press) + numberofdigits(ax) + numberofdigits(ay);
   //print the number of characters for this line
   Serial.print(linelen);
   Serial.print(13, BYTE);
   
   Serial.print(t1);
   Serial.print(",");
   //get T2 and convert
   //LCDSerial.print( lookup_temp(analogRead(t2pin)) );
   Serial.print(t2);
   Serial.print(",");
   //get oil temp and convert
   //LCDSerial.print( analogRead(tempPin) );
   Serial.print(oil);
   Serial.print(",");
   //get boost and convert
   Serial.print(press);
   //LCDSerial.print("###");
   Serial.print(",");
   //get x accel
   Serial.print(ax);
   Serial.print(",");
   //get y accel
   Serial.print(ay);
   //Serial.print("\n");
   
   Serial.print(13, BYTE);
 }
 while ( (digitalRead(buttonApin) == LOW) && (digitalRead(buttonBpin) == LOW) ){}
 //close the file
 Serial.print("CLF log%"); 
 Serial.print(logfilecount);
 Serial.print(".txt");
 Serial.print(13, BYTE);
 logfilecount++;
 //LCDSerial.print(0xFE, BYTE);   //command flag
 //LCDSerial.print(0x0C, BYTE);   //turn on visual display
 return;
}

void warn_flash(){
  Serial.print(0x7C, BYTE);  
  Serial.print(128, BYTE);  //backlight off
  delay(300);
  Serial.print(0x7C, BYTE);  
  Serial.print(157, BYTE);  //backlight on
  delay(300);
}

void meter_splash(char line1[], char line2[]){
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(0x01, BYTE); //clear
   LCDSerial.print(0xFE, BYTE);  
   LCDSerial.print(128, BYTE); //select line 1
   LCDSerial.print(line1);
   LCDSerial.print(0xFE, BYTE);   
   LCDSerial.print(192, BYTE);  //select line 2
   LCDSerial.print(line2); 
   delay(1000);                  //wait
   LCDSerial.print(0xFE, BYTE);   //clear
   LCDSerial.print(0x01, BYTE);
}
Other useful code:
www.randomcrap.us/otherjustin/meter_independent_lines.pde
The start of a version of the interface with independent lines. As in, you can change what one line displays independent of the others. I stopped coding on this because I didn't like how much you had to work to get the display to look exactly like you want while trying to drive a car at the same time (dangerous). But, if you want to work on this version of the code feel free.

www.randomcrap.us/otherjustin/serial_lcd_spash_set.pde
A sketch that can be used to set the splash screen on the lcd. Change the text on the appropriate line. Flash to the board...let run for a sec and you're set.

ERRORS THAT NEED FIXING: Spacing is fixed and so is the boost formula.

Component list:
Parts were sourced from Sparkfun, Digikey, egauges, radioshack (use radioshack only for convenience as parts are cheaper at digikey, newark, sparkfun, etc.), and directly from some manufacturers as samples.
-Arduino (Arduino - HomePage)-I'm using the standard USB version as it allows me to easily log all sensor parameters to a laptop.
-Sparkfun serial lcd (SparkFun Electronics)
-accelerometer (using a sparkfun breakout board...code was written for this one: SparkFun Electronics but will probably switch to this one: SparkFun Electronics)
-Oil temperature sender is a ISSPRO sender (part R8958). They were nice enough to send me their RT curve for this specific sender. All I had to do was call them. In addition I was surprised to get RT curve points from autometer, cyberdyne, and dakota digital. I ended up using the ISSPRO sender because it was the only one that fit my galley plug without an adapter.
-Temperature sensors: 252FG1K from ussensors (U.S. Sensor Thermistor, Manufacturer of NTC thermistors and RTD and thermistor temperature sensors), but you could use whatever thermistor you wanted. The only work involved would be mapping out the RT curve. I plan to insulate these with fiberglass sleeves much like the insulation on an EGT probe.
-Turbo pressure sensor: MPX4250GP from freescale (freescale is very nice in that they provide you with free samples of some of their products. Very good for a prototype. Please don't abuse their sample system.) You will also need tubing, a pilled t-fitting, and a some zip ties if you don't already have them.
-A lot of 18 and 22 gauge wire. I believe that the oil temp sensor requires 18 or 16 gauge wire (I can't recall off the top of my head).
-A piezo or a warning led...I haven't installed this yet but it should be as easy as wiring up an LED to blink. Any one that'll drive off of the 5V the arduino supplies will work.
-A relay and supporting circuitry for the boost referenced IC spray is on its way (watch this space!)
-buttons-any normally open (NO) SPST momentary button will work. I used what they had at radioshack and i'm not entirely pleased with how they held up. For now they work, but I'd suggest getting something better. I may, later switch to conductive touch sensor button sort of thing or "harvest" buttons from an older telephone.
-A 12V voltage regulator-this was an important missing component for a while. After some hard driving the original prototype would stop working and refuse to boot. For the longest time I thought it was a heat issue. Turns out it was a voltage issue and the car was actually providing 14.5V or more at times. This caused the arduino to start flipping bits on the microcontroller. The voltage regulator prevents this.
-An inline fuse was used for safely powering the arduino off the car's battery (I can't recall the specifics off the top of my head)
-A spare USB cable...to leave in the car
-2.5mm power plug to easily put the arduino in and out of the car.
-I used the standard clock location and some creative dremel tool work + a non-flammable glue to hold the display. You may wish to get an enclosure for this. I recommend hunting around for free samples (I personally enjoy the ones I got from PacTec and OKW. Pictures of these are in the thread)
-male header pins-attach these to the signal wires coming off of your sensors and they make swapping components out easy.
-female header pins and small board can be used to make a simple power and ground extender (the arduino does not have enough power and ground pins for every sensor)
-470 Ohm resistors to be used with the above listed thermistors in a voltage divider configuration (Voltage divider - Wikipedia, the free encyclopedia)
-a 220 Ohm resistor to be used in a voltage divider configuration with the oil temperature sender (I'm 90% positive it is a 220 Ohm but will double check).
-a 10k Ohm resistor to fix a bug with the arduino not sending serial signals to the lcd when not USB powered. (This plugs from gnd to RX).

Circuit diagram (using eaglecad http://www.cadsoftusa.com/):


Useful charts and stuff:
RT curve straight from ISSPRO

Graph showing use of multiple fit lines for complex thermistor RT curve


BTW I'm currently looking for a job and would love something related to this project.

A word on licensing, money, etc:
-I'm not a vendor on this site and the more and more I look at it I may never become a vendor on this site. This means, you cannot purchase things or services from me via this website and I cannot advertise things or services on this website.
-Their will be an open source license for this software. It will probably be a GPL license or some derivative. I have used adaptations of example code provided in the arduino forum and general knowledge base to produce this code. The code does not contain any proprietary information. To the best of my knowledge the RT curves for the theremistors are not proprietary knowledge and were given to me freely by the manufacturers.
-To the best of my knowledge I have not infringed on any copyrights, patents, etc. If you believe their is a problem please contact me so we can rectify the situation. However, I believe that what I have produced is a joining of several "public knowledge" ideas into one device. These ideas include the use of sensors with a digital display, logging data to a computer via USB, putting multiple sensors on one device, flashing warning text, etc.

Pictars and more demos:



and a better demo: TinyPic - Share The Experience!

[The Following is the original first post]
I've finally decided on the electronics project I'm going to start. Just wondering if anyone else would be interested/should I look into getting a vendor account.

I'll be building a digital accelerometer display to go in the place of the clock. When you turn on the car it'll show a custom welcome message and then it'll have two lines of display. The top will be a meter/analog style output and the bottom will have an instant and a max g force reading.

When all is said and done it'll probably be fairly easy to change the custom welcome message via usb and it'll be able to draw power from 12V (with a fuse of course). It should also be backlit and come in several colors.

I'll be using open source software/hardware (arduino, etc.) so if I do become a vendor you'll only be paying for assembly, support, and shipping.

All comments welcome.

(basically I watered down what I wanted to make from this:
track data logger - IWSTI.com: Subaru WRX STI Forums)

Sort of like this idea from a while back (Clock replacement data display / IC Spray controller - ScoobyMods)

I think I'm going to go with this LCD: SparkFun Electronics or maybe this one SparkFun Electronics

__________________
now in a 2013 DGM BRZ (04 sti -> NA miata -> e36 m3 -> brz) I'm baaaaack.

Last edited by sti robot; 10-22-08 at 05:07 AM.
sti robot is offline   Reply With Quote
Old 02-26-07, 11:29 AM   #2
Advanced Mastery Level I
Feedback Score: 3 reviews
 
Car: 07 SWP STi
Fav Mod: Perrin Exhaust
My Subaru Parts for sale

Join Date: Apr 2006
Location: Denver
Dragicon is on a distinguished road
Default

i think it would be cool for a while, but personally i think after a week or two i would want the clock back... any idea how much road noise from the bumps will transfer into the accelerometer?
Dragicon is offline   Reply With Quote
Old 02-26-07, 12:05 PM   #3
Advanced Mastery Level II
Feedback Score: 3 reviews
 
Fav Mod: a garage
My Subaru Parts for sale

Join Date: Sep 2005
Location: San Diego
sti robot is on a distinguished road
Default

No Idea about the road noise. I haven't even ordered parts yet
__________________
now in a 2013 DGM BRZ (04 sti -> NA miata -> e36 m3 -> brz) I'm baaaaack.
sti robot is offline   Reply With Quote
Old 02-26-07, 12:20 PM   #4
resigned
Feedback Score: 9 reviews
 
My Subaru Parts for sale

Join Date: Apr 2006
lackskill is on a distinguished road
Default

I like my clock..
lackskill is offline   Reply With Quote
Old 02-26-07, 12:57 PM   #5
Advanced Mastery Level II
Feedback Score: 3 reviews
 
Fav Mod: a garage
My Subaru Parts for sale

Join Date: Sep 2005
Location: San Diego
sti robot is on a distinguished road
Default

What would want it to display instead? Oh and you wouldn't have to put it where the clock is.
__________________
now in a 2013 DGM BRZ (04 sti -> NA miata -> e36 m3 -> brz) I'm baaaaack.
sti robot is offline   Reply With Quote
Old 03-04-07, 10:00 AM   #6
Contributor
Feedback Score: 1 reviews
 
My Threads
Posts: 73
My Subaru Parts for sale

Join Date: Oct 2006
Location: va beach
15secwrx is on a distinguished road
Send a message via AIM to 15secwrx
Default

if the screen can have the same red led as the interior gauge lighting I think that would be a plus. and depending on price and final look i might be interested.
15secwrx is offline   Reply With Quote
Old 03-06-07, 09:16 AM   #7
Developing Advanced Mastery
Feedback Score: 0 reviews
 
Car: 06 Corvette (Z51)
My Threads
Posts: 964
My Subaru Parts for sale

Join Date: Mar 2004
Location: Haymarket VA
Meridock is an unknown quantity at this point
Send a message via AIM to Meridock
Default

This would be a neat gadget if executed well. Keep me in the loop - I would like it in a different place (ashtray, DIN pocket)


Make mine red please.
__________________
Meridock is offline   Reply With Quote
Old 03-06-07, 10:53 AM   #8
Advanced Contributor Level 4
Feedback Score: 0 reviews
 
Car: 2015 red STI
My Threads
Posts: 473
My Subaru Parts for sale

Join Date: Nov 2005
Location: canada
the ambush is on a distinguished road
Default

i personnally think a precise/adjustable speedometer would be more useful.
as for accelerometer, i have a g-tech
__________________
2015 Red STI (Still stock)
2013 Outback (wife's)

Fisher RC4 Worldcup SL
Rocky Mountain Element Team Scandium

previous cars
-2011 Audi B8-S4
-2009 White Pearl STI stg2
-2006 WRB STI stg2:13.25 @ 104
-2004 red svt cobra : 100% stock 12.72 @ 114
the ambush is offline   Reply With Quote
Old 03-06-07, 08:20 PM   #9
Becoming A Master Contributor
Feedback Score: 1 reviews
 
Car: 04 Porsche GT3 - Red
Fav Mod: HPDE
My Threads
Posts: 615
My Subaru Parts for sale

Join Date: Dec 2004
Location: Long Island, NY
ace996 is an unknown quantity at this point
Default

You're on to something here, but think big picture and what is needed. Research the PSI3 meter...that's what we need, but with a larger display. Get one of those larger LCD displays, and allow 6 different readouts, or 3 bar gauges, and you'd make a mint.
I'm looking at dataloggers, gauges, laptimers and my head is spinning.

A larger screen that fits in the clock-pod, like a 3 gauge cluster, that can replace several gauges AND have accelerometers would be the deal.

Either way, good job for trying something new.

Be good,
TomK
__________________
"Arcadian, I've fought countless times, yet I've never met an adversary who could offer me what we Spartans call "A Beautiful Death." I can only hope, with all the world's warriors gathered against us, there might be one down there who's up to the task."
Μολὼν λαβέ!!
ace996 is offline   Reply With Quote
Old 03-07-07, 04:31 AM   #10
Master Contributor Level 1
Feedback Score: 2 reviews
 
Car: 04 PSM STi
My Threads
Posts: 709
My Subaru Parts for sale

Join Date: May 2003
Location: Chester Springs, PA
wi77iam is an unknown quantity at this point
Default

For the work and expense, it's probably just as easy to install a car PC, which will do all that you want and a whole lot more. You can have GPS for speed and grab ecu parameters displayed on a virtual dashboard using a program like ecuEdit. I added a Phidgets accelerometer to provide a view of g-forces.
wi77iam is offline   Reply With Quote
Reply

Thread Tools

Posting Rules
You may post new threads
You may post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are Off
Pingbacks are Off
Refbacks are Off



New To Site? Need Help? More

All times are GMT -8. The time now is 10:38 PM.


Powered by vBulletin
Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
Designed & Powered by Domain Architect
Privacy Policy