G meter coding help

Post here about your Arduino projects, get help - for Adafruit customers!

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
bchouston
 
Posts: 2
Joined: Sat Oct 29, 2011 12:36 pm

G meter coding help

Post by bchouston »

I am working on a simple G meter to be installed in 5 dummy LED slots in the gauge cluster of my car. I have taught myself the little bit of coding I have used. I currently have 5 LED that light from right to left as the car turns left and left to right as the car turn right. The thing I would like to add is to have the highest LED reached during a turn to stay on for about 1 second, but I have no clue how to get it to. For instance if you are taking a left turn and get the 3rd LED to light up I want it to stay lit for a second or two so you can see it after you finish the turn, so you can watch the road instead of your dash while turning. Any help or pointers would be greatly appreciated!

I am using the arduino UNO with the ADXL335 accelerometer with 3.3v as my ADC reff.
Here is a short vid of it in action: http://www.youtube.com/watch?v=xcIpC4FiJXY
Here is the coding I have so far (sorry if it is sloppy, I'm still trying to learn) :

Code: Select all

// Lateral 5 LED G meter using MMA7260 accelerometer 3.3v ADC Reff
// Intervals of .2g from -1 to 1g
//=================================================================


// Identifying my pins
const unsigned int X_AXIS_PIN = 2;
const unsigned int Y_AXIS_PIN = 1;
const unsigned int Z_AXIS_PIN = 0;
const unsigned int NUM_AXES = 3;
const unsigned int PINS[NUM_AXES] = {
X_AXIS_PIN, Y_AXIS_PIN, Z_AXIS_PIN
};
const unsigned int BUFFER_SIZE = 25;
const unsigned int BAUD_RATE = 9600;

int led1 = 8; //defining LED pin #'s
int led2 = 9;
int led3 = 10;
int led4 = 11;
int led5 = 12;
int X_AXIS = 0;


int buffer[NUM_AXES][BUFFER_SIZE]; // label id="code.motion.axis_buffer"
int buffer_pos[NUM_AXES] = { 0 }; // label id="code.motion.axis_buffer_pos"

void setup()
{
Serial.begin(BAUD_RATE);

pinMode(led1, OUTPUT); //Defining LED pins as outputs output
pinMode(led2, OUTPUT);
pinMode(led3, OUTPUT);
pinMode(led4, OUTPUT);
pinMode(led5, OUTPUT);

digitalWrite(led1, LOW); //setting LEDS to OFF for start
digitalWrite(led2, LOW);
digitalWrite(led3, LOW);
digitalWrite(led4, LOW);
digitalWrite(led5, LOW);
}

int get_axis(const int axis) {
delay(1); // <label id="code.motion.multiplex_delay"/>
buffer[axis][buffer_pos[axis]] = analogRead(PINS[axis]);
buffer_pos[axis] = (buffer_pos[axis] + 1) % BUFFER_SIZE;

long sum = 0;
for (int i = 0; i < BUFFER_SIZE; i++)
sum += buffer[axis][i];
return round(sum / BUFFER_SIZE);

// External AREF for better resolution
analogReference(EXTERNAL);
}

int get_x() { return get_axis(0); }
int get_y() { return get_axis(1); }
int get_z() { return get_axis(2); }


void loop() {

//Print ADC reading to serial monitor
Serial.print(get_x());
Serial.print(" ");
Serial.print(get_y());
Serial.print(" ");
Serial.println(get_z());

//get reading from X axis input on pin 2
X_AXIS = analogRead(X_AXIS_PIN);

// G force 1g to -1g

//LED1 on at .2g or 1g
if(X_AXIS > 546 || X_AXIS < 341) {digitalWrite(led1, HIGH);}
else {digitalWrite(led1, LOW);}

//LED2 on .4g or -.8g
if(X_AXIS > 580 || X_AXIS < 375) {digitalWrite(led2, HIGH);}
else {digitalWrite(led2, LOW);}

//LED3 on .6g or -.6g
if(X_AXIS > 614 || X_AXIS < 409) {digitalWrite(led3, HIGH);}
else {digitalWrite(led3, LOW);}

//LED4 on .8g or -.4g
if(X_AXIS > 648 || X_AXIS < 443) {digitalWrite(led4, HIGH);}
else {digitalWrite(led4, LOW);}

//LED5 on 1g or -.2g
if(X_AXIS > 682|| X_AXIS < 477 ) {digitalWrite(led5, HIGH);}
else {digitalWrite(led5, LOW);}

User avatar
cstratton
 
Posts: 294
Joined: Wed Sep 29, 2010 3:52 pm

Re: G meter coding help

Post by cstratton »

A simple algorithm would be to have a peak variable and a timer (which could be as crude and empirical as counting cycles through the loop). For simplicity of explanation I'm going to ignore the left right and just think of the turns as increasing the overall acceleration beyond 1g - it shouldn't be hard to extend the idea later.

1) If the current measurement is higher than the peak level, set the peak to the current measurement, display it, and reset the timer

2) If the timer has elapsed, clear the peak level and display nothing (or the current level, which will become the new peak on the next run of the loop)

Depending on what behavior you want, this may or may not have a failure mode. Consider

Time 0: execute 1.5g turn, gauge displays 1.5g
Time 0.5 execute 1.2g turn, gauge still displaying 1.5g
Time 1.0: timer expires, gauge now displaying 1.0g (or whatever)

The argument could be made that after the 1.5g peak expired, you should be display a 1.2g peak for another half second until that also expires - but if you really want that behavior, you would probably need a 1 second circular buffer from which you would always display the largest value. This is quite a bit more complicated to implement, and I'm guessing it's likely that you only care about the "big" turn and not the weaker one following it.

bchouston
 
Posts: 2
Joined: Sat Oct 29, 2011 12:36 pm

Re: G meter coding help

Post by bchouston »

What you said at the end would be correct. Any ideas on the actual coding needed to make this happen? I am clueless, but I am still trying to read through all of my arduino book to see if something similar can be adapted to it. thanks again

User avatar
adafruit_support_bill
 
Posts: 88093
Joined: Sat Feb 07, 2009 10:11 am

Re: G meter coding help

Post by adafruit_support_bill »

Have a variable for the peak, and another for the time-stamp of when it occurred.
Only update those variables if the reading is higher (new peak) or the time-stamp is more than 1 second old.

Locked
Please be positive and constructive with your questions and comments.

Return to “Arduino”