Friday, November 14, 2014

How to Combine a Vibration Sensor and Reed Switch to Detect Door Open or Tailgate Down

In this project I show how to make a door open or tailgate down sensor using an Arduino vibration sensor and Reed switch. This builds on my previous blogs of how to build a high sensitivity vibration sensor, and how to avoid false positives with a high sensitivity piezo vibration sensor. In this latest project I use a Reed switch to detect if something is open, for example a door or a tailgate. The sketch running on the Arduino Uno only records vibration events if the Reed switch is open. In order to trigger the vibration alarm it must receive at least 5 vibration events within a 5 second period (configurable in sketch below). Each vibration event is represented as a square pulse out of the comparator in the vibration sensor circuit. When the vibration alarm is triggered it fires the large LED . This could be placed in the view of a rear view mirror for example, to alert the driver that the car or truck is in motion and something is left open, for example a tailgate may be down.

Below is the sketch I used, running on the Arduino Uno:

#define VIBRATION_SENSOR_DIGITAL_INPUT_PIN 10
#define VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN 8
#define REED_SWITCH_DIGITAL_INPUT_PIN 6

#define VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT 5
#define VIBRATION_EVENTS_ALARM_THRESHOLD_PERIOD_MILLIS 5000

#define VIBRATION_ALARM_FLASHES 5
#define VIBRATION_ALARM_PERIOD_MILLIS 400

long vibrationEvents[VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT];
int vibrationEventIndex;

//------------------------------------------------------------------
void setup(){
  Serial.begin(19200);
  
  pinMode(VIBRATION_SENSOR_DIGITAL_INPUT_PIN, INPUT);
  pinMode(REED_SWITCH_DIGITAL_INPUT_PIN, INPUT);
  pinMode(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, OUTPUT);
  
  vibrationEventIndex = 0;
  clearVibrationEvents();
}

//------------------------------------------------------------------
void loop(){
  // only pay attention to vibration when the Reed switch is open
  if(digitalRead(REED_SWITCH_DIGITAL_INPUT_PIN) == HIGH && 
     digitalRead(VIBRATION_SENSOR_DIGITAL_INPUT_PIN) == HIGH){
       
    addVibrationSample();
    delay(100); // debounce current vibration shock
  }
}

//------------------------------------------------------------------
void addVibrationSample(){
   vibrationEvents[vibrationEventIndex++] = millis();
   
   // wrap index around end of sample array
   vibrationEventIndex %= VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT; 
   
  if(isVibrationAlarmTiggered()){
    Serial.println(String(millis()) + "\t ALARM");
    triggerAlarm();
  }
}

//------------------------------------------------------------------
boolean triggerAlarm(){
  for(int i = 0; i < VIBRATION_ALARM_FLASHES; ++i){
    digitalWrite(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, HIGH);
    delay(VIBRATION_ALARM_PERIOD_MILLIS/2);
    digitalWrite(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, LOW);
    delay(VIBRATION_ALARM_PERIOD_MILLIS/2);
  }
  clearVibrationEvents();
}

//------------------------------------------------------------------
void clearVibrationEvents(){
  for(int i = 0; i < VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT ; ++i){
    vibrationEvents[i] = -1;
  }
}

//------------------------------------------------------------------
boolean isVibrationAlarmTiggered(){
  long thresholdMillis 
    = millis() - VIBRATION_EVENTS_ALARM_THRESHOLD_PERIOD_MILLIS;
    
  if(thresholdMillis < 0) thresholdMillis = 0;
  int numVibrationsSinceThreshold = 0;
  for(int i = 0; i < VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT ; ++i){
    if(vibrationEvents[i] >= thresholdMillis){
      ++numVibrationsSinceThreshold;
    }
  }
  
  Serial.println(
    String(millis()) + 
    "\t# events: " + 
    String(numVibrationsSinceThreshold));
    
  boolean alarmTriggered = false;
  if(numVibrationsSinceThreshold >= VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT){
    alarmTriggered = true;
  }
  
  return alarmTriggered;
}

//------------------------------------------------------------------

If you are interested in how this type of sensor can be integrated into a broader solution that includes notification of a door open on a users Android phone see Detect if a Door or Gate is Opened

Friday, November 7, 2014

How to Avoid False Positives with a High Sensitivity Piezo Vibration Sensor

