PageSourceSearch

https://www.benropple.com/2020/09/01/hummingbird-cam.html

html benropple.com collected 2026-10-07 19:04:37 UTC 19,577 bytes, 400 lines download raw bytes

1<!DOCTYPE html>
2<html lang="en">
3<head>
4  <meta charset="UTF-8">
5  <meta name="viewport" content="width=device-width, initial-scale=1.0">
6  <meta http-equiv="X-UA-Compatible" content="ie=edge">
7  <!--Favicon-->
8  <link rel="shortcut icon" href="/assets/icon.png" type="image/x-icon">
9
10  <!-- Font Awesome -->
11  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.9.0/css/all.css"
12    integrity="sha384-i1LQnF23gykqWXg6jxC2ZbCbUMxyw5gLZY6UiUS98LYV5unm8GWmfkIS6jqJfb4E" crossorigin="anonymous">
13
14  <!-- Spoqa Han Sans -->
15  <link href='//spoqa.github.io/spoqa-han-sans/css/SpoqaHanSans-kr.css' rel='stylesheet' type='text/css'>
16
17  <!-- CSS -->
18  <link rel="stylesheet" href="/assets/css/main.css">
19
20  <!-- OG Tag -->
21  
22  <meta name="title" content="Benjamin Ropple-Hummingbird Cam - Version 1" />
23  <meta name="author" content="Benjamin Ropple" />
24  <meta name="keywords" content="Quick Projects,ESP-32,ESP32-CAM,Camera,Hummingbirds" />
25  <meta name="description" content="A low-cost, motion-triggered camera" />
26  <meta name="robots" content="index,follow" />
27
28  <meta property="og:title" content="Benjamin Ropple-Hummingbird Cam - Version 1" />
29  <meta property="og:description" content="A low-cost, motion-triggered camera" />
30  <meta property="og:type" content="website, blog" />
31  <meta property="og:image"
32    content="https://www.benropple.com/assets/img/profile.jpg" />
33  <meta property="og:site_name" content="Benjamin Ropple" />
34  <meta property="og:url" content="https://www.benropple.com/2020/09/01/hummingbird-cam.html" />
35
36  <meta name="twitter:card" content="summary" />
37  <meta name="twitter:title" content="Benjamin Ropple-Hummingbird Cam - Version 1" />
38  <meta name="twitter:description" content="A low-cost, motion-triggered camera" />
39  <meta name="twitter:image"
40    content="https://www.benropple.com/assets/img/profile.jpg" />
41
42  <title>Benjamin Ropple-Hummingbird Cam - Version 1</title>
43</head>
44<body>
45  <div class="container">
46    
47
48<header>
49  <nav>
50    <ul>
51      
52      <!-- others -->
53      <a href="https://www.benropple.com">
54        <li class="current btn-nav">Main</li>
55      </a>
56      <a href="https://www.benropple.com/portfolio">
57        <li class="btn-nav">Portfolio</li>
58      </a>
59      <a href="https://www.benropple.com/tags">
60        <li class="btn-nav">Tags</li>
61      </a>
62      <!--<ul id="icons">
63            
64
65<li>
66  <a href="mailto:[email protected]">
67    <i class="fas fa-envelope"></i>
68  </a>
69</li>
70
71
72
73<li>
74  <a href="https://www.linkedin.com/in/benjamin-ropple-66aaa1124/" target="_blank">
75    <i class="fab fa-linkedin"></i>
76  </a>
77</li>
78
79
80
81<li>
82  <a href="https://github.com/bropple" target="_blank">
83    <i class="fab fa-github"></i>
84  </a>
85</li>
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102      </ul>-->
103      
104    </ul>
105  </nav>
106</header>
107
108<div id="post">
109  <section class="post-header">
110    <h1 class="title">Hummingbird Cam - Version 1</h1>
111    <p class="subtitle">A low-cost, motion-triggered camera</p>
112    <p class="meta">
113      September 1, 2020
114    </p>
115  </section>
116  <section class="post-content">
117    <p>The Hummingbird Cam is a motion-triggered camera, featuring an ESP32-CAM development board and a passive infrared sensor.</p>
118
119<p><img src="/assets/img/HummingbirdCam/hummbirddeployed.jpg" alt="Hummingbird Camera" class="width-55" /></p>
120<center> Hummingbird Cam in operation. </center>
121
122<h2> Inspiration </h2>
123<p>Since May 2020, I have observed the hummingbirds that come to drink from the feeders set up around my house. I was able to take some decent pictures of them with a DSLR:</p>
124
125<p><img src="/assets/img/HummingbirdCam/BackyardHummBirbs.jpg" alt="Hummingbirds" class="width-85" /></p>
126<center>Left: Male Ruby-Throated Hummingbird. Right: Female Ruby-Throated Hummingbird.
127<br />
128Photos taken with a Nikon D90 DSLR camera.
129</center>
130
131<p><br /></p>
132
133<p>While I am able to take high-quality pictures of the hummingbirds with a normal camera, I have to wait for them to appear and manually take a photo each time. I would also sometimes startle the hummingbirds if I got too close, causing them to fly away. This is when I came up with the idea of using a motion-triggered camera. A motion-triggered camera would be able to take pictures of the hummingbirds up close without disturbing them. Products like this exist already for taking pictures of animals (trail cams), but that would take the fun out of building one.</p>
134
135<p><br /></p>
136
137<h2> Components </h2>
138<p>After doing some research online, I found components that would help me achieve this goal. The following section describes the devices and parts I used to build the Hummingbird Camera.</p>
139
140<p><br /></p>
141
142<h3> ESP32-CAM </h3>
143
144<p><img src="/assets/img/HummingbirdCam/esp32cam.jpg" alt="ESP32-CAM module" class="width-35" /></p>
145<center> The ESP32-CAM development board. </center>
146
147<p><br /></p>
148
149<p>The ESP32-CAM is a development board created specifically for use with a camera module. It uses the ESP32-S microcontroller developed by Espressif Systems. The microcontroller itself operates on 3.3V, but the development board has a built-in voltage regulator to convert a 5V input to the required 3.3V. Some of its specifications are listed below:</p>
150
151<figure class="highlight"><pre><code class="language-html" data-lang="html">- Dual-core 32-bit microprocessor, with adjustable clock speed from 80MHz to 240MHz
152- 520kB RAM + 4MB PSRAM
153- ULP co-processor
154- WiFi and Bluetooth connectivity
155- Built-in SD card slot
156- ZIF connector for camera module</code></pre></figure>
157
158<p>Detailed specifications for the ESP32-S microcontroller can be found in <a href="https://www.es.co.th/Schemetic/PDF/ESP32.PDF">its datasheet</a>.</p>
159
160<p><br /></p>
161
162<p>The ESP32-CAM comes with an OV2640 camera module, a 2MP camera that supports a maximum resolution of 1632x1232. The picture settings can be modified in software, which can change the brightness, exposure, saturation, etc.</p>
163
164<p><br /></p>
165
166<p>The ESP32-CAM can enter a deep-sleep state, where it only draws 20μA-150μA depending on the usage of the ULP coprocessor. The ESP32-CAM can wake up from deep sleep using an external wakeup <a href="https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/system/sleep_modes.html">as described on Espressif’s website</a>.</p>
167
168<h3> HC-SR501 Passive Infrared Sensor </h3>
169
170<p><img src="/assets/img/HummingbirdCam/PIR.jpg" alt="PIR Module" class="width-45" /></p>
171<center> HC-SR501 Module. </center>
172
173<p><br /></p>
174
175<p>The HC-SR501 passive infrared (PIR) sensor is used to detect motion. It accepts an input voltage range from 5V to 20V and outputs a 3.3V signal when it detects motion. The time the signal is high and the detection range can be adju
175sted using the potentiometers on the board. The module also has two modes: single-trigger mode, where the output pulses for the set duration, or continuous mode, where the output stays high as long as it detects movement.</p>
176
177<p><br /></p>
178
179<h3> 18650 Lithium-Ion Battery</h3>
180
181<p><img src="/assets/img/HummingbirdCam/18650.jpg" alt="18650 Battery" class="width-40" /></p>
182<center> An 18650 battery. </center>
183<p><br />
184<br /></p>
185
186<p>I chose to use an 18650 battery from an old Raspberry Pi handheld project I worked on back in 2017. The one I used has a 2000mAh capacity. 
187<br /></p>
188
189<p><img src="/assets/img/HummingbirdCam/18650shield.jpg" alt="18650 Shield" class="width-45" /></p>
190<center> 18650 battery shield. </center>
191<p><br />
192<br /></p>
193
194<p>Additionally, I used a modified 18650 Raspberry Pi shield from the same project, which essentially manages the power usage of the battery. It allows the battery to recharge from a 5V input and it steps up the 3.7V from the battery to a 5V output.</p>
195
196<p><br /></p>
197
198<h3> Crayon Box </h3>
199
200<p><img src="/assets/img/HummingbirdCam/CrayonBox.jpg" alt="Crayon Box" class="width-45" /></p>
201<center> A "Super Stacker" crayon box. </center>
202
203<p><br /></p>
204
205<p>Believe it or not, the case is actually a crayon box. I used this as the project’s enclosure because it’s small, readily available, and extremely low-cost: they’re only $1 each at the local supermarket. It’s also clear enough to take decent pictures through it while still offering some degree of protection from the elements.</p>
206
207<p><br /></p>
208
209<p>I tested the water resistance of the box by placing paper inside, closing it, and putting it in the shower for a few minutes. It keeps out most of the water on its own, but some drops managed to slip in. This is mitigated by either sealing or covering the edges with each use. Covering each edge from front to back with plastic wrap and tape keeps all droplets out. The seal can also be made tighter by placing a thick tape around the edge, where the lid touches the case. The case can’t withstand being submerged for very long, so no underwater pictures.</p>
210
211<p><br /></p>
212
213<h3> Various Other Parts </h3>
214<p>To hold everything together, I used a solder board, female and male header pins, wires, and hot glue. A male USB cable was tucked inside and can be extended outside of the case to recharge the battery. A small switch was added to turn the device on and off. A Dremel was used to make a hole in the lid for the sensor to fit through.</p>
215
216<p><img src="/assets/img/HummingbirdCam/hummcaminside.jpg" alt="Inside" class="width-55" /></p>
217<center> The completed Hummingbird Cam - version 1. </center>
218<p><br />
219I initially used zip-ties to hold the camera in place, but I cut two slots on either side of the case later on for reusable Velcro straps.</p>
220
221<p><br /></p>
222
223<p>There is a header on the left side of the solder board for connecting a serial programmer, and a jumper for grounding IO-0 to put the ESP32-S into download mode. Programming the ESP32-CAM is tedious, as the jumper has to be moved back and forth when testing new code.</p>
224
225<p><br /></p>
226
227<p>Note: I used a BJT circuit to pull a pin on the ESP32-CAM to ground whenever the PIR module triggered, but I later learned that I didn’t need it; the software does support wakeup from a HIGH signal. I may still be able to use the circuit for a future purpose that I’ll discuss later.</p>
228
229<p><br /></p>
230
231<h2> Programming </h2>
232<p>The Arduino IDE is used to program the ESP32-CAM, with an additional extension provided by Espressif. The code is written in C++. An external serial programmer is required to program the board, as it doesn’t have a USB port. The code I used for this can be found on <a href="https://github.com/bropple/HummingbirdCam">my Github profile</a>.</p>
233
234<p><br /></p>
235
236<h2> Results </h2>
237
238<p><img src="/assets/img/HummingbirdCam/camsetup.jpg" alt="Camera Setup" class="width-55" /></p>
239<center> The placement of the Hummingbird Cam - before the addition of Velcro straps. </center>
240<p><br /></p>
241
242<p>The Hummingbird Cam functioned as intended when set up next to a hummingbird feeder. It sometimes triggers from the wind blowing the feeder and nearby plants around, but in most cases it captures the intended subjects. Below are some of the best photos taken so far:</p>
243
244<p><br /></p>
245
246<p><img src="/assets/img/HummingbirdCam/hummhover.jpg" alt="Hummingbird1" class="width-75" /></p>
247<center> Hovering hummingbird. </center>
248<p><br />
249<img src="/assets/img/HummingbirdCam/hummhoverleft.jpg" alt="Hummingbird2" class="width-75" /></p>
250<center> A hummingbird approaching from the left. </center>
251<p><br />
252<img src="/assets/img/HummingbirdCam/hummhoverright.jpg" alt="Hummingbird3" class="width-75" /></p>
253<center> A hummingbird looking away from the camera. </center>
254<p><br />
255<img src="/assets/img/HummingbirdCam/hummbackperch.jpg" alt="Camera Setup" class="width-75" /></p>
256<center> A perched hummingbird facing away from the camera. </center>
257<p><br />
258<img src="/assets/img/HummingbirdCam/hummbehind.jpg" alt="Camera Setup" class="width-75" /></p>
259<center> A hummingbird hovering right in front of the camera. </center>
260<p><br />
261<img src="/assets/img/HummingbirdCam/hummface.jpg" alt="Camera Setup" class="width-75" /></p>
262<center> A hummingbird facing the camera from the opposite side of the feeder. </center>
263<p><br />
264<img src="/assets/img/HummingbirdCam/hummface2.jpg" alt="Camera Setup" class="width-75" /></p>
265<center> A perched hummingbird, still flapping its wings. </center>
266<p><br /></p>
267
268<p>There were also a couple of interesting moments captured by the camera, but they are less clear:</p>
269
270<p><br /></p>
271
272<p><img src="/assets/img/HummingbirdCam/weirdhumm1.jpg" alt="Camera Setup" class="width-75" /></p>
273<center> Two hummingbirds fighting. </center>
274<p><br />
275<img src="/assets/img/HummingbirdCam/weirdhumm2.jpg" alt="Camera Setup" class="width-75" /></p>
276<center> A hummingbird sticking its tongue out. </center>
277<p><br /></p>
278
279<p>The Hummingbird Cam works reasonably well, but there are still a few issues to work out. The brightness and saturation in some of the photos are far too high. This seems to have the worst impact during the day, when the sun shines brightest on that side of the house. It takes better photos during the afternoon and evening. These parameters can be adju
279sted to an extent in software.</p>
280
281<p><br /></p>
282
283<p>The case used to protect the electronics also adds a slight blue tint to the images. This can easily be corrected on a computer, but it is possible to do this on the ESP32-CAM right after taking a picture.</p>
284
285<p><br /></p>
286
287<h2> Future Work </h2>
288<p>I’ve looked into adding more features to the Hummingbird Cam, as it is pretty simple in its current state. Some of the features I’d like to add are listed below:</p>
289
290<figure class="highlight"><pre><code class="language-html" data-lang="html">1. Power usage monitoring
2912. Photos with the proper timestamp
2923. A hardware user interface
2934. A Bluetooth interface that can be accessed through an Android app
2945. Temperature sensors, for inside and outside the enclosure
2956. A better charging port for the 18650 shield</code></pre></figure>
296
297<p>Implementing these features using only the ESP32-CAM to control all the peripherals may present an issue. Below is a schematic of the ESP32-CAM development board:</p>
298
299<p><img src="/assets/img/HummingbirdCam/esp32camdiag.webp" alt="ESP32-CAM Schematic" class="width-95" /></p>
300<center> The schematics of the ESP32-CAM module. </center>
301<p><br /></p>
302
303<p>The top right-hand corner of the schematics shows the two 8-pin headers on either side of the module. Every pin is either designated for power, ground, download mode, or a signal line for the SD card and camera. If I used these pins for anything else, it would potentially interfere with using the SD card. The only pins that won’t interfere with the camera and SD card are U0TXD and U0RXD: the pins used for serial communication. Since I want to use both the SD card and the camera, I want to avoid connecting anything else to those pins, except HS2_DATA3 as the ext0 RTC wakeup pin.</p>
304
305<p><br /></p>
306
307<p><img src="/assets/img/HummingbirdCam/ardunano.jpg" alt="Arduino Nano" class="width-45" /></p>
308<center> An Arduino Nano, an ATmega328p development board. </center>
309<p><br /></p>
310
311<p>I’ve contemplated adding an Arduino Nano (with some bidirectional level shifters) inside the case as a companion device. The Arduino would be able to exchange information with the ESP32-CAM using serial communication on U0TXD and U0RXD, and would consume less power than leaving WiFi or Bluetooth on.</p>
312
313<p><br /></p>
314
315<p>The Arduino could also have an extra benefit: It can eliminate the need for an external programmer, since it can be programmed as one. If the BJT pull-down circuit is connected to an Arduino output at the base, and the collector output is changed to pull down IO-0 on the ESP32-CAM, the Arduino could ground the download pin on the ESP32-CAM automatically before programming.</p>
316
317<p><br /></p>
318
319<p><img src="/assets/img/HummingbirdCam/oledtemp.jpg" alt="Parts" class="width-40" /></p>
320<center> Left: A 0.96" i2c OLED display. Right: A DS18B20 one-wire temperature sensor. </center>
321
322<p><img src="/assets/img/HummingbirdCam/RTCbutton.jpg" alt="More Parts" class="width-40" /></p>
323<center> Left: A DS3231 RTC module. Right: Soft push buttons. </center>
324<p><br /></p>
325
326<p>When not being used to program the ESP32-CAM, the Arduino can be switched to a different mode to support peripherals like a small i2c display, an i2c real-time clock (RTC), some one-wire temperature sensors, and several buttons. The Arduino can read the voltage level of the battery and the output of a Hall Effect sensor using its ADC inputs. The Arduino could then communicate with the ESP32-CAM over the same serial pins it uses to program it. When not in use, the Arduino can enter deep sleep mode, similarly to the ESP32-CAM.</p>
327
328<p><br /></p>
329
330<p>As of now, I think I am limited to a single GPIO pin for wakeup, since ext1 wakeup mode uses pins that aren’t exposed on this board. To get around this, I can have the Arduino send a code over serial as it triggers the wakeup and have the ESP32-CAM enter a different mode as it receives it. This would only need a few milliseconds to process, and would be sufficient to know the difference between a motion trigger wakeup and an Arduino wakeup.</p>
331
332<p><br /></p>
333
334<p>The WiFi capability of the ESP32-CAM could be used to update its own internal RTC at periodic intervals or after receiving a command; however, its RTC is not very accurate and has no battery backup. It would be better in my case to use a more accurate RTC module with a small battery backup to store time information, and only update it as needed.</p>
335
336<p><br /></p>
337
338<p>These proposed additions require testing to see if it will work. I already have all the parts I need to get this working, so a future post will describe how this goes.</p>
339
340<p><br /></p>
341
342<h2> Device Schematics </h2>
343<p>The schematics are pretty simple for this version:
344<img src="/assets/img/HummingbirdCam/HummingbirdCamV1.jpg" alt="Hummingbird Cam Schematics" class="width-95" /></p>
345<center> The schematics for the Hummingbird Cam - Version 1. </center>
346
347<p><br /></p>
348
349<h2> Conclusion </h2>
350<p>This post has described the purpose, programming, construction, and deployment of the Hummingbird Cam. It succeeded in capturing many interesting photos of hummingbirds. I hope to improve the device so I can use it in different situations and to photograph other kinds of animals. I will make a post describing the features I add when they’re finished. Thanks for reading!</p>
351
352  </section>
353</div>
354
355<div id="top" class="top-btn" onclick="moveTop()">
356  <i class="fas fa-chevron-up"></i>
357</div>
358
359<!-- Disqus -->
360
361
362<!-- Footer -->
363<footer>
364  <div class="footer">
365    Page content: Copyright © 2020
366    <a href="https://github.com/bropple">Benjamin Ropple</a>.
367    Powered by Jekyll using modified
368    <a href="https://github.com/naye0ng/Grape-Theme">Grape Theme.
369  </div>
370</footer>
371
372
373<script>
374  var lastScrollTop = 0;
375  window.onscroll = function () {
376    var st = document.body.scrollTop || document.documentElement.scrollTop;
377    if (st > 250) {
378      document.getElementById("top").style.display = "block"
379      if (st > lastScrollTop) {
380        document.getElementById("top").style.opacity = 0
381      } else {
382        document.getElementById("top").style.opacity = 1
383      }
384    } else {
385      document.getElementById("top").style.opacity = 0
386      if (st > lastScrollTop) {
387        document.getElementById("top").style.display = "none"
388      }
389    }
390    lastScrollTop = st <= 0 ? 0 : st;
391  }
392  function moveTop() {
393    document.body.scrollTop = 0
394    document.documentElement.scrollTop = 0
395  }
396</script>
396
397  </div>
398</body>
399
400</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.