I managed to get the accelerometer to work and put in a sensitivity so it prints when the chip has been moved (i.e. does not print the raw data, just the statement “MOVED” when there has been movement.
However, for the bag movement alarm project I need it to tell for how long there has been movement, and only if there is movement for say 5 seconds does it trigger the “MOVED”… if it is moving for longer than 5 seconds then it has been stolen! The difficult part is that there may be moments in there where there is no movement, e.g. for a half second it may stop but then start moving again, and I don’t want that to ‘reset’ the movement time counter.
Here is what I thought of as a possible approach:
- I would store the ”moved” value in an array, shifting the new one in each time I take a reading. Since I have the sensor reading at 1/3 of a second right now, to store the previous 5 seconds of “moved” would take 15 elements. Each time I read a sensor value, I drop the oldest one, and add the newest one to the array.
- I would then look to see if there is a more than 5 second period between two moments of movement (i.e. it has been potentially been moving for more than 5 seconds). I may need to have another criteria: the number of seconds I am reviewing (e.g. may need to store the previous 10 seconds of data, and look at any more than 5 second period in that) but would need to think through if this is actually necessary given the second criteria.
- Then, I would loop through each element of the array and count how many are “moved” and how many are “not moved” between those two moments of movement, to see if it exceeds a threshold amount (say I allow 20% not movement).
This way, there would be two tests:
- Does the time between the oldest “moved” and the newest “moved” exceed 5 seconds? (i.e. it has potentially been moving for more that 5 seconds)
- If so, does “moved” exceed the threshold value for that time period? (i.e. it has actually been moving)
I can thus exclude the two events I want to exclude:
- Two blips more than 5 seconds apart, but with little movement in between (below the threshold).
- Movement (even 100% of the time) of say 4 seconds, and then stop.
I would only include it as “stolen” if:
- There are two blips of movement more than 5 second apart (with some maximum time period between moments of movement)
- AND there has been movement above the threshold in between those two blips (e.g. 80% of the time it has been moving)
After much back a forth, the following code was developed, which works.
// MPU-6050 MovementForXSeconds
//
//circuit:
// Arduino Ground –> MPU VCC
// Arduino 5V –> MPU VCC
// Arduino A4 (SDA) –> MPU SDA
// Arduino A5(SCL) –> MPU SCL#include<Wire.h>
const int MPU=0x68; // I2C address of the MPU-6050
int AcX,AcY,AcZ,Tmp,GyX,GyY,GyZ;
int OldAcX,OldAcY,OldAcZ,OldTmp,OldGyX,OldGyY,OldGyZ = 0;const int AcSensitivity = 500;
boolean moved = false;//———BELOW can change ————
const int maxMovementTime = 5000; //number of milliseconds. 5000 = 5 seconds.
const int maxStillnessThreshold = 20; // % threshold of stillness above which the thing is moving
const int readMPUinterval = 250; //number of milliseconds between checks of the accelerometer
//———ABOVE can change ————//const int movedRecordLength = int((int(maxMovementTime / interval) * (100 + maxStillnessThreshold)) / 100);
const int maxMovementTimeArrayDifference = maxMovementTime / readMPUinterval;
const int movedRecordLength = maxMovementTimeArrayDifference * 2;
boolean movedRecord[movedRecordLength];unsigned long previousMPUmillis = 0;
void setup(){
beginMPUcommunications();
intializeMovedRecord();
Serial.begin(9600);
Serial.print(“MovedRecordLength: “);
Serial.println(movedRecordLength);} //end setup
void loop(){
unsigned long currentMillis = millis();
boolean isStolen = false;if ((currentMillis – previousMPUmillis) > readMPUinterval){
// read the MPU and process the data
checkPositionChangeAndShiftRecord();
printMovedRecord();
isStolen = checkIfStolen();
if (isStolen == true) {
Serial.print(“STOLEN”);
} //end if stolen/
previousMPUmillis = currentMillis; //reset timer
} //end if
} //end loop//———–FUNCTIONS————————-
void intializeMovedRecord() {
for (int x = 0; x < movedRecordLength; x++) {
movedRecord[x] = false;
} //end for
} //end initializeMovedRecordvoid printMovedRecord() {
for (int x = 0; x < movedRecordLength; x++) {
Serial.print(movedRecord[x]);
} //end for
Serial.println();
} //end initializeMovedRecordvoid beginMPUcommunications() {
Wire.begin();
Wire.beginTransmission(MPU);
Wire.write(0x6B); // PWR_MGMT_1 register
Wire.write(0); // set to zero (wakes up the MPU-6050)
Wire.endTransmission(true);
} //end beginMPUcommunicationsvoid readMPUrawvalues() {
Wire.beginTransmission(MPU);
Wire.write(0x3B); // starting with register 0x3B (ACCEL_XOUT_H)
Wire.endTransmission(false);
Wire.requestFrom(MPU,14,true); // request a total of 14 registers
AcX=Wire.read()<<8|Wire.read(); // 0x3B (ACCEL_XOUT_H) & 0x3C (ACCEL_XOUT_L)
AcY=Wire.read()<<8|Wire.read(); // 0x3D (ACCEL_YOUT_H) & 0x3E (ACCEL_YOUT_L)
AcZ=Wire.read()<<8|Wire.read(); // 0x3F (ACCEL_ZOUT_H) & 0x40 (ACCEL_ZOUT_L)
Tmp=Wire.read()<<8|Wire.read(); // 0x41 (TEMP_OUT_H) & 0x42 (TEMP_OUT_L)
GyX=Wire.read()<<8|Wire.read(); // 0x43 (GYRO_XOUT_H) & 0x44 (GYRO_XOUT_L)
GyY=Wire.read()<<8|Wire.read(); // 0x45 (GYRO_YOUT_H) & 0x46 (GYRO_YOUT_L)
GyZ=Wire.read()<<8|Wire.read(); // 0x47 (GYRO_ZOUT_H) & 0x48 (GYRO_ZOUT_L)
} //end readMPUrawvaluesvoid checkPositionChangeAndShiftRecord() {
readMPUrawvalues();
//Check to see if it has moved and add to the move record
if (abs(OldAcX – AcX) > AcSensitivity) { moved = true; }
if (abs(OldAcY – AcY) > AcSensitivity) { moved = true; }
if (abs(OldAcY – AcY) > AcSensitivity) { moved = true; }
shiftMovedRecord(moved);
//reset the values for next check
OldAcX = AcX;
OldAcY = AcY;
OldAcZ = AcZ;
moved = false;
} //end checkPositionChangeAndShiftRecordvoid shiftMovedRecord(boolean movedValue) { //PURPOSE: shifts the movedRecord one to the left, and then adds the value of the most recent moved record the right
for (int x = 0; x < movedRecordLength; x++) { //step through the movedRecord
movedRecord[x] = movedRecord[x+1]; //for each record spot, shift it to the left. the first record gets lost.
if (x == (movedRecordLength-1)) { //if the last spot, add the new record from the most recent record
movedRecord [x] = movedValue;
} //end if
}//end for
} //end shiftMovedRecordboolean checkIfStolen() {
//—————First test: is there movement more than 5 seconds apart
int firstMoved = movedRecordLength -1;
int lastMoved = 0;
boolean firstMovedSet = false;
boolean lastMovedSet = false;
boolean movedEnoughTime = false;for (int x = 0; x < movedRecordLength; x++) { // get first moved
if (movedRecord[x] == true && firstMovedSet == false) {
firstMoved = x;
firstMovedSet = true;
} //end if
} //end forfor (int x = (movedRecordLength – 1); x >= 0; x–) { // get last moved
if (movedRecord[x] == true && lastMovedSet == false) {
lastMoved = x;
lastMovedSet = true;
} //end if
} //end forif ((lastMoved – firstMoved) > maxMovementTimeArrayDifference){
movedEnoughTime = true;
}
//————-end First test —————————————–//—————Second test: if there is movement over 5 seconds, is it more than the threshold
if (movedEnoughTime == true){
int trueCounter = 0;
for (int x = firstMoved; x <= lastMoved; x++) { //step through the movedRecord
if (movedRecord[x] == true) {
trueCounter++;
} //end if
} //end forint movementPercent = map(trueCounter, 0, lastMoved – firstMoved + 1, 0, 100);
if (movementPercent > maxStillnessThreshold) {
return true;
} //end greater than maxStillnessThreshold
else {
return false;
} //end less than maxStillnessThreshold} //end—————–Second test ——— if movement over difference in array
} //end checkIfStolen