Thanks for all the interest and comments in my previous blog on the High Sensitivity Vibration Sensor. In this previous project I described how to use a piezo element, an op amp and comparator to create a high sensitivity vibration sensor. Based on the great level of interest in this project I have created an advanced vibration sensor that uses the same design and builds upon it. One of the challenges with vibration sensors is screening out spurious events such as bumps that can lead to false positives. In this project the sketch running on the Arduino Uno watches for vibration events but only triggers if it sees 5 vibration events within a 5 second period. So if it gets 3 events and then none for a while it will forget those 3 events. Only if it gets 5 or more within 5 seconds will the alarm trigger. This effectively screens out spurious bumps and fires on persistent vibration events. This can be useful for a variety of applications where was is sought is the ability to detect vibration rather than a single bump. The values for the number of events (5 in my sketch) and period of time (5 seconds) are configurable by changing the values at the top of the sketch for your project.

You can find the sketch I used on the Arduino Uno below:

#define VIBRATION_SENSOR_DIGITAL_INPUT_PIN 10
#define VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN 8

#define VIBRATION_SAMPLE_ARRAY_SIZE 100

// if we 5 or more vibration events over a five second period then a vibration alarm is triggered
#define VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT 5
#define VIBRATION_EVENTS_ALARM_THRESHOLD_PERIOD_MILLIS 5000

long vibrationEvents[VIBRATION_SAMPLE_ARRAY_SIZE];
int vibrationEventIndex;

void setup(){
  Serial.begin(19200);
  
  pinMode(VIBRATION_SENSOR_DIGITAL_INPUT_PIN, INPUT);
  pinMode(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, OUTPUT);
  
  vibrationEventIndex = 0;
  clearVibrationEvents();
}

void loop(){
  if(digitalRead(VIBRATION_SENSOR_DIGITAL_INPUT_PIN) == HIGH){
    long currentMillis = millis();
    addVibrationSample(currentMillis);
    if(isVibrationAlarmTiggered()){
      triggerAlarm();
      Serial.println(String(millis()) + "\t ALARM");
    }
    delay(100); // wait for current vibration shock to subside
  }
}

void addVibrationSample(long vibrationMillis){
   vibrationEvents[vibrationEventIndex++] = vibrationMillis;
   if(vibrationEventIndex >= VIBRATION_SAMPLE_ARRAY_SIZE){
     vibrationEventIndex = 0; // wrap vibration sample index around when we get to end of sample array
   }
}

boolean triggerAlarm(){
  digitalWrite(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, HIGH);
  delay(1000);
  digitalWrite(VIBRATION_SENSOR_DIGITAL_OUTPUT_PIN, LOW);
  clearVibrationEvents();
}

void clearVibrationEvents(){
  for(int i = 0; i < VIBRATION_SAMPLE_ARRAY_SIZE ; ++i){
    vibrationEvents[i] = -1;
  }
}

boolean isVibrationAlarmTiggered(){
  long thresholdMillis = millis() - VIBRATION_EVENTS_ALARM_THRESHOLD_PERIOD_MILLIS;
  if(thresholdMillis < 0) thresholdMillis = 0;
  int numVibrationsSinceThreshold = 0;
  for(int i = 0; i < VIBRATION_SAMPLE_ARRAY_SIZE ; ++i){
    if(vibrationEvents[i] >= thresholdMillis){
      ++numVibrationsSinceThreshold;
    }
  }
  
  Serial.println(String(millis()) + "\t# events: " + String(numVibrationsSinceThreshold));
  boolean alarmTriggered = false;
  if(numVibrationsSinceThreshold >= VIBRATION_EVENTS_ALARM_THRESHOLD_COUNT){
    alarmTriggered = true;
  }
  
  return alarmTriggered;
}



Below is an example of the output on the Arduino IDE console when the Arduino Uno is running off a USB cable:

9018 # events: 1
9703 # events: 2
10330 # events: 3
10935 # events: 4
11697 # events: 5
12698  ALARM
14902 # events: 1
15398 # events: 2
15925 # events: 3
27161 # events: 1

If you found this interesting you may also want to have a look at how to build a High Sensitivity Sound Level Detector. You may also want to look at my subsequent blog on how to use these in an open door or tailgate down sensor which also uses a Reed switch.

If you are interested in how this type of sensor can be integrated into a broader solution that includes notification of detected vibration on a users Android phone see Detect Intrusion with Passive Infrared, Sound, or Vibration