Created
October 22, 2015 13:53
-
-
Save fexploit/b2388f4e2461af302658 to your computer and use it in GitHub Desktop.
Arduino based Outdoor People Counter. see https://github.com/petervojtek/diy/wiki/Arduino-based-Outdoor-People-Counter
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <lowpower.h> | |
| #include <EEPROM.h> | |
| int currentSessionId; | |
| int humanCount = 0; | |
| int eepromHumanCount = 0; | |
| long eepromLastSyncAt = 0; | |
| const int trigPin = 9; | |
| const int echoPin = 10; | |
| const int humanCountedLedPin = 11; | |
| boolean iSeeHuman = false; | |
| boolean iTrackHuman = false; | |
| long lastTimeISawHuman; | |
| // once we observe a person, we count number of times the person stays in front of our device | |
| int numberOfPingsObsevedHumanIsInRange = 0; | |
| // minimum count of hitting a "person" by ultrasonic sensor to accept it as a person | |
| static int minPingCountToAcceptHuman = 2; | |
| static float maxBlackoutInMillis = 500; | |
| static int iSeeHumanThresholdInCm = 250; | |
| // set to true to make the LED blink everytime we count a person | |
| const boolean DEBUG = true; | |
| void setup() { | |
| LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF); | |
| pinMode(trigPin, OUTPUT); | |
| pinMode(echoPin, INPUT); | |
| detectCurrentSessionId(); | |
| if(DEBUG){ | |
| pinMode(humanCountedLedPin, OUTPUT); | |
| blinkHumanCountedLed(); | |
| Serial.begin(9600); | |
| delay(500); | |
| printHistory(); | |
| } | |
| } | |
| void loop() | |
| { | |
| iSeeHuman = pingDistanceInCm() < iSeeHumanThresholdInCm; | |
| if(iSeeHuman && !iTrackHuman) // we have first contact with human | |
| { | |
| numberOfPingsObsevedHumanIsInRange = 1; | |
| iTrackHuman = true; | |
| lastTimeISawHuman = millis(); | |
| } | |
| else if(iSeeHuman && iTrackHuman) // we already recognized him and we keep tracking him | |
| { | |
| numberOfPingsObsevedHumanIsInRange++; | |
| lastTimeISawHuman = millis(); | |
| } | |
| else if(!iSeeHuman && iTrackHuman) | |
| { | |
| if((millis() - lastTimeISawHuman) < maxBlackoutInMillis) | |
| { | |
| // wo dont see him now, but we believe he may still be in sight | |
| } | |
| else | |
| { // we havent seen him for too long | |
| iTrackHuman = false; | |
| if(numberOfPingsObsevedHumanIsInRange >= minPingCountToAcceptHuman){ | |
| humanCount++; | |
| if(DEBUG) | |
| blinkHumanCountedLed(); | |
| } | |
| } | |
| } | |
| else | |
| { | |
| // !iSeeHuman && !iTrackHuman - nothing to do | |
| } | |
| syncHumanCount(); | |
| LowPower.powerDown(SLEEP_15Ms, ADC_OFF, BOD_OFF); | |
| } | |
| long pingDistanceInCm(){ | |
| digitalWrite(trigPin, LOW); | |
| delayMicroseconds(2); | |
| digitalWrite(trigPin, HIGH); | |
| delayMicroseconds(10); | |
| digitalWrite(trigPin, LOW); | |
| long durationInMicroseconds = pulseIn(echoPin, HIGH, 15 * 1000); | |
| long cm = durationInMicroseconds / 58; | |
| if(cm == 0){ | |
| // when the background is too far away, the measurement may return distance = 0 cm | |
| // in such case we want to avoid counting this ping as a human presence | |
| cm = 500; | |
| } | |
| return(cm); | |
| } | |
| void detectCurrentSessionId(){ | |
| int previousSessionId = EEPROM.read(0); | |
| if(previousSessionId == 255) // "Locations that have never been written to have the value of 255." | |
| currentSessionId = 1; | |
| else | |
| currentSessionId = previousSessionId + 1; | |
| EEPROM.write(0, currentSessionId); | |
| } | |
| int majorHumanCount; | |
| int minorHumanCount; | |
| int majorBytePosition; | |
| int minorBytePosition; | |
| // we dont want to write too ofter to eeprom: | |
| // atmel warns the eeprom may die after 100.000 r&w cycles (per single eeprom byte) | |
| // also the 1byte write takes cca 3.3ms | |
| void syncHumanCount() | |
| { | |
| if((humanCount - eepromHumanCount) > 10){ | |
| majorHumanCount = humanCount / 256; | |
| minorHumanCount = humanCount % 256; | |
| majorBytePosition = currentSessionId * 2 - 1; | |
| minorBytePosition = majorBytePosition + 1; | |
| EEPROM.write(majorBytePosition, majorHumanCount); | |
| EEPROM.write(minorBytePosition, minorHumanCount); | |
| eepromLastSyncAt = millis(); | |
| eepromHumanCount = humanCount; | |
| } | |
| } | |
| // session 1: 1,2 | |
| // session 2: 3,4 | |
| // session 3: 3*2 -1, 3*2 | |
| // session 100: [100*2 - 1, 100*2] | |
| // majorBytePosition = sessionId*2 - 1 | |
| // minorBytePosition = sessionId*2 | |
| void printHistory() | |
| { | |
| Serial.write("History\n\n"); | |
| int sessionHumanCount; | |
| for(int sessionId = 1; sessionId < currentSessionId; sessionId++) | |
| { | |
| majorBytePosition = sessionId * 2 - 1; | |
| minorBytePosition = majorBytePosition + 1; | |
| sessionHumanCount = 256 * ( EEPROM.read(majorBytePosition)) + EEPROM.read(minorBytePosition); | |
| Serial.print("session id: "); | |
| Serial.println(sessionId); | |
| Serial.print("session count: "); | |
| Serial.println(sessionHumanCount); | |
| Serial.println(); | |
| } | |
| } | |
| void resetSessionInfoInEeprom(){ | |
| EEPROM.write(0, 0); | |
| } | |
| void blinkHumanCountedLed(){ | |
| for(int i = 0; i < 5; i++){ | |
| digitalWrite(humanCountedLedPin, HIGH); | |
| delay(50); | |
| digitalWrite(humanCountedLedPin, LOW); | |
| delay(50); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment