Advertisement
vulture2600

SammyDoor

Oct 30th, 2015
134
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 12.51 KB | None | 0 0
  1. /*
  2. SammyDoor!
  3. Automatic door for my cat. This sketch unlocks and props open a door when my cat wants to enter or exit the house. There is an ultrasonic range finder on the
  4. inside of the house for when he wants to exit and an IR break beam sensor inside the box for when he wants to enter. There are three temp sensors on the
  5. OneWire box. There is also a magnetic door switch that senses when the door is fully closed. Photos will be posted soon.
  6. steve.a.mccluskey@gmail.com
  7.  
  8. Revision history:
  9. V1.0: Prototype release.
  10. V1.1: Added 2nd and 3rd temp sensor on OneWire bus. There is now a sensor in the room, inside the insulated box and outside to get an idea of the
  11. temperature gradient and see how well the insulation is working. 11/12/15.
  12.  
  13. Hardware used:
  14. Arduino Uno.
  15. Adafruit ProtoShield.                        
  16. Adafruit I2C MotorShield.
  17. Adafruit I2C LCD Backpack.
  18. 16x2 Standard LCD.
  19. DS18B20 OneWire digital waterproof temp sensor (3x).    
  20. Magnetic door sensor.
  21. 5V voltage regulator.
  22. Micro servo to simulate door lock.
  23. Large servo to prop door open.
  24.  
  25. Pin layout as follows:
  26. 0  : Hardware serial RX.
  27. 1  : Hardware serial TX.
  28. 2  :
  29. 3 ~:
  30. 4  : Magnetic door sensor.
  31. 5 ~: Break beem sensor.
  32. 6 ~: OneWire bus.
  33. 7  : Ultrasonic range finder trigger pin.
  34. 8  : Ultrasonic range finder echo pin.
  35. 9 ~: Door servo.
  36. 10~: Lock servo.
  37. 11~:
  38. 12 : Green LED on protoshield.
  39. 13 : Red LED on protoshield.
  40.  
  41. A0 :
  42. A1 :
  43. A2 :
  44. A3 :
  45. A4 : I2C SDA.
  46. A5 : I2C SCL.
  47.  
  48. Sketch outline:
  49. Libraries.
  50. Pin declarations.
  51. Global values.
  52. Timer values.
  53. Sensor variables.
  54. Boolean variables.
  55. Objects.
  56.  
  57. setup().
  58. loop() {
  59.  
  60. }
  61. openTheDoor().
  62. closeTheDoor().
  63. lockDoor().
  64. unlockDoor().
  65. printResults().
  66. cToF().
  67. getOneWireTemp().
  68. */
  69.  
  70. #include <Wire.h>
  71. #include <Adafruit_MotorShield.h>
  72. #include "utility/Adafruit_PWMServoDriver.h"
  73. #include <NewPing.h>
  74. #include <Servo.h>
  75. #include <Wire.h>
  76. #include <OneWire.h>
  77. #include <LiquidTWI.h>
  78.  
  79. //#define includeMotor           // Comment out to remove all motor code.
  80. #define debug                  // Comment out to skip printResults().
  81.  
  82. // Global values:
  83. #define doorSensor       4     // Magnetic sensor on door.
  84. #define beamSensor       5     // Break beam sensor.
  85. #define oneWireBus       6     // OneWire bus.
  86. #define TRIGGER_PIN      7     // Arduino pin tied to trigger pin on the ultrasonic sensor.
  87. #define ECHO_PIN         8     // Arduino pin tied to echo pin on the ultrasonic sensor.
  88. #define doorServoPin     9     // Door servo.
  89. #define lockServoPin     10    // Lock servo.
  90. #define greenLed         12    // Green LED on protoshield.
  91. #define redLed           13    // Red LED on protoshield.
  92.  
  93. #define MAX_DISTANCE     150   // Maximum distance we want to ping for (in centimeters). Maximum sensor distance is rated at 400-500cm.
  94. #define triggerDistance  75    // Distance threshold.
  95. #define readingInterval  500   // Interval between readings in ms.
  96. #define doorCloseTimeout 8000  // How long to keep the door open.
  97. #define lockTimeout      5000  // How long to keep the door unlocked after closing.
  98. #define doorClosedPos    130   // Closed position for door servo.
  99. #define doorOpenPos      70    // Open position for door servo.
  100. #define doorLockPos      0     // Locked position for lock servo.
  101. #define doorUnlockPos    170   // Unlocked posittion for lock servo.
  102.  
  103. // Timer variables:
  104. unsigned long timeNow;        
  105. unsigned long timeDoorOpen;
  106. unsigned long timeLast;
  107. //unsigned long detachDelay = 500;
  108. unsigned long lockDelay;
  109.  
  110. // Sensor variables:
  111. uint8_t  dists[8]   = {150, 150, 150, 150, 150, 150, 150, 150}; // Array to store distances. Set to high value by default so a low average doesnt cause door to open upon startup.
  112. uint8_t  beams[8]   = {0};                                      // Array to store beam readings.
  113. uint8_t  slot       =  0;
  114.  
  115. uint16_t avgDist    =  0;
  116. uint8_t  avgBeams   =  0;
  117.  
  118. // Booleans:
  119. bool     doorOpen   =  false;
  120. bool     doorLocked =  false;
  121. bool     doorClear  =  false;
  122. bool     lockReset  =  false;
  123. bool     beamClear  =  false;
  124.  
  125. // Objects:
  126. NewPing  sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);     // NewPing setup of pins and maximum distance.
  127.  
  128. Servo    doorServo;
  129. Servo    lockServo;
  130.  
  131. OneWire  oneWire(oneWireBus);
  132. byte     sensor1 [8];                                    // Arrays to store OneWire device's address.
  133. byte     sensor2 [8];
  134. byte     sensor3 [8];
  135. int8_t   tempOut = 0;                                    
  136. int8_t   tempBox = 0;
  137. int8_t   tempIn  = 0;
  138.  
  139. #ifdef includeMotor
  140.   Adafruit_MotorShield  AFMS       = Adafruit_MotorShield();
  141.   Adafruit_StepperMotor *myStepper = AFMS.getStepper(513, 2);
  142.   Adafruit_DCMotor      *myMotor1  = AFMS.getMotor(1);
  143.   Adafruit_DCMotor      *myMotor2  = AFMS.getMotor(2);
  144. #endif
  145.  
  146. LiquidTWI lcd(1);                                        // LCD on I2C Backpack.
  147.  
  148. void setup() {
  149.   Serial.begin(19200);
  150.   lcd.begin(16, 2);
  151.   lcd.setCursor(0, 0);
  152.   lcd.print(F("SammyDoor!"));
  153.   lcd.setCursor(0, 1);
  154.   lcd.print(F("V 1.1"));
  155.   delay(1000);
  156.   lcd.clear();
  157.   doorServo.attach(doorServoPin);
  158.   lockServo.attach(lockServoPin);
  159.   doorServo.write (doorClosedPos);
  160.   lockServo.write (doorUnlockPos);
  161.   delay(500);
  162.   doorServo.detach();
  163.   //lockServo.detach();
  164.   pinMode(doorSensor, INPUT_PULLUP);
  165.   pinMode(beamSensor, INPUT_PULLUP);
  166.   pinMode(greenLed,   OUTPUT);
  167.   pinMode(redLed,     OUTPUT);
  168.   oneWire.search(sensor1);
  169.   oneWire.search(sensor2);
  170.   oneWire.search(sensor3);
  171.  
  172.   #ifdef includeMotor
  173.     AFMS.begin();
  174.     myStepper->setSpeed(50);
  175.     myMotor1->setSpeed(75);
  176.     myMotor1->run(RELEASE);
  177.     myMotor2->setSpeed(75);
  178.     myMotor2->run(RELEASE);
  179.   #endif
  180. } // end setup().
  181.  
  182. void loop() {
  183.   timeNow = millis();
  184.   lcd.setCursor(0, 0);
  185.   lcd.print(F("I:"));
  186.   lcd.print(tempIn);
  187.   lcd.print(F("F "));
  188.   lcd.print(F("B:"));
  189.   lcd.print(tempBox);
  190.   lcd.print(F("F "));
  191.   lcd.print(F("O:"));
  192.   lcd.print(tempOut);
  193.   lcd.print(F("F   "));
  194.   lcd.setCursor(0, 1);
  195.   lcd.print(F("Door: "));
  196.   if (!doorOpen && doorLocked) {
  197.     lcd.print(F("Locked.     "));
  198.   }
  199.   else if (!doorOpen && !doorLocked) {
  200.     lcd.print(F("Unlocked.    "));
  201.   }
  202.   else if (doorOpen) {
  203.     lcd.print(F("Open!    "));
  204.   }
  205.  
  206.   if (digitalRead(doorSensor) == LOW) {        
  207.     // Read door sensor every time thru loop. Input is pulled low when door is closed.
  208.     doorClear   = true;
  209.     digitalWrite(redLed, LOW);
  210.     if (!lockReset) {
  211.       lockDelay = timeNow;
  212.       lockReset = true;
  213.     } // end if.
  214.   } // end if.
  215.   else {
  216.     doorClear = false;
  217.     digitalWrite(redLed, HIGH);
  218.     lockReset = false;                             // Reset lock timer if door is opened.
  219.   } // end else.
  220.    
  221.   if (timeNow - timeLast > readingInterval) {      // Wait 500ms between readings.
  222.     tempOut       = cToF(getOneWireTemp(sensor1)); // Get OneWire temp and convert to F.
  223.     tempBox       = cToF(getOneWireTemp(sensor2));
  224.     tempIn        = cToF(getOneWireTemp(sensor3));
  225.     dists[slot]   = sonar.ping_cm();               // Store distance to current array slot.
  226.     if (dists[slot] < 15) {                        // Prevent erranious low pings.
  227.       dists[slot] = 86;
  228.     }    
  229.    
  230.     if (digitalRead(beamSensor) == HIGH) {
  231.       beams[slot] = 0;                             // Save zero value to array.
  232.       digitalWrite(greenLed, LOW);
  233.       beamClear   = true;
  234.     } // end if.
  235.     else {
  236.       beamClear   = false;
  237.       beams[slot] = 10;                            // Save value 10 to array.
  238.       digitalWrite(greenLed, HIGH);
  239.     } // end else.
  240.    
  241.     avgDist       = 0;
  242.     avgBeams      = 0;
  243.    
  244.     for (uint8_t x = 0; x < 8; x ++) {             // Add them up.
  245.       avgDist  += dists[x];
  246.       avgBeams += beams[x];
  247.     } // end for.
  248.    
  249.     avgDist  /= 8;                                 // Average them.
  250.     avgBeams /= 8;
  251.    
  252.     #ifdef debug
  253.       printResults();                              // For debugging.
  254.     #endif
  255.    
  256.     slot ++;                                       // Increment slot.
  257.     if (slot > 7) {                                // reset to zero if 8.
  258.       slot = 0;
  259.     } // end if.
  260.     timeLast = timeNow;                            // Reset reading timer.
  261.   } // end if.
  262.  
  263.   // Open door logic:
  264.   if ((avgDist <= triggerDistance && avgDist > 0) || avgBeams >= 9) {
  265.     unlockDoor ();
  266.     openTheDoor();
  267.     timeDoorOpen = timeNow;                        // Reset timer to hold door open.
  268.   } // end if.
  269.  
  270.   // Close door logic:
  271.   else if ((avgDist > triggerDistance || avgBeams < 2) && (timeNow - timeDoorOpen > doorCloseTimeout)) {
  272.     closeTheDoor();
  273.     if (doorClear) {
  274.       lockDoor();
  275.     } // end if.
  276.   } // end else if.
  277. } // end loop().
  278.  
  279. void openTheDoor() {
  280.   if (!doorOpen) {    
  281.     doorServo.attach(doorServoPin);
  282.     doorServo.write (doorOpenPos);
  283.     delay(500);
  284.     doorServo.detach();
  285.     //delay(250);
  286.     doorOpen = true;
  287.   } // end if.
  288. } // end openTheDoor().
  289.  
  290. void closeTheDoor() {
  291.   if (doorOpen) {
  292.     doorServo.attach(doorServoPin);
  293.     doorServo.write(doorClosedPos);
  294.     doorOpen = false;
  295.     delay(500);
  296.     doorServo.detach();    
  297.   } // end if.
  298. } // end closeTheDoor().
  299.  
  300. void lockDoor() {
  301.   if (!doorLocked && (timeNow - lockDelay > lockTimeout)) {
  302.     #ifdef includeMotor
  303.       myStepper->step(100, FORWARD, DOUBLE);
  304.       myMotor1->setSpeed(75);
  305.       myMotor2->setSpeed(75);
  306.       myMotor1->run(FORWARD);
  307.       myMotor2->run(FORWARD);
  308.     #endif
  309.     lockServo.attach(lockServoPin);
  310.     lockServo.write(doorLockPos);
  311.     delay(500);
  312.     lockServo.detach();
  313.    
  314.     #ifdef includeMotor
  315.       myMotor1->setSpeed(0);
  316.       myMotor2->setSpeed(0);
  317.     #endif
  318.    
  319.     lockServo.detach();  
  320.     doorLocked = true;
  321.   } // end if.  
  322. } // end lockDoor().
  323.  
  324. void unlockDoor() {
  325.   if (doorLocked) {
  326.     #ifdef includeMotor
  327.       myStepper->step(100, BACKWARD, DOUBLE);
  328.       myMotor1->setSpeed(75);
  329.       myMotor2->setSpeed(75);
  330.       myMotor1->run(BACKWARD);
  331.       myMotor2->run(BACKWARD);
  332.       delay(500);
  333.     #endif
  334.    
  335.     lockServo.attach(lockServoPin);
  336.     lockServo.write (doorUnlockPos);
  337.     delay(500);
  338.     lockServo.detach();
  339.    
  340.     #ifdef includeMotor
  341.       myMotor1->setSpeed(0);
  342.       myMotor2->setSpeed(0);
  343.     #endif
  344.    
  345.     doorLocked = false;
  346.   } // end if.
  347. } // end unlockDoor().
  348.  
  349. void printResults() { // For debugging.
  350.   Serial.print(F("Current slot: "));
  351.   Serial.println(slot);
  352.   Serial.print(F("Distance: "));
  353.   Serial.print(dists[slot]);                
  354.   Serial.println(F("cm"));  
  355.   for (uint8_t x = 0; x < 8; x ++) {
  356.     Serial.print(dists[x]);
  357.     Serial.print(" ");
  358.   } // end for.
  359.   Serial.println();
  360.   Serial.print  (F("Avg: "));
  361.   Serial.println(avgDist);
  362.   if (beamClear) {
  363.     Serial.println(F("Sensor: Clear"));
  364.   } // end if.
  365.   else {
  366.     Serial.println(F("Sensor: BLOCKED!"));
  367.   } // end else.
  368.   for (uint8_t x = 0; x < 8; x ++) {
  369.     Serial.print(beams[x]);
  370.     Serial.print(" ");
  371.   } // end for.
  372.   Serial.println();
  373.   Serial.print  (F("Beams: "));
  374.   Serial.println(avgBeams);
  375.  
  376.   if (!doorLocked) {
  377.     Serial.println(F("Door: Unlocked."));
  378.   } // end if.
  379.   else {
  380.     Serial.println(F("Door: locked."));
  381.   } // end else.
  382.  
  383.   if (doorOpen) {
  384.     Serial.println(F("Door state: OPEN!"));
  385.   } // end if.
  386.   else {
  387.     Serial.println(F("Door state: closed."));
  388.   } // end else.
  389.  
  390.   if (doorClear) {
  391.     Serial.println(F("Door: clear."));
  392.   } // end if.
  393.   else {
  394.     Serial.println(F("Door: blocked"));
  395.   } // end else.
  396.   Serial.print(F("Current outside temp: "));
  397.   Serial.print(tempOut);
  398.   Serial.println(F(" F"));
  399.   Serial.print(F("Current box temp    : "));
  400.   Serial.print(tempBox);
  401.   Serial.println(F(" F"));
  402.   Serial.print(F("Current inside temp : "));
  403.  
  404.   Serial.print(tempIn);
  405.   Serial.println(F(" F"));
  406.   Serial.println();
  407. } // end printResults().
  408.  
  409. int8_t cToF(float c) {                    // Convert float C to int F.
  410.   return round((1.8 * c) + 32.0);
  411. } // end cToF().
  412.  
  413. int8_t getOneWireTemp(byte *str) {        // Get OneWire temp.
  414.   byte data[2];                           // Array to store data retrieved from sensor.
  415.   oneWire.reset ();
  416.   oneWire.select(str);
  417.   oneWire.write (0x44, 1);                // start conversion.
  418.   oneWire.reset ();
  419.   oneWire.select(str);
  420.   oneWire.write (0xBE);                   // Read scratchpad.
  421.  
  422.   for (byte i = 0; i < 2; i ++) {
  423.     data[i] = oneWire.read();             // Collect data.
  424.   } // end for.
  425.  
  426.   int16_t raw = (data[1] << 8) | data[0]; // Convert raw data to C.
  427.   return round((float)raw / 16.0);
  428. } //end getOneWireTemp().
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement