/* * This board code will do all the communication and data processing * * As input I use a ultrasonic sensor to detect if a cat has entered, has left or is in the litterbox itself * Second input will be the bluethoot-command via app for manuel cleaning and resetting values * * As output I use two servo-motors for locking the door of the litterbox - so that the cat cant enter whle cleaning * Second output will be the Steppermotors for lifting the strainer up and down aswell as rtating the strainer for cleaning * Third output will be the bluethoot connection to the app, to communicate and display all informations about the cats * * * For savin the Data I use a SD Card module * For traking the time the user have to set up the date and time first time the app is used?? * * As ultrasoni sensor I will use the HC-SR04 * As servo I will use the Sg90 servo motors * As Steppermotor i will use Nema 17 * As Steppermotrodriver I will use A4988 * As bluetooth module I use a HC-05 or HC-06 * As SD-Card-Module I use ... * * After inserting the litter in the litterbox I will level the loadcell via command * After this the loadcell will measure the weight of my cats every time they enter * After leaving the litterbox, if they bin in there for a set amount of time, the automatic cleaning wil start * First the Servomotor will lock the door * Then the strainer will lift down and the rotate 3 times in order to clean the toilett * After lifting up the loadcell will calculate the remaining amount of litter and then level itself again * Then the door will unlock * * Meanwhile all the data will be collected, processed and stored on the SD Card as JSON file * * Everytime the User opends the app he can send a command by pressing a button, to get the colted data * The user can manualy start a cleaning process or deactive the system for cleaning or switching the litter * Also the user can level the loadcell manualy after ne litter was inserted * * Made by Jonas van Hagen as FabAcademy Final 2021 * */ #include #include //#include #include #include #include #include #define TRIG_PIN 17 //Pin PC2 #define ECHO_PIN 16 //Pin PC3 #define STEP_PIN 2 //Pin PD2 #define DIR_PIN 3 //Pin PD3 #define STEP2_PIN 15 //Pin PC1 #define DIR2_PIN 14 //Pin PC0 #define END_PIN 6 //Pin PD6 const int HX711_dout = 9; //mcu > HX711 dout pin const int HX711_sck = 8; //mcu > HX711 sck pin Servo servoLeft; HX711_ADC LoadCell(HX711_dout, HX711_sck); File myFile; virtuabotixRTC myRTC(19, 18, 7); long duration; int distance; unsigned long t = 0; const int chipSelect = 10; bool catDetected = false; bool doorLocked = false; bool catWasInLitterbox = false; bool strainerStateUp = false; int travelDistanceUp = 100; //100mm for the strainer to go up int stepsPerMilimeter = 40; float litterWeight = 0; float catWeight = 0; int cleanCycles = 3; int beginTimeMinute = 0; //start minute cat enters litterbox int endTimeMinute = 0;//end minute of cat in litterbox int timeInLitterbox = 0; int cleaningThresholdTime = 2; //threshold for the time the cat needs to be in the litterbox so it starts cleaning float calibrationValue; // calibration value (see example file "Calibration.ino") String dataString = ""; /* ######################################################################################################################################################################################################################################################*/ void setup() { // put your setup code here, to run once: //Wire.begin(); //start i2c (required for connection to Clocl) Serial.begin(9600); // for bluetooth Serial.println("CatToilette is active\n"); myRTC.setDS1302Time(00, 05, 20, 6, 12, 6, 2021); //only for the first time //Rtc.Begin(); servoLeft.attach(5); //Pin PD5 pinMode(TRIG_PIN, OUTPUT); pinMode(ECHO_PIN, INPUT); pinMode(STEP_PIN, OUTPUT); pinMode(DIR_PIN, OUTPUT); pinMode(STEP2_PIN, OUTPUT); pinMode(DIR2_PIN, OUTPUT); pinMode(END_PIN, INPUT); digitalWrite(END_PIN, HIGH); //Codew for Loadcell LoadCell.begin(); calibrationValue = 86.4; // uncomment this if you want to set the calibration value in the sketch unsigned long stabilizingtime = 2000; LoadCell.start(stabilizingtime, false); LoadCell.setCalFactor(calibrationValue); if (!SD.begin(chipSelect)) { Serial.println("Card failed, or not present"); }else Serial.println("card initialized."); myRTC.updateTime(); File dataFile = SD.open("data.txt", FILE_WRITE); if (dataFile) { dataFile.println("Die Katzentoilette wurde neu gestarte am:\n"); dataFile.print(myRTC.seconds); dataFile.print(":"); dataFile.print(myRTC.minutes); dataFile.print(":"); dataFile.print(myRTC.hours); dataFile.print("/"); dataFile.print(myRTC.dayofmonth); dataFile.print("."); dataFile.print(myRTC.month); dataFile.print("."); dataFile.print(myRTC.year); dataFile.close(); } // Move Strainer to wait position digitalWrite(DIR2_PIN, HIGH); //set to low if moving in wrong direction for(int j=0;j<105;j++){ digitalWrite(STEP2_PIN, HIGH); delay(25); digitalWrite(STEP2_PIN, LOW); delay(25); } Serial.println("Strainer moved to 90 degree\n"); //Move strainer UP until endstop detected digitalWrite(DIR_PIN, LOW); while(strainerStateUp == false){ digitalWrite(STEP_PIN, HIGH); delay(5); digitalWrite(STEP_PIN, LOW); delay(5); if(digitalRead(END_PIN) == 0){ strainerStateUp = true; break; } } Serial.println("Strainer moved up\n"); } /* ######################################################################################################################################################################################################################################################*/ void loop() { // put your main code here, to run repeatedly: //check if cat is currently in the litterbox: myRTC.updateTime(); catDetected = checkLitterbox(); if(catDetected == true){ catWasInLitterbox = true; Serial.println("Cat detected\n"); myRTC.updateTime(); beginTimeMinute = myRTC.minutes; catWeight = measureCatWeihgt(); File dataFile = SD.open("data.txt", FILE_WRITE); if (dataFile) { dataFile.println("Die Katze wiegt:"); dataFile.println(catWeight); dataFile.println("Gewogen am:"); dataFile.print(myRTC.seconds); dataFile.print(":"); dataFile.print(myRTC.minutes); dataFile.print(":"); dataFile.print(myRTC.hours); dataFile.print("/"); dataFile.print(myRTC.dayofmonth); dataFile.print("."); dataFile.print(myRTC.month); dataFile.print("."); dataFile.print(myRTC.year); dataFile.close(); } Serial.print("Cat weight:"); Serial.print(catWeight); Serial.println("\n"); //Code for geting Time and Date /* * t.mon formonth * t.mday for day * t.year for year * t.hour for hour * t.min for minute * t.sec for second */ //Converting all data to one string: //Serial.println(myRTC); //Code for Storing Time, Date and Weight in File dataFile = SD.open("data.txt", FILE_WRITE); if (dataFile) { dataFile.println(myRTC.year); dataFile.close(); } //Check that if cat is still in litterbox: while(catDetected == true) { Serial.println("Cat is in Litterbox\n"); catDetected = checkLitterbox(); delay(500); } Serial.println("Cat has left???\n"); for(int i=0;i<30;i++){ //Checks again for 30 Seconds if the cat returns, if not, starts cleaning process catDetected = checkLitterbox(); if(catDetected == true){ break; } delay(1000); //Check for 30 seconds } //Code for when the Cat leaves: if(catDetected == false && catWasInLitterbox == true){ catWasInLitterbox = false; //Getting time how long cat was in litterbox myRTC.updateTime(); endTimeMinute = myRTC.minutes; timeInLitterbox = calcTimeInLitterbox(); Serial.println(timeInLitterbox); //Code for storing Time in Litterbox File dataFile = SD.open("data.txt", FILE_WRITE); if (dataFile) { dataFile.println("Die Katze war so lange im Klo:"); dataFile.println(timeInLitterbox); dataFile.close(); } //Increase ounter of litterbox entries total and daily //Code needs to be HERE!!! //If time was higher than threshold, start cleaning //if(timeInLitterbox >= cleaningThresholdTime){ lockDoor(); Serial.println("Door Locked\n"); delay(1000); strainerDown(); Serial.println("Strainer is moving down\n"); delay(1000); if(strainerStateUp == false){ Serial.println("Cleaning started\n"); strainerClean(); delay(1000); //Code for measuring the remaining litter inside HERE!!! } strainerUp(); Serial.println("Strainer is moving up\n"); delay(1000); unlockDoor(); Serial.println("Door unlocked\n"); Serial.println("Litterbox has been cleaned.\n"); //} //Code for tara scale //unsigned long stabilizingtime = 2000; //LoadCell.start(stabilizingtime, true); //LoadCell.setCalFactor(calibrationValue); catWasInLitterbox = false; } } //check if data has been requested by the app: char blueToothVal; //Value recieved via BT if(Serial.available()){ blueToothVal = Serial.read(); Serial.println(blueToothVal); } /* * Code for Sending different Data, based on the input of the user * * 1 = Status OK? * 2 = Last saved Data = Last Cat Enter / Last cleanup / Last weight etc. * 3 = Data of last 7 days * 4 = Data of Last 30 Days * 5 = Manual Cleaning -> Checking if Cat is in there, if so, wait untl cat leaves * 6 = Tara Scale - after filling in new litter * (7 = Set Threshold for minimum Time for cleaning Litterbox) */ if(blueToothVal == "1" ){ }else if(blueToothVal == "2" ){ Serial.print("Last data:\n"); Serial.print(dataString); }else if(blueToothVal == "3"){ }else if(blueToothVal == "4"){ }else if(blueToothVal == "5"){ }else if(blueToothVal == "6"){ }else if(blueToothVal == "7"){ } } /* ######################################################################################################################################################################################################################################################*/ bool checkLitterbox(){ digitalWrite(TRIG_PIN, LOW); delayMicroseconds(2); digitalWrite(TRIG_PIN, HIGH); delayMicroseconds(10); digitalWrite(TRIG_PIN, LOW); duration = pulseIn(ECHO_PIN, HIGH); distance = duration*0.034/2; //Serial.println(distance); if(distance < 45){ //30cm has to be changed after installing the sensor return true; } else return false; } /* ######################################################################################################################################################################################################################################################*/ void unlockDoor(){ servoLeft.write(90); } /* ######################################################################################################################################################################################################################################################*/ void lockDoor(){ servoLeft.write(270); } /* ######################################################################################################################################################################################################################################################*/ void strainerUp(){ digitalWrite(DIR_PIN, LOW); while(strainerStateUp == false){ digitalWrite(STEP_PIN, HIGH); delay(5); digitalWrite(STEP_PIN, LOW); delay(5); if(digitalRead(END_PIN) == 0){ strainerStateUp = true; break; } } } /* ######################################################################################################################################################################################################################################################*/ void strainerDown(){ digitalWrite(DIR_PIN, LOW); while(strainerStateUp == false){ digitalWrite(STEP_PIN, HIGH); delay(5); digitalWrite(STEP_PIN, LOW); delay(5); if(digitalRead(END_PIN) == 0){ strainerStateUp = true; break; } } digitalWrite(DIR_PIN, HIGH); for(int i=0;i