Intro
The theme of this project is spy nerd. I am a fan of spy novels, but I am not really into spying on people, so I thought I would have some fun experimenting with spying on my cats. That is about as nerdy as it gets.
I wanted to do something a bit original - something that you can't buy, which meant a nannycam was out. And of course since this is just for fun and not likely to be used regularly, the price needed to be low.
The simple description is several passive infrared sensors and a color sensor that can:
- detect cats or dogs
- detect people and differentiate them from animals
- detect the direction of travel of the animal
- identify which animal is detected
This sensor system requires an MCU to analyze the sensor data and deduce the above information.
To help the MCU, the sensors are arranged in a specific geometry. Two PIR sensors which will detect any hot body are used to figure out which direction the body is travelling by recognizing which one was triggered first. The third PIR sensor is aimed higher than pet height so it only detects people. This sensor can be used to confirm that the other sensors are seeing a pet and not a person. The final sensor is a color sensor that is used to figure out which pet is detected by their chacteristic color. We have 2 cats that have different coloring.
The Breadboard
The first video shows the electronics and sensors that are used in the system as well as how the electronics work to detect pet activity using a breadboard.
The Schematic
Here is the schematic of how the electronics are hooked up:
The 3D Printed Plastic Parts
This video shows all the plastic parts and 3D printed parts used to build the system:
This video walks through design of the 3D printed parts:
The Assembled System
This video shows the system completely wired up and working .... and of course being photobombed by a curious cat.
The Cat House PC Software
This cat house video shows the remote computer program that displays where the cats are. It has some footage of cats walking in the appropriate direction as well as cat images to indicate where they end up.
This VB6 program was whipped up in 20 minutes because the publishing deadline is imminent. It runs fine, although I was going to embed the video clips if I had time. Also in the interests of full disclosure, it is faking a bit because the cat color detection is not tuned properly yet.
The Firmware
Here is the arduino code for those who need to know....
/* This program detects cats and their direction of travel Doug Wong 2021-11-07 Hardware: 0.96" TFT 80x160 SPI ST7735 display TCS34725 color sensor HC-SR501 PIR sensors bluetooth arduino Pro Micro Hardware SPI Pins: * Arduino Pro Micro SCK=15, SDA=16 */ #include <Adafruit_GFX.h> // Include core graphics library #include <Adafruit_ST7735.h> // Include Adafruit_ST7735 library to drive the display #include <Wire.h> #include <Adafruit_TCS34725.h> //color sensor library // Declare pins for the display: #define TFT_CS 7 #define TFT_RST -1 // You can also connect this to the Arduino reset in which case, set this #define pin to -1! #define TFT_DC 5 // The rest of the pins are pre-selected as the default hardware SPI for Arduino Uno (SCK = 13 and SDA = 11) // Create color sensor Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_50MS, TCS34725_GAIN_1X); // Create display: Adafruit_ST7735 tft = Adafruit_ST7735(TFT_CS, TFT_DC, TFT_RST); #include <Fonts/FreeSerif18pt7b.h> // Add a custom font char btchar = 0; // bluetooth input character int cat; // cat ID : 0 = dark cat, 1 = light cat int event = 0; int lrevent = 0, rlevent = 0, rlfevent = 0, lrfevent = 0; char catevent; int catc; // cat color void setup() // Start of setup { // Display setup: // Use this initializer if you're using a 0.96" TFT tft.initR(INITR_MINI160x80); // Initialize a ST7735S chip, mini display tft.fillScreen(ST7735_BLACK); // Fill screen with black //tft.setRotation(0); // Set orientation of the display = portait tft.setTextWrap(false); // Display static text: tft.setTextSize(2); // Set text size. Goes from 0 (the smallest) to 20 (very big) tft.setCursor(0, 0); // Set position (x,y) tft.setTextColor(0x001F, ST7735_BLACK); // RED text with BLACK background tft.println("RED"); // Print a text or value tft.setCursor(0, 18); // Set position (x,y) tft.setTextColor(0x07E0, ST7735_BLACK); // GREEN text with BLACK background tft.println("GRN"); // Print a text or value tft.setCursor(0, 36); // Set position (x,y) tft.setTextColor(0xF800, ST7735_BLACK); // BLUE text with BLACK background tft.println("BLU"); // Print a text or value tft.setTextColor(ST7735_WHITE, ST7735_BLACK); // Set text white on black background // Color Sensor setup: pinMode(8, OUTPUT); // color sensor white LED //PIR Setup pinMode(18, INPUT); // right PIR pinMode(19, INPUT); // high PIR pinMode(20, INPUT); // left PIR Serial1.begin(9600); Serial1.println("Cat Spy"); } // End of setup void loop() // Start of loop { int lp, hp, rp; char cato = "N"; int color, r, g, b, c, colorTemp, lux, catl; int isf; // color scaling factor float sf; // color scaling factor float rd, gr, bl; // color components int rc, gc, bc; // corrected RGB rp = 0; lp = 0; rp = digitalRead(18); hp = digitalRead(19); lp = digitalRead(20); if (lp == 1) // left PIR detected { tft.fillRect(0, 60, 10, 10, 31); // light left } else { tft.fillRect(0, 60, 10, 10, 0); // light off left } if (hp == 1) // high PIR detected { tft.fillRect(35, 60, 10, 10, 31); // light high } else { tft.fillRect(35, 60, 10, 10, 0); // light off high } if (rp == 1) // rihgt PIR detected { tft.fillRect(70, 60, 10, 10, 31); // light right } else { tft.fillRect(70, 60, 10, 10, 0); // light off right } if (lp == 1 && event == 0) { event = 1; lrevent = 1; } if (rp == 1 && event == 0) { event = 1; rlevent = 1; } if (event == 1) { tft.setCursor(35, 80); // Set position (x,y) tft.println("E"); // event } if (lp == 1 && rlevent == 1) { rlfevent = 1; } if (rp == 1 && lrevent == 1) { lrfevent = 1; } if (rlfevent == 1 && lp == 0) { event = 0; rlfevent = 0; lrfevent = 0; rlevent = 0; lrevent = 0; tft.setCursor(10, 100); // Set position (x,y) if (catc == 0) { catevent = "L"; tft.println("L"); // left event } else { catevent = "l"; tft.println("l"); // left event } } if (lrfevent == 1 && rp == 0) { event = 0; lrfevent = 0; rlfevent = 0; rlevent = 0; lrevent = 0; tft.setCursor(60, 100); // Set position (x,y) if (catc == 0) { catevent = "R"; tft.println("R"); // right event } else { catevent = "r"; tft.println("r"); // right event } } digitalWrite(8, LOW); // turn on LED delay (10); tcs.getRawData(&r, &g, &b, &c); // tcs.getRGB(&rd, &gr, &bl); delay(110); digitalWrite(8, LOW); // turn off LED colorTemp = tcs.calculateColorTemperature(b, g, r); lux = tcs.calculateLux(r, g, b); if ((r > 255) || (g > 255) || (b > 255)) { r = r/8; g = g/8; b = b/8; } if ((r > 255) || (g > 255) || (b > 255)) { r = r/8; g = g/8; b = b/8; } if ((r > 255) || (g > 255) || (b > 255)) { r = r/8; g = g/8; b = b/8; } sf = 32/r; if ((r > g) && (r > b)) sf = 31/r; if ((g > r) && (g > b)) sf = 31/g; if ((b > r) && (b > g)) sf = 31/b; rc = int(r * sf); gc = int(g * sf); bc = int(b * sf); // bitWrite(color, 0, rc); // bitWrite(color, 5, gc); // bitWrite(color, 10, bc); color = rc + gc*32 + bc*2048; // display color catl = r + g + b; // cat luminance // if (catl > 400) if (rc > bc) { catc = 1; //Nugget } else { catc = 0; //Shmoopy } // Fill the digit space with background color: tft.fillRect(64, 0, 40, 60, ST7735_BLACK); // blank the values // Fill the color space with RGB color: tft.fillRect(0, 72, 80, 70, color); // Draw filled rectangle (x,y,width,height,color) // Write RGB values to the display: if (r < 10) { tft.fillRect(50, 0, 14, 16, 0); } if (r < 100) { tft.fillRect(64, 0, 14, 16, 0); } tft.setCursor(40, 0); // Set position (x,y) tft.println(rc); // Print RED value if (g < 10) { tft.fillRect(50, 17, 14, 16, 0); } if (g < 100) { tft.fillRect(64, 17, 14, 16, 0); } tft.setCursor(40, 18); // Set position (x,y) tft.println(gc); // Print GREEN value if (b < 10) { tft.fillRect(50, 34, 14, 16, 0); } if (b < 100) { tft.fillRect(64, 34, 14, 16, 0); } tft.setCursor(40, 36); // Set position (x,y) tft.println(bc); // Print BLUE value if (Serial1.available() > 0) { btchar = Serial1.read(); if (btchar == 'A') { Serial1.println(catevent); catevent = "N"; } } } // End of loop
Discussion
The project was a lot of fun even though it involved a lot more mechanical design than electronic design.
The PIR sensors and their shrouds work extremely well, very reliably detecting the cats and their direction. Both the PIR sensors and the color sensor are passive - they do not emit any harmful radiation or even ultrasonic noise.
The color sensor was a lot more problematic. Although the telephoto lens did a great job of allowing colors to be detected at a distance, it needs the lighting to be pretty consistent and the firmware needs to employ a lot of normalizing and other clever analysis techniques. Daylight is way different from artificial light and each light has a unique spectrum. The color sensor datasheet indicates it can do a decent job if you have a way of calibrating it. It might need a separate color sensor just to sort out what the ambient light composition is.
If you use one of these interesting color sensors, be prepared to mess around for quite a while tuning it to your application.
Training cats to walk in front of a sensor so you can tune up its performance is just wishful thinking. This made tuning up the color sensor extremely challenging, and it still isn't where it needs to be.
The mechanical design successfully attempted to utilize an empty filament spool as a stand, and now that I have a working way to adapt a spool to a shaft, I may find more uses for all my empty spools. The plastic shaft is from a Dollar Store toy.
Considering the system has an MCU, a color graphics display, four sensors and 8 custom plastic parts, the total cost of under $15 was a nice achievement.
It took some meticulous measurement work to ensure the color sensor chip was exactly where the lens was focusing the light, but 3D printing eliminated a lot of fiddling around with files to adjust position.
Overall I learned a lot and it is always fun to see how cats respond to new situations. I was very happy with the way the PIR sensors worked and that the telephoto lens worked so well with the color sensor.
Related Links:
Project14 | Spy Nerd: Win Spy Gadgets for Your Security or Spy Related Project!
Top Comments