Accelerometer as Run/Stop sensor

Hi everyone
I wonder if its possible to use an accelerometer sensor with arduino for the purpose that the controller can find out if its moving or stationary? I would be mounting the circuit on a car and the circuit will blink an LED if the car is moving and otherwise if its not moving then the LED will turn off.

i have asked this question in an earlier post but that post was not specific to an accelerometer sensor. Hopefully someone will guide me how to use an accelerometer for this purpose. I need to make rough and approximate indication so a very slow speed for example 0.1kph can be taken as stop if that can help in simplifying and solving the problem. Also the response time of Stop/Run condition can also be as slow as few seconds.

Any help will be highly appreciated.

An accelerometer will only measur acceleration that is change in velocity, it will not measure velocity. When something is moving at a constant speed the acceleration will be zero, the same as it is at rest.

Normal measurements are noisy and you can't distinguish that from low levels of acceleration.

If you measure an axis at right angles to the direction of movement, say the up / down axis that might give you an indication of movement depending on how smooth the motion is, if it is rough that might give you a measure of if it has stopped.

The best way is to detect motion is to monitor the motor current.

Thanks "Grumpy_Mike" for the reply.
One limitation is that i cannot connect any wires from the circuit to the car. So everything should be on-board including the battery and sensors etc.

As i don't need to measure the speed with any degree of accuracy so maybe accelerometer can be used for Run/Stop sensor.
Regarding the constant speed vs zero speed, probably i can use the history log of motion to check if the car has stopped to moving with constant speed.

Can you provide some rough sample code for a 3-axis accelerometer used for this purpose?

I don't think you get what I was saying. I am saying that you can not measure speed only change in speed.

I have no sample code for this but any sample code for the sensor you are using should work, all you have to do is make sense of the readings, which I am saying you can't. However in any one situation you might be able to but you have to experiment. Make the measurements, see what you get and see if those results allow YOU to see if the car is moving or not.

Then it might be a simple matter to write code that matches your decision you make from just looking at the readings.

Grumpy_Mike:
If you measure an axis at right angles to the direction of movement, say the up / down axis that might give you an indication of movement depending on how smooth the motion is, if it is rough that might give you a measure of if it has stopped.

If i am using a 3-axis accelerometer in my circuit and the mounting of the circuit on the car is not in my hands, instead some other person will mount it randomly on the car. Then is it possible to write some code that can use your above logic/algo for detection of Run/Stop indication? Luckily the terrain is bumpy and uneven so the jumps are there all the time :slight_smile:

Hi,
I think you need to look at what the accelerometer does and what you have been told.

Assume you have the accelerometer mounted,

The car STARTS to move, you measure positive acceleration.
The car then drives at constant speed, you measure NIL acceleration.
The car then STOPS, you measure negative acceleration, deceleration.

You will not know if the car has stopped unless you have the same accel and deccel, and that just doesn't happen.

You can do calculations to calculate speed, but the calculation process has drift in its output, so STOP will probably not end up being calculated to ZERO speed.

Also you will need to keep track of ALL accel and decel readings as the car drives along, calculating current speed all the time.

Your best bet is GPS, monitor the speed output.

Tom... :slight_smile:

Thanks "TomGeorge" for the detail reply.
I have earlier used GPS, it works fine but there is a problem of no-fix in it. Now i an trying to find some other sensor maybe accelerometer or gyro etc.

Any help?

Then is it possible to write some code that can use your above logic/algo for detection of Run/Stop indication?

I would look at logging the results and a time stamp to an SD card so you can look at them later. This is all about pattern recognition and unless you know what pattern you are looking for you can't begin to write any code.

It is one of those projects that sound deceptively easy but getting good results is very difficult.

The best way of thinking about accelerometers is to imagine putting one on the International Space Station. What does it show? Pretty much exactly zero. What is the speed? Kilometers per second. That's many many thousands of kilometers per hour.

A vibration sensor might be best to detect a car moving or not-moving, if you can't rely on GPS. Particularly if you can tune it to the frequencies of vibration related to driving and can filter out frequencies like doors opening and closing.

I am interested in accelerometer because there is almost zero chance that the car will be running at constant speed for more than a few seconds. so if i check the speed for long durations then it looks like that accelerometer can fulfill the job.

Can anyone help in giving a simple sample code for a 3 axis-accelerometer? Please note that the mounting of the circuit on the vehicle is at random orientation, so i cannot align any axis with the direction of motion.

Hi,

Please note that the mounting of the circuit on the vehicle is at random orientation, so i cannot align any axis with the direction of motion.

You will have to orient it correctly, as turning a corner will produce acceleration in the cross axis to direction of motion.

You have acceleration in a vehicle in X Y and Z, so if you make X your direction of travel, you know to ignore Y and Z, but that relies on correct orientation.

Tom... :slight_smile:
PS Have you researched the process/maths needed to continually convert accel to velocity?

Using an accelerometer as a vibration sensor would probably work to get the run/stop indication.

Here's an example I just wrote for the ADXL345 3-axis accelerometer. Note that this chip can do this internally and will give you a direct on/off output on the INT pin if you program it correctly.

//Add the SPI library so we can communicate with the ADXL345 sensor
#include <SPI.h>

//threshold for vibration on any axis
#define THRESHOLD 6 //this is based on the ADXL345 integer output, 3 is approx 1/10th G

//Assign the Chip Select signal to pin 17. (testing on Teensy)
int CS=20;

