Flexible Birdhouse Camera System for Multiple Nests

by Donut Studio in Circuits > Cameras

151 Views, 1 Favorites, 0 Comments

Flexible Birdhouse Camera System for Multiple Nests

Cover5.png
All_Modules2.jpg

Birdhouses are a great way to bring more wildlife into your garden. Birds add life with their songs, their stunning flights, and simply make the whole environment feel more alive. You’ve probably even heard the constant chirping of hungry chicks inside a nest. But how amazing would it be to actually look inside a birdhouse and see how many tiny birds are being fed?

That’s exactly where this project idea came from.

There are already many birdhouse cameras available online. Some come integrated into the birdhouse, others are sold as standalone modules, and most rely on Wi-Fi to transmit images. However, they tend to be quite expensive and none of them really suited my needs. I wanted a system that could be used across multiple birdhouses, which means each camera module has to be affordable and the overall setup needs to be flexible. Wi-Fi also didn’t seem like a reliable option, since signal strength can vary and data loss is always a concern.

So once again, I set out to build my biggest project yet: a complete birdhouse monitoring system for multiple nests while keeping costs as low as possible.

And here we are.

This system is now ready for you to build and install in your own birdhouses. I’m especially proud of it because it includes a custom-built Python Flask web server and a dedicated camera module. Everything runs locally in your network, collects incoming data, and presents it in a clean and user-friendly interface.

As always, the entire project is open-source, so you can adapt and modify it to fit your own needs. I’d love to see what you create with it and of course, what amazing bird photos you manage to capture.

The code is split across two GitHub repositories:

  1. Camera node (ESP): https://github.com/KonradWohlfahrt/BirdhouseCameraSystemCameraNode
  2. Web server (Flask): https://github.com/KonradWohlfahrt/BirdhouseCameraSystemServer

The custom PCBs used in this project were kindly provided by NextPCB - more on them later in the blog.

Without further ado, let’s get building!

Supplies

Parts_Camera_Node.jpg
W5500_1.jpg
RaspberryPi_Parts.jpg
PowerSupply.jpg
NetworkSwitch.jpg

PCB COMPONENTS (1 Unit):

  1. 2x 1uF
  2. 1x 100nF
  3. 5x 5mm LED (850nm)
  4. 2x JST-XH vertical 4-pin
  5. 2x JST-XH vertical 2-pin
  6. 1x JST-XH vertical 3-pin (for external DS18B20)
  7. 1x 2N2222A transistor
  8. 1x 20k
  9. 1x 4.7k
  10. 5x 100r
  11. 1x 1k
  12. 2x DIP switch (optional)
  13. 1x ESP32-CAM module with OV3660 (or similar)
  14. 1x AM312 PIR sensor
  15. 1x DS18B20 (optional, doesn't work at the moment)
  16. 3D printed housing

ETHERNET (1 Unit):

  1. 1x W5500 Lite
  2. Perfboard
  3. Cables
  4. Heat-shrink tubing
  5. JST-XH crimping kit

SERVER:

  1. Raspberry Pi Zero 2W
  2. Raspberry Pi power supply
  3. USB-Micro LAN adapter

OTHER:

  1. 5V power supply (for camera nodes), planning on integrating PoE later
  2. LAN cables and power cables
  3. Network switch

The Idea and PCB

Schematic_PCB_Amsel.png
Birdhouse Camera System Render Front.png
Birdhouse Camera System Render Back.png

Before getting into the build process, let’s take a closer look at the system and the PCB design. The project consists of two main components: the camera nodes and the server.

For the camera node, I quickly settled on the ESP32-CAM. It’s not only very affordable (around 6€ per module) and compact, but I already had some experience working with it. The ESP32-CAM is mounted on a custom PCB that adds several useful features and makes the overall system much easier to integrate.

First of all, illumination. Since it gets quite dark inside a birdhouse, I added a few IR LEDs so the camera can still capture images without disturbing the birds. When the module is not in use, it should enter a low-power mode and wake up when activity is detected. For this, I included a PIR sensor (AM312), which requires only a few passive components.

While the ESP32 does support Wi-Fi, it didn’t feel like the best choice for this application. With multiple birdhouses placed at varying distances, signal strength and reliability can quickly become an issue. Instead, I opted for a wired LAN connection. Using the W5500 Lite Ethernet module over SPI provides a much more stable and reliable communication link.

With hardly any pins left, I also added a DS18B20 temperature sensor to monitor the conditions inside the birdhouse. Unfortunately, this feature is not working yet due to pin conflicts. The preferred pin (IO0) is already used by the camera, and the alternative (IO16) is connected to the RAM IC. I’m hoping to resolve this via software in the future, but for now the feature remains unused. If you have an idea for a workaround, I’d love to hear it!

Another major feature of this system is OTA (over-the-air) firmware updates. Once the cameras are installed inside the birdhouses, accessing them physically becomes inconvenient. With OTA, new firmware can be uploaded easily over the network, making updates much more practical.

On the server side, a Raspberry Pi is the perfect fit. A power-efficient Raspberry Pi Zero 2 W handles all incoming data and user interactions. It provides more than enough performance for this application while keeping power consumption low. Since no graphical interface is needed, a lightweight, console-based operating system is sufficient.

The backend is built with a Python Flask application, which processes incoming data and presents it through a custom web interface. Users can view images, adjust camera settings, and even access a real-time stream from the devices.

With my newly acquired KiCad skills, I started designing the schematic and PCB. For some components, I had to create custom symbols and footprints. The design itself is fairly straightforward, essentially a refined version of what I had already tested on a prototyping board. I chose through-hole components, making the board easier to assemble, even for beginners.

At some point, the board needed a name. I might create smaller variants in the future for tighter spaces, so I named this initial version Amsel (German for blackbird), as it’s one of the most common birds here in Germany. Even though this system is actually used to take images of the Mauersegler (German for common swift).

With the design finalized, it was time to send the gerber file off to NextPCB and wait for the PCBs to arrive.

NextPCB

NextPCB.png
Platinen.jpg
All_Modules.jpg

Now a quick word about the sponsor of this project: NextPCB.

NextPCB is a company specializing in PCB prototyping and fabrication. They offer a wide range of services, from simple two-layer boards to more advanced designs, making them a great option for both hobbyists and more complex projects.

For projects like this one, using a custom PCB makes a huge difference. While a perfboard is perfectly fine for early prototyping, it quickly becomes impractical when building multiple modules. Soldering and managing all the connections by hand is not only time-consuming but also at risk for errors. A properly designed PCB results in a much cleaner, more reliable and professional solution.

This was my first time using NextPCB’s service, and the experience was very positive. The board quality is excellent, the turnaround time was short, and the pricing is very reasonable, especially when building multiple units like in this project.

If you’re planning to take your electronics projects beyond the prototype stage, getting custom PCBs manufactured is definitely worth considering.

Programming the ESP32 Cam Module

Programming.jpg

If you bought your ESP32-CAM together with a programming adapter, this step is fairly straightforward. First, make sure you have the Arduino IDE installed. Next, install support for ESP32 boards:

  1. Open the Arduino IDE
  2. Go to File/Preferences
  3. Add the following URL under "Additional Boards Manager URLs"
https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json
  1. Open the Boards Manager, search for "ESP32" and install it
  2. Install the following libraries via the Library Manager:
  3. EthernetESP32
  4. ArduinoJSON
  5. DallasTemperature
  6. Open the Sketch "ESP32_Cam_Birdhouse_W5500.ino"
  7. Select the Board "AI Thinker ESP32-CAM"
  8. Set the right board settings and upload (pay close attention to select the right Partition Scheme, otherwise OTA might not work)
CPU Frequency: "240MHz (WiFi/BT)"
Core Debug Level: "None"
Erase All Flash Before Sketch Upload: "Disabled"
Flash Frequency: "80MHz"
Flash Mode: "QIO"
Partition Scheme: "Minimal SPIFFS (1.9MB APP with OTA/128KB SPIFFS)"

Programmer: "Esptool"

The firmware has been tested with the OV2640 and OV3660 camera modules. If you are using a different camera, you may need to adjust the pin configuration and initialization settings in the code.

Before uploading, it’s worth taking a look at the "configuration.h" file. This allows you to customize important settings such as:

  1. GPIOs
  2. Server IP address (your Raspberry Pi)
  3. Timing parameters

You may need to adjust the server IP depending on your network setup. If you’re unsure, take a look at Step 10 first, where different connection options are explained.

Soldering the Camera Node

Soldering_Help.png
XH_Connections.png
Soldering_PIR.jpg
Soldering_Sockets_Back.jpg
Soldering_Done.jpg
Soldering_Modules.jpg

With the programming complete, it’s time to solder the PCBs.

Start with the smaller components first. Begin by soldering the resistors, followed by the transistor and the optional temperature sensor. Next, make sure to bridge all solder jumpers (JP1, JP2, JP4) with a small blob of solder to properly connect the corresponding parts of the circuit.

After that, solder the PIR motion sensor along with its capacitor.

The XH sockets should be soldered on the underside of the PCB. Then move on to the larger components: IR LEDs and bigger capacitors.

Finally, mount the ESP32-CAM. You can either use pin headers for easier replacement or solder it directly to the board. If you choose the second, adding a bit of insulation tape underneath is a good idea to prevent any short circuits.

And that’s it, the assembly is quite straightforward and doesn’t require much effort - it only takes a while if you have to solder ten modules ;)

