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
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:
- Camera node (ESP): https://github.com/KonradWohlfahrt/BirdhouseCameraSystemCameraNode
- 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
PCB COMPONENTS (1 Unit):
- 2x 1uF
- 1x 100nF
- 5x 5mm LED (850nm)
- 2x JST-XH vertical 4-pin
- 2x JST-XH vertical 2-pin
- 1x JST-XH vertical 3-pin (for external DS18B20)
- 1x 2N2222A transistor
- 1x 20k
- 1x 4.7k
- 5x 100r
- 1x 1k
- 2x DIP switch (optional)
- 1x ESP32-CAM module with OV3660 (or similar)
- 1x AM312 PIR sensor
- 1x DS18B20 (optional, doesn't work at the moment)
- 3D printed housing
ETHERNET (1 Unit):
- 1x W5500 Lite
- Perfboard
- Cables
- Heat-shrink tubing
- JST-XH crimping kit
SERVER:
- Raspberry Pi Zero 2W
- Raspberry Pi power supply
- USB-Micro LAN adapter
OTHER:
- 5V power supply (for camera nodes), planning on integrating PoE later
- LAN cables and power cables
- Network switch
The Idea and PCB
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
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
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:
- Open the Arduino IDE
- Go to File/Preferences
- Add the following URL under "Additional Boards Manager URLs"
- Open the Boards Manager, search for "ESP32" and install it
- Install the following libraries via the Library Manager:
- EthernetESP32
- ArduinoJSON
- DallasTemperature
- Open the Sketch "ESP32_Cam_Birdhouse_W5500.ino"
- Select the Board "AI Thinker ESP32-CAM"
- Set the right board settings and upload (pay close attention to select the right Partition Scheme, otherwise OTA might not work)
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:
- GPIOs
- Server IP address (your Raspberry Pi)
- 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
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
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
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:
- Secure the camera carefully (a vise with some rubber padding works well)
- Use a small file to carefully remove material from the side of the lens housing
- 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:
- Carefully remove the glue securing the lens using a sharp razor blade
- Unscrew the lens from the camera module
- Take extra care to avoid dust reaching the sensor
- 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
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.
- Cut a small piece of perfboard that fits underneath the LAN module and leaves space for XH connectors (4-pin and 2-pin)
- Solder the perfboard to the underside of the module
- Connect each pin of the module to the corresponding pins on the XH connectors with cables
- Add a bit of hot glue to secure the connections and reduce strain on the wires
- 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
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:
- Solder wires directly to the pins of the W5500 module
- Insulate each connection using heat-shrink tubing
- Bundle the wires together using a larger piece of heat-shrink
- 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
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:
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.
- Install Updates
- Clone the Server Repository Into a Folder
- Set Up Python Environment
- Test the Flask Application (return with CTRL+C)
- Create a systemd Service
Add the following content, save and exit:
And enable the system
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
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:
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:
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:
- A fixed 5V power supply (simple and reliable)
- 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:
If everything is working correctly, the devices should appear automatically on the main page. At this point, it’s a good idea to:
- Assign meaningful names to your devices
- Check the logs for any errors
- 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
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:
- Green: everything is working correctly
- Yellow: a log entry was recorded on the current day
- Red: the device has not been seen for more than a day
The settings menu on this page allows the user to:
- Download stored data (images, temperatures, etc.)
- Upload a device settings JSON file (containing IP addresses, camera settings, and other configuration data)
- 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:
- Open Stream
- View Logs
- 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:
- Data download
- General device configuration
- Camera settings
- Firmware updates
- 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
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:
- ESP32-CAM: 6.64€
- W5500 Lite: 4.15€
- AM312 PIR Sensor: 1.00€
- DS18B20 Temperature Sensor: 1.20€
- 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!