//This is a list of some of the registers available on the ADXL345.
//To learn more about these and the rest of the registers on the ADXL345, read the datasheet!
char POWER_CTL = 0x2D;	//Power Control Register
char DATA_FORMAT = 0x31;
byte DATAX0 = 0x32;	//X-Axis Data 0
byte DATAX1 = 0x33;	//X-Axis Data 1
byte DATAY0 = 0x34;	//Y-Axis Data 0
byte DATAY1 = 0x35;	//Y-Axis Data 1
byte DATAZ0 = 0x36;	//Z-Axis Data 0
byte DATAZ1 = 0x37;	//Z-Axis Data 1

//This buffer will hold values read from the ADXL345 registers.
byte values[10];
//These variables will be used to hold the x,y and z axis accelerometer values.
int16_t x,y,z, prevX, prevY, prevZ;

void setup(){ 
  //Initiate an SPI communication instance.
  SPI.begin();
  //Configure the SPI connection for the ADXL345.
  SPI.setDataMode(SPI_MODE3);
  //Test a lower clock speed           //4 seems to be the default = 3.6MHz with clock speed 72MHz
  SPI.setClockDivider(SPI_CLOCK_DIV8); //8 gives us half that = 1.8MHz, which is plenty fast enough 
  //Create a serial connection to display the data on the terminal.
  Serial.begin(9600);

  //Set up the Chip Select pin to be an output from the Arduino.
  pinMode(CS, OUTPUT);
  //Before communication starts, the Chip Select pin needs to be set high.
  digitalWrite(CS, HIGH);
  
  //Put the ADXL345 into +/- 4G range by writing the value 0x01 to the DATA_FORMAT register.
  //Values are: 0x0 = 2G
  //            0x1 = 4G
  //            0x2 = 8G
  //            0x3 = 16G
  // try full-resolution mode (set the 4th bit to 1 for full-resolution 4mG per LSB)
  //only makes a difference for ranges other than 2G range
  const byte FULL_RES_MODE = 0x08;
  writeRegister(DATA_FORMAT, 0x03 | FULL_RES_MODE);
  //Put the ADXL345 into Measurement Mode by writing 0x08 to the POWER_CTL register.
  writeRegister(POWER_CTL, 0x08);  //Measurement mode  
}

void loop(){
  //Reading 6 bytes of data starting at register DATAX0 will retrieve the x,y and z acceleration values from the ADXL345.
  //The results of the read operation will get stored to the values[] buffer.
  readRegister(DATAX0, 6, values);

  //The ADXL345 gives 10-bit acceleration values, but they are stored as bytes (8-bits). To get the full value, two bytes must be combined for each axis.
  //The X value is stored in values[0] and values[1].
  x = ((int)values[1]<<8)|(int)values[0];
  //The Y value is stored in values[2] and values[3].
  y = ((int)values[3]<<8)|(int)values[2];
  //The Z value is stored in values[4] and values[5].
  z = ((int)values[5]<<8)|(int)values[4];
  
  //Print the results to the terminal.
  Serial.print(x, DEC);
  Serial.print(',');
  Serial.print(y, DEC);
  Serial.print(',');
  Serial.println(z, DEC);      

  if(abs(x-prevX)>THRESHOLD || abs(y-prevY)>THRESHOLD || abs(z-prevZ)>THRESHOLD) {
    Serial.println("MOVING");
  } else {
    Serial.println("Not moving");
  }
  prevX = x;
  prevY = y;
  prevZ = z;

  //for interest, calculate the absolute acceleration
  /*Serial.println(sqrt(x*x + y*y + z*z));*/
  delay(10); 
}

//This function will write a value to a register on the ADXL345.
//Parameters:
//  char registerAddress - The register to write a value to
//  char value - The value to be written to the specified register.
void writeRegister(char registerAddress, byte value){
  //Set Chip Select pin low to signal the beginning of an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the register address over SPI.
  SPI.transfer(registerAddress);
  //Transfer the desired register value over SPI.
  SPI.transfer(value);
  //Set the Chip Select pin high to signal the end of an SPI packet.
  digitalWrite(CS, HIGH);
}

//This function will read a certain number of registers starting from a specified address and store their values in a buffer.
//Parameters:
//  char registerAddress - The register addresse to start the read sequence from.
//  int numBytes - The number of registers that should be read.
//  char * values - A pointer to a buffer where the results of the operation should be stored.
void readRegister(char registerAddress, int numBytes, byte * values){
  //Since we're performing a read operation, the most significant bit of the register address should be set.
  char address = 0x80 | registerAddress;
  //If we're doing a multi-byte read, bit 6 needs to be set as well.
  if(numBytes > 1)address = address | 0x40;
  
  //Set the Chip select pin low to start an SPI packet.
  digitalWrite(CS, LOW);
  //Transfer the starting register address that needs to be read.
  SPI.transfer(address);
  //Continue to read registers until we've read the number specified, storing the results to the input buffer.
  for(int i=0; i<numBytes; i++){
    values[i] = SPI.transfer(0x00);
  }
  //Set the Chips Select pin high to end the SPI packet.
  digitalWrite(CS, HIGH);
}

MorganS:
A vibration sensor might be best to detect a car moving or not-moving, if you can't rely on GPS. Particularly if you can tune it to the frequencies of vibration related to driving and can filter out frequencies like doors opening and closing.

Thanks MorganS for the reply. I am going for the vibration sensor to detect vehicle run/stop condition as you have suggested.
Would you be kind enough to point out any specific vibration sensor for this purpose? There are so many different types available but i don't know which one will be suitable for the vehicle environment.

Put the sensor in a wheel, use radio to relay the data.
There are LOTS simpler and cheaper ways to sense a wheel turning though.

A vibration sensor can be a pair of metal contacts and a loose ball bearing rolling around. That's how the "tilt" sensor in an old pinball machine works.

These days, I'd use an ADXL345 accelerometer as the vibration sensor.