Removing the LED

RemoveIRLED.png

The integrated flash LED on the ESP32-CAM is not very useful for this project. In fact, it would likely scare the birds away. That’s why we need to remove it.

The LED is located at the bottom right of the module. Since the pads are not easily accessible and I didn’t have a hot air station available, I removed it using a soldering iron. By heating the component and cutting it in half, this of course will destroy the LED in the process.

Once removed, the GPIO pin (IO4) that originally controlled the flash LED can now be repurposed to drive the IR LEDs.

Removing the IR Filter

Removing_Lens.jpg
Removing_IR_Filter.jpg
Removed_IR_Filter.jpg

Most camera modules come with an integrated IR filter. This filter ensures accurate colors, but it also blocks infrared light which means the camera won’t be able to see in the dark. To enable night vision with IR LEDs, the filter needs to be removed.

Depending on the module, the filter can be located in one of two places:

Option 1: Filter on Top of the Lens

In many cases (such as my OV3660 modules), the IR filter is mounted directly inside the lens. You don’t necessarily need to remove the lens. Instead:

  1. Secure the camera carefully (a vise with some rubber padding works well)
  2. Use a small file to carefully remove material from the side of the lens housing
  3. Once you reach the filter, gently push it out through the opening

For my modules, the filter was square-shaped and could be removed this way, sometimes even without completely destroying it.

Option 2: Filter Near the CMOS Sensor

In some variants, the IR filter is located behind the lens, closer to the sensor. In this case:

  1. Carefully remove the glue securing the lens using a sharp razor blade
  2. Unscrew the lens from the camera module
  3. Take extra care to avoid dust reaching the sensor
  4. Use the razor blade to remove or destroy the small round filter attached to the bottom of the lens

Note: Be very careful not to damage the camera sensor (avoid touching the sensor surface directly, work in a clean environment to prevent dust contamination)! This modification is irreversible!

The W5500 Lite Ethernet Module

W5500_Lite_Pinout.png
W5500_2.jpg
W5500_4.jpg
W5500_5.jpg
W5500_3.jpg
W5500_6.jpg
W5500_7.jpg

For the Ethernet connection, I chose the W5500 Lite module. It’s inexpensive (around 4€ per module), compact, and works reliably. Communication with the ESP32-CAM is handled via SPI at 3.3V. Only a single 3.3V and GND connection is required. There are two different ways to connect the module to the PCB, depending on how permanent and flexible you want the setup to be.

Method A:

This method requires a bit more effort but makes replacing cables much easier later on.

  1. Cut a small piece of perfboard that fits underneath the LAN module and leaves space for XH connectors (4-pin and 2-pin)
  2. Solder the perfboard to the underside of the module
  3. Connect each pin of the module to the corresponding pins on the XH connectors with cables
  4. Add a bit of hot glue to secure the connections and reduce strain on the wires
  5. Finally, crimp the cables and connect them to the PCB.

The cable length can vary depending on your setup. For example, you might want to mount the Ethernet module outside of the birdhouse. However, I wouldn’t recommend going beyond ~30 cm, as SPI is not designed for long-distance communication. For testing, I used short cables directly connected to the back of the PCB.

Note: Always double-check your wiring, especially the power lines! Swapping 3.3V and GND can damage the module.

Method B

W5500_V2_1.jpg
W5500_V2_2.jpg
W5500_V2_3.jpg
W5500_V2_4.jpg

This is the method I used for most of the boards, as it is quicker and requires fewer components. You will need: Wires, Heat-shrink tubing, XH crimp connectors

Steps:

  1. Solder wires directly to the pins of the W5500 module
  2. Insulate each connection using heat-shrink tubing
  3. Bundle the wires together using a larger piece of heat-shrink
  4. Crimp XH connectors onto the other ends and connect them to the PCB

Note: Using clamps or helping hands can make soldering the wires much easier.

Setting Up the Raspberry Pi

RaspberryPi_Housing.jpg

With the PCBs ready, it’s time to set up the Raspberry Pi to host the web server.

Use the Raspberry Pi Imager to flash the SD card with the latest Raspberry Pi OS. For this project, I used "Raspberry Pi OS Lite (64-bit)". During setup, enable SSH as it will make remote access much easier later.

Note: My default user is called "pi"

On the first boot, you may need an external monitor and keyboard to log in. Once logged in, run:

sudo raspi-config

I enabled auto-login, this way my Pi boots directly into the console. Optionally, set a hostname to make it easier to access the web interface via your network.

  1. Install Updates
sudo apt update
sudo apt upgrade -y
sudo apt install python3 python3-venv python3-pip git -y
  1. Clone the Server Repository Into a Folder
git clone https://github.com/KonradWohlfahrt/BirdhouseCameraSystemServer birdhouse
  1. Set Up Python Environment
cd birdhouse
python3 -m venv venv
source venv/bin/activate
pip install -r requirements.txt
  1. Test the Flask Application (return with CTRL+C)
gunicorn -c gunicorn_config.py app:app
  1. Create a systemd Service
sudo nano /etc/systemd/system/gunicorn.service

Add the following content, save and exit:

[Unit]
Description=Birdhouse Flask Server
After=network.target

[Service]
User=pi
WorkingDirectory=/home/pi/birdhouse
Environment="PATH=/home/pi/birdhouse/venv/bin"
ExecStart=/home/pi/birdhouse/venv/bin/gunicorn -c gunicorn_config.py app:app

Restart=always
RestartSec=5

[Install]
WantedBy=multi-user.target

And enable the system

sudo systemctl daemon-reload
sudo systemctl enable gunicorn
sudo systemctl start gunicorn
sudo journalctl --vacuum-time=7d # optional, keeps logs manageable
sudo systemctl status gunicorn


Once this is complete, your Raspberry Pi is configured as a server. The Flask web application will automatically start on boot and host the interface for your birdhouse system on your network.

The next and final step will show you how to connect the entire system.

Connect Everything

3D_Printed_Housing.jpg
CentralBox.jpg
CameraBox.jpg
IMG_20260407_233506_364.jpg
IMG_20260407_233507_278.jpg

There are two different ways to connect the LAN system:


Option A: Router-Based Network (Recommended)

This is the most straightforward setup and the one I personally use. All devices (ESP modules and Raspberry Pi) are connected to your router. The router automatically assigns a unique IP address to each device via DHCP. In this setup, you only need to define the IP address of the Raspberry Pi in the ESP firmware using the "staticServerIP" variable. Additionally, make sure to enable the following line in your code so the ESP uses this static server IP:

#define USE_STATIC_SERVER_IP

This ensures that all data is sent directly to the Raspberry Pi, rather than to the device that originally assigned the IP address (i.e., the router).


Option B: Raspberry Pi as DHCP Server

In this setup, all camera modules are connected directly to the Raspberry Pi, and the Pi itself connects to your network via Wi-Fi. Here, the Raspberry Pi acts as a DHCP server and assigns IP addresses to the ESP modules. There are many guides available online for setting this up, for example:

https://raspberrytips.com/dhcp-server-on-raspberry-pi/

In this case, you should disable the static server IP in your firmware:

//#define USE_STATIC_SERVER_IP

The ESP will then automatically send data to the DHCP server (the Raspberry Pi), so no manual IP configuration is required.


Final Assembly:

With everything prepared, it’s time to assemble the system. You can either 3D-print my or your own enclosure or simply mount the PCB inside your birdhouse. Then mount the W5500 Lite module and prepare the power connections. For power, you have a few options:

  1. A fixed 5V power supply (simple and reliable)
  2. A rechargeable battery with a solar panel (more flexible, but more complex)

For this project, I used a standard 5V / 5A power supply for simplicity. Connect all cables to the PCB (W5500 Lite, power cable), then link the Ethernet modules Raspberry Pi and your router using LAN cables connected through a network switch.


First Startup:

Start your Raspberry Pi first. Once the server is running, power up the camera modules. After a short time, you should be able to access the web interface in your browser using one of those options:

http://<pi-ip>:8000
http://<hostname>:8000

If everything is working correctly, the devices should appear automatically on the main page. At this point, it’s a good idea to:

  1. Assign meaningful names to your devices
  2. Check the logs for any errors
  3. Test key features such as image capture, streaming, and settings


Note: The birdhouses you see are for the common swift, they are a bit bigger than regular birdhouses. Fortunately, this gives extra room for all the cables and modules.

Webserver Navigation and Features

Screenshot (61).png
Screenshot (62).png
Screenshot (64).png
Screenshot (65).png
Screenshot (66).png
Screenshot (67).png
Screenshot (70).png
Screenshot (68).png

Most of the development time for this project went into the web server. It needed to be visually appealing, flexible, and capable of controlling all connected camera nodes. The page automatically refreshes every 60 seconds to display the latest data.


The Main Page

On the main page, the user is presented with the latest 32 images from all camera nodes, along with a storage usage indicator. The storage indicator is purely informational, no data is automatically deleted when the limit is reached. Instead, it serves as a reminder to back up and manually clear the database if necessary.

Below the image grid, all devices are listed and sorted by name. If no name has been assigned, the ESP’s MAC address is displayed instead. Each device also includes a status indicator:

  1. Green: everything is working correctly
  2. Yellow: a log entry was recorded on the current day
  3. Red: the device has not been seen for more than a day

The settings menu on this page allows the user to:

  1. Download stored data (images, temperatures, etc.)
  2. Upload a device settings JSON file (containing IP addresses, camera settings, and other configuration data)
  3. Delete all stored data


The Device Page

Clicking on a device opens a dedicated page for that specific node. The header displays key status information, along with controls such as:

  1. Open Stream
  2. View Logs
  3. Temperature indicator

Images are displayed in pages of 24. Navigation buttons allow the user to switch between pages and browse through the recorded data. The settings menu on this page provides additional options, including:

  1. Data download
  2. General device configuration
  3. Camera settings
  4. Firmware updates
  5. Delete all stored device data


Streaming and Firmware Updates

When starting a live stream or uploading new firmware (via a ".bin" file), the system first waits for the ESP32 to come online. Since the devices operate in a low-power mode, they periodically wake up to check for incoming requests. During this waiting period, a simple popup is shown. The user can cancel the operation at any time.


Logging

A logging system is implemented to help verify correct operation and identify potential issues. It provides insight into device activity and helps diagnose errors that may occur during runtime.

Enjoy

End.jpg

And that wraps up yet another project and again my biggest one.

There’s still plenty of room for improvement, and I’m planning to expand the system further in the future. Once the temperature sensor is fully working, I’d like to integrate a temperature graph into the web interface. And of course, there will likely be more adjustments and improvements as the system gets used in real-world conditions.

I’m also thinking about ways to simplify the overall setup. One idea is to experiment with Power over Ethernet (PoE), which would allow both power and data to be delivered through a single cable. Additionally, there is potential to reduce the PCB size even further. Switching to SMD components would help, and there are also alternative camera modules worth exploring, although that would likely increase the cost per unit.

For now, though, the current setup strikes a good balance. It’s affordable, flexible, and works reliably in testing. At the moment, I’m still waiting for birds to move in, but I’m optimistic that the system will perform just as well in real use.


Cost per Camera Node:

Here’s a rough breakdown of the cost per module:

  1. ESP32-CAM: 6.64€
  2. W5500 Lite: 4.15€
  3. AM312 PIR Sensor: 1.00€
  4. DS18B20 Temperature Sensor: 1.20€
  5. Other components (estimated): 2.00€

Total: ~15.00€ per node

Keep in mind that this does not include shared components such as LAN cables, the Raspberry Pi or the server hardware. In my case, I reused many parts I already had available.


Now it’s time to be patient and wait for the first birds to settle in. I’m really looking forward to seeing the first images captured by the system.

And with that, this blog comes to an end. I hope you found it interesting and helpful. If you have any questions or suggestions, feel free to reach out, I’ll do my best to help!