<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Scarey's Tech]]></title><description><![CDATA[Cool, Geeky Stuff]]></description><link>https://tech.scarey.net/</link><image><url>https://tech.scarey.net/favicon.png</url><title>Scarey&apos;s Tech</title><link>https://tech.scarey.net/</link></image><generator>Ghost 5.68</generator><lastBuildDate>Fri, 17 Apr 2026 23:59:51 GMT</lastBuildDate><atom:link href="https://tech.scarey.net/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[Kitty 3000 Firmware]]></title><description><![CDATA[<p>I was sad to notice in a comment on <a href="https://www.thingiverse.com/thing:5595111/comments?ref=tech.scarey.net" rel="noreferrer">Thingiverse</a> that the instructional video for the Kitty 3000 pet treat dispenser was no longer available so I cleaned up my micropython code a bit and am making it available here.</p><p>About 2 years ago I came across the <a href="https://www.elektormagazine.com/news/kitty-3000-cat-treat-dispenser?ref=tech.scarey.net" rel="noreferrer">Kitty 3000</a></p>]]></description><link>https://tech.scarey.net/kitty-3000-backend/</link><guid isPermaLink="false">6731758848a92700011ee548</guid><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Tue, 12 Nov 2024 00:12:29 GMT</pubDate><media:content url="https://tech.scarey.net/content/images/2024/11/AI-Kitty-3000-1.png" medium="image"/><content:encoded><![CDATA[<img src="https://tech.scarey.net/content/images/2024/11/AI-Kitty-3000-1.png" alt="Kitty 3000 Firmware"><p>I was sad to notice in a comment on <a href="https://www.thingiverse.com/thing:5595111/comments?ref=tech.scarey.net" rel="noreferrer">Thingiverse</a> that the instructional video for the Kitty 3000 pet treat dispenser was no longer available so I cleaned up my micropython code a bit and am making it available here.</p><p>About 2 years ago I came across the <a href="https://www.elektormagazine.com/news/kitty-3000-cat-treat-dispenser?ref=tech.scarey.net" rel="noreferrer">Kitty 3000 treat dispenser</a> and printed one out figuring my dogs wouldn&apos;t be too offended.  The software that ran it relied on a raspberry pi and served a custom web page to control.  Since the functionality was so simple I just ported it to an ESP32 and used MQTT and Home Assistant to handle the treat dispensing and tracking duties.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2024/11/20241112_120630.jpg" class="kg-image" alt="Kitty 3000 Firmware" loading="lazy" width="2000" height="2667" srcset="https://tech.scarey.net/content/images/size/w600/2024/11/20241112_120630.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2024/11/20241112_120630.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2024/11/20241112_120630.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2024/11/20241112_120630.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">One of my dusty Doggy 3000s</span></figcaption></figure><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>,&#xA0;<a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, or whatever ESP32 you prefer</li><li><a href="https://amzn.to/3Z0f9WI?ref=tech.scarey.net" rel="noreferrer">Stepper motor and driver</a></li><li><a href="https://amzn.to/3AHFCiB?ref=tech.scarey.net" rel="noreferrer">Wire</a></li><li><a href="https://amzn.to/3VeKpQd?ref=tech.scarey.net" rel="noreferrer">Dupont connector kit</a> - (optional)</li><li><a href="https://amzn.to/3wPMs3s?ref=tech.scarey.net" rel="noreferrer">Dupont Terminal Block</a> (optional, handy for all the ground connections)</li><li><a href="https://amzn.to/4bm86eS?ref=tech.scarey.net" rel="noreferrer">USB cable</a></li><li><a href="https://amzn.to/4bGLW6H?ref=tech.scarey.net" rel="noreferrer">USB wall charger</a></li><li><a href="https://amzn.to/4fgROG2?ref=tech.scarey.net" rel="noreferrer">3D Printer</a> for the Kitty 3000 itself</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><h2 id="3d-printing">3D Printing</h2><p>Without the video to explain it&apos;s hard to know what to print.  I barely remember but in general you can have up to 5(?) levels maybe.  Each level holds about 11 treats and I just used 2 levels on top of the base.  I also changed the text on the front from Kitty 3000 to Doggy 3000 and hopefully no-one minds if I make that available here:</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2024/11/Doggy-3000.stl" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">Doggy 3000</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">Doggy 3000.stl</div><div class="kg-file-card-filesize">310 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><ol><li>Bottom (thin base plate)</li><li>Bottom enclosure (lowest level that holds the stepper motor)</li><li>Lowest layer</li><li>Basic enclosure (or could be swapped for Kitty/Doggy 3000 logo enclosure at any layer)</li><li>Bottom drum (attaches to stepper motor)</li><li><em>(You&apos;re functional at this point and have 11 treats but each level above would need the following)</em></li><li>Drum</li><li>Nub (connects the drums between levels)</li><li><em>X</em> layer - Second, Third, Forth, and Fifth layer files are provided (the openings between the layers need to be offset to prevent upper layer treats from falling more than one layer down) </li><li>Basic enclosure</li><li><em>(Loop steps 7 through 10  for each other layer)</em></li><li>Lid</li></ol><h2 id="wiring-and-assembly">Wiring and Assembly</h2><p>The stepper motor driver and ESP32 both need 5V power.  I usually cut a micro USB cable and connect it to the power adapter and the other side to a terminal block.  Then connect the micro side from the terminal block to the ESP32 and another 2 pin female dupont from the terminal block to the power in on the stepper driver.  The driver board connects to 4 pins on the ESP32.  In the default config I&apos;m using pins 32,33,25,26 but can be easily changed.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2024/11/20241111_190525.jpg" class="kg-image" alt="Kitty 3000 Firmware" loading="lazy" width="2000" height="2667" srcset="https://tech.scarey.net/content/images/size/w600/2024/11/20241111_190525.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2024/11/20241111_190525.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2024/11/20241111_190525.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2024/11/20241111_190525.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Example wiring</span></figcaption></figure><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Kitty 3000 Firmware"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Kitty 3000 Firmware"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/57e183199732349c7d1cc8a929bcb3ce90f7bc9f19584c99ba0215025aabbc13/peterhinch/micropython-mqtt" alt="Kitty 3000 Firmware"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/kitty-3000?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/kitty-3000: Alternative code for running the Kitty 3000 as the original project seems unavailable. This project uses an Micropython on an ESP32 and Home Assistant to release and track treat counts.</div><div class="kg-bookmark-description">Alternative code for running the Kitty 3000 as the original project seems unavailable. This project uses an Micropython on an ESP32 and Home Assistant to release and track treat counts. - scarey/ki&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="Kitty 3000 Firmware"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/f2967c83e740d30dd37d69ea32d8d248199428f8467b51adb00ebf2df630f132/scarey/kitty-3000" alt="Kitty 3000 Firmware"></div></a></figure><p>Copy all python files to the root of the ESP32.  If you don&apos;t want the automatic Home Assistant device and entity creation you can get rid of ha.py and use an MQTT client instead.</p><h2 id="configuration">Configuration</h2><h3 id="static-config-configjson">Static config (config.json)</h3><p>The static config file contains config for the 4 stepper pin numbers, a dispenser number so you can have mutiple Kitty 3000&apos;s, and the number of treats it can hold (based on how many layers).  Make necessary changes and copy to the root of the ESP32.</p><h3 id="mqtt-config">MQTT config</h3><p>I made some configuration easier to change and it exists as a JSON document in the &quot;esp32/kitty3000/&lt;dispenser num&gt;/config&quot; topic.  The &quot;name&quot; shows up in Home Assistant auto discovery device.  The cheap steppers seem to need some tweaking as they get a little off over time.  I&apos;ve added &quot;adjustment-angle&quot; (how much to adjust) and &quot;adjustment-freq&quot; (number of treats to adjust after) and you can muck with those to calibrate yours.<br></p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;name&quot;: &quot;Doggy 3000 - Family room&quot;,
  &quot;adjustment-angle&quot;: 2,
  &quot;adjustment-freq&quot;: 6
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">&quot;esp32/kitty3000/&lt;dispenser num&gt;/config&quot; topic</span></p></figcaption></figure><h2 id="home-assistant">Home Assistant</h2><p>If you uploaded ha.py to your ESP32 then the code will use MQTT Discovery to create a device and entities.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2024/11/Home-Assistant.jpg" class="kg-image" alt="Kitty 3000 Firmware" loading="lazy" width="1080" height="1125" srcset="https://tech.scarey.net/content/images/size/w600/2024/11/Home-Assistant.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2024/11/Home-Assistant.jpg 1000w, https://tech.scarey.net/content/images/2024/11/Home-Assistant.jpg 1080w" sizes="(min-width: 720px) 720px"></figure><h2 id="notifications">Notifications</h2><p>I didn&apos;t bother making any but you could notify yourself when the treat count gets low.</p>]]></content:encoded></item><item><title><![CDATA[Smart Mousetrap]]></title><description><![CDATA[<p>I got tired of hearing critters running around in my walls.  Ordered some traps and quickly got tired of going into the attic every day to check them.  I ended up adding small reed switches and magnets to the traps and wiring them to an ESP32.  Now I just wait</p>]]></description><link>https://tech.scarey.net/smart-mousetrap/</link><guid isPermaLink="false">66475b84a8bc210001b85f39</guid><category><![CDATA[esp32]]></category><category><![CDATA[mice]]></category><category><![CDATA[MQTT]]></category><category><![CDATA[micropython]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Sat, 18 May 2024 19:44:48 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1510833606101-ca2953c586a5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1vdXNlJTIwdHJhcHxlbnwwfHx8fDE3MTU5NTI1NjV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1510833606101-ca2953c586a5?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDJ8fG1vdXNlJTIwdHJhcHxlbnwwfHx8fDE3MTU5NTI1NjV8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Smart Mousetrap"><p>I got tired of hearing critters running around in my walls.  Ordered some traps and quickly got tired of going into the attic every day to check them.  I ended up adding small reed switches and magnets to the traps and wiring them to an ESP32.  Now I just wait for the &quot;A &#x1FAA4; went off! Another &#x1F401; bites the dust!&quot; message, grab a Ziploc bag and head up to the attic hoping it was a merciful death.</p><p>&#x1FAA4; Running tally &#x1FAA4; - &#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;&#x1F401;</p><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>,&#xA0;<a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, or whatever ESP32 you prefer</li><li><a href="https://amzn.to/4bLaprL?ref=tech.scarey.net" rel="noreferrer">Mousetraps</a></li><li><a href="https://amzn.to/44HX4hD?ref=tech.scarey.net" rel="noreferrer">Small reed switches</a></li><li><a href="https://amzn.to/4bzrkxk?ref=tech.scarey.net" rel="noreferrer">Magnets</a> - the tiny magnets that come with the reed switches didn&apos;t do a good job</li><li><a href="https://amzn.to/3WEE95g?ref=tech.scarey.net" rel="noreferrer">Wire</a> - the layout of your traps determines how much wire you&apos;ll need.  See the Wiring section below.</li><li><a href="https://amzn.to/3VeKpQd?ref=tech.scarey.net" rel="noreferrer">Dupont connector kit</a> - (optional)</li><li><a href="https://amzn.to/3wPMs3s?ref=tech.scarey.net" rel="noreferrer">Dupont Terminal Block</a> (optional, handy for all the ground connections)</li><li><a href="https://amzn.to/4bm86eS?ref=tech.scarey.net" rel="noreferrer">USB cable</a></li><li><a href="https://amzn.to/4bGLW6H?ref=tech.scarey.net" rel="noreferrer">USB wall charger</a></li><li><a href="https://amzn.to/3wEv9CA?ref=tech.scarey.net" rel="noreferrer">Hot glue gun</a></li><li><a href="https://amzn.to/4dNlkTk?ref=tech.scarey.net" rel="noreferrer">Multimeter</a> (optional)</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring-and-assembly">Wiring and Assembly</h2><p>You need 2 wires between each trap and ESP32.  Depending on the spread you might be better off having multiple ESP32s and shorter runs of wire.  One wire from each trap needs to go to ground and the other to an input pin.  Among others, pins 16 - 33 are safe to use.</p><p>The ends of the wires on the trap side are connected to the reed switch.  Test the reed switch before connecting the wires as some are likely DOA.  Hot glue the reed switch to the bottom of the trap opposite the teeth and hot glue the magnet above that on the part you press down.  I used a multimeter while gluing the magnet to ensure it was in a good spot to trigger the reed switch.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2024/05/20240517_122932.jpg" class="kg-image" alt="Smart Mousetrap" loading="lazy" width="1757" height="1972" srcset="https://tech.scarey.net/content/images/size/w600/2024/05/20240517_122932.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2024/05/20240517_122932.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2024/05/20240517_122932.jpg 1600w, https://tech.scarey.net/content/images/2024/05/20240517_122932.jpg 1757w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Magnet and reed switch hot glued in place</span></figcaption></figure><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Smart Mousetrap"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub
 - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. 
Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A
 &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of 
using an ESP8266 to bring MQTT to non-networked targets. - GitHub - 
peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous 
M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Smart Mousetrap"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/57e183199732349c7d1cc8a929bcb3ce90f7bc9f19584c99ba0215025aabbc13/peterhinch/micropython-mqtt" alt="Smart Mousetrap"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs. We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="ota-library-optional">OTA library (optional)</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/simple-ota-updater?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/simple-ota-updater: Micropython code to read updated code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-description">Micropython
 code to read updated code via MQTT and update the ESP32 filesystem - 
GitHub - scarey/simple-ota-updater: Micropython code to read updated 
code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Smart Mousetrap"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/0943b1414c7c4390e8d575e7016204a762c41522788ec08af52bf315197fe6e8/scarey/simple-ota-updater" alt="Smart Mousetrap"></div></a></figure><p>If you want to be able to remotely update the code, grab ota.py and upload to the root of the ESP32. See this <a href="https://tech.scarey.net/ota-updates-via-mqtt/">post</a> for more details.</p><h3 id="this-projects-code">This project&apos;s code</h3><p>Copy main.py to the root of the ESP32.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/smart-mousetrap?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/smart-mousetrap: Micropython code for monitoring mousetraps using ESP32.</div><div class="kg-bookmark-description">Micropython code for monitoring mousetraps using ESP32. - scarey/smart-mousetrap</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="Smart Mousetrap"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/858180c59a4821621465486d2b7ce08e9500518c3785bdb77bcb345fc4891278/scarey/smart-mousetrap" alt="Smart Mousetrap"></div></a></figure><hr><h2 id="configuration">Configuration</h2><p>You just need to let the software know what pins the trap(s) are connected to via MQTT configuration data in the &apos;esp32/mousetrap/config&apos; topic (set retain for the config). It looks something like:<br></p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;activePins&quot;: [25,26,27]
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample esp32/mousetrap/config</span></p></figcaption></figure><p>To use multiple ESP32s just change the BASE_TOPIC in the code for each to a unique value, e.g. &apos;esp32/mousetrap2&apos;.</p><hr><h2 id="notifications">Notifications</h2><p>When the trap is sprung an MQTT message with a comma separated list of all sprung trap pin numbers will be sent.  Use Home Assistant automation or Node-RED etc to let you know traps went off.  Home Assistant phone notifications work well and are free.  Twilio costs a few bucks a month and let&apos;s you send text messages.</p><hr><h2 id="notes">Notes</h2><p>I&apos;ve got an outlet near the air handler for the AC so I just power the ESP32s from that.  If you have a light socket you could get a socket adapter to add an outlet there.  If there&apos;s any interest I could look into running off a battery and going into deep sleep mode, etc, etc.</p>]]></content:encoded></item><item><title><![CDATA[More Hot Tub Ideas]]></title><description><![CDATA[<p>I&apos;ve been working on a towel warmer for out by the hot tub.  If it doesn&apos;t burn down my house I&apos;ll probably make a post about it.  I am also looking into automatic dispensing of chlorine and boric acid though I wanted some feedback</p>]]></description><link>https://tech.scarey.net/more-hot-tub/</link><guid isPermaLink="false">653bc289888efa000105be1e</guid><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Sun, 05 Nov 2023 14:47:29 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1620354318203-cac692976b04?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ4fHxob3QlMjB0dWJ8ZW58MHx8fHwxNjk5MTQwNTExfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1620354318203-cac692976b04?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDQ4fHxob3QlMjB0dWJ8ZW58MHx8fHwxNjk5MTQwNTExfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="More Hot Tub Ideas"><p>I&apos;ve been working on a towel warmer for out by the hot tub.  If it doesn&apos;t burn down my house I&apos;ll probably make a post about it.  I am also looking into automatic dispensing of chlorine and boric acid though I wanted some feedback first.</p><h2 id="towel-warmer">Towel warmer</h2><p>This is essentially an insulated box with a solid state relay controlling an electric heater to keep the box in a toasty temperature range.   I need to play around and see what temps will work well but I&apos;ve currently got the heater shutting off at 130<strong>&#xB0;</strong>F...</p><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/11/20231104_172245.jpg" width="2000" height="2667" loading="lazy" alt="More Hot Tub Ideas" srcset="https://tech.scarey.net/content/images/size/w600/2023/11/20231104_172245.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/11/20231104_172245.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/11/20231104_172245.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/11/20231104_172245.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/11/20231105_084700.jpg" width="2000" height="1562" loading="lazy" alt="More Hot Tub Ideas" srcset="https://tech.scarey.net/content/images/size/w600/2023/11/20231105_084700.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/11/20231105_084700.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/11/20231105_084700.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/11/20231105_084700.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/11/20231105_084709.jpg" width="2000" height="1500" loading="lazy" alt="More Hot Tub Ideas" srcset="https://tech.scarey.net/content/images/size/w600/2023/11/20231105_084709.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/11/20231105_084709.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/11/20231105_084709.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/11/20231105_084709.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/11/Screenshot_20231105_092315_Home-Assistant-1.jpg" width="1440" height="801" loading="lazy" alt="More Hot Tub Ideas" srcset="https://tech.scarey.net/content/images/size/w600/2023/11/Screenshot_20231105_092315_Home-Assistant-1.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/11/Screenshot_20231105_092315_Home-Assistant-1.jpg 1000w, https://tech.scarey.net/content/images/2023/11/Screenshot_20231105_092315_Home-Assistant-1.jpg 1440w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="automatic-chemical-dispensing">Automatic chemical dispensing</h2><p>I&apos;ve been playing around with peristaltic pumps and they&apos;re pretty cool.  I have cheap and easy access to 10% bleach and I guess I&apos;ll be dissolving boric acid powder into water.  Would still need to occasionally manually add CYA and oxidizer, oh well.</p><h3 id="when-to-add">When to add?</h3><ul><li>Only during the filter cycles?  That way you wouldn&apos;t need automated pump control to ensure circulation.</li><li>For those with automated pump control I could publish when chemicals are being added and you could use Node-RED/HA automation to circulate when necessary.</li></ul><h3 id="how-to-prevent-dispensing-when-the-tub-is-in-use">How to prevent dispensing when the tub is in use?</h3><ul><li>Disable if the cover is open?</li></ul><h3 id="freezing-temps">Freezing temps?</h3><ul><li>Boric acid and bleach freezing in winter?  Additional circulator pump?</li><li>Or storing the chemicals in the tub cabinet?  That would also protect them from the sun but would be more of a pain to access.</li></ul>]]></content:encoded></item><item><title><![CDATA[Hot Tub Monitor]]></title><description><![CDATA[<p>When I got my hot tub last year and was looking into remote monitoring and control I could only find an old <a href="https://hackaday.com/2015/06/01/poolhot-tub-monitoring-and-data-collection/?ref=tech.scarey.net">Hackaday post</a> from 2015 but the old microcontroller was hard to source.  I figured I&apos;d rework it using tech from this decade so I could read</p>]]></description><link>https://tech.scarey.net/hot-tub-monitor/</link><guid isPermaLink="false">64d4e7019e300400011593d1</guid><category><![CDATA[Hot tub]]></category><category><![CDATA[esp32]]></category><category><![CDATA[Home Assistant]]></category><category><![CDATA[InfluxDB]]></category><category><![CDATA[micropython]]></category><category><![CDATA[MQTT]]></category><category><![CDATA[OTA]]></category><category><![CDATA[PH]]></category><category><![CDATA[ORP]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Thu, 28 Sep 2023 14:00:38 GMT</pubDate><media:content url="https://tech.scarey.net/content/images/2023/09/HottubFeature.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tech.scarey.net/content/images/2023/09/HottubFeature.jpg" alt="Hot Tub Monitor"><p>When I got my hot tub last year and was looking into remote monitoring and control I could only find an old <a href="https://hackaday.com/2015/06/01/poolhot-tub-monitoring-and-data-collection/?ref=tech.scarey.net">Hackaday post</a> from 2015 but the old microcontroller was hard to source.  I figured I&apos;d rework it using tech from this decade so I could read the temperature, PH, and ORP in Home Assistant and not have to deal as much with test strips.  </p><p>This uses an ESP32 and industrial PH and ORP sensors that seem to last for a year or so.  You can get cheap replacement sensors from Aliexpress.com to make that less painful.  I just replaced my PH sensor and have a new ORP sensor on order.</p><p>It takes readings every minute so you can watch the battle between chlorine and filthy kids in real-time.  It also has a two-point PH calibration mode to help make re-calibration easier, a display so you can check the sensor data locally and check calibration status, water and air temperature sensors, and an option to monitor the cover state (opened/closed).</p><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>, <a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, or whatever ESP32 you prefer</li><li><a href="https://amzn.to/44tqCgW?ref=tech.scarey.net">OLED Display</a> - 0.96&quot; 128x64</li><li><a href="https://amzn.to/3rj14pB?ref=tech.scarey.net">Assorted M2 and M4 nuts and bolts to mount box cover and display</a></li><li><a href="https://amzn.to/45KLaCU?ref=tech.scarey.net">Display on/off switch</a></li><li><a href="https://www.dfrobot.com/product-2069.html?ref=tech.scarey.net">Gravity: Analog Industrial pH Sensor / Meter Pro Kit V2</a></li><li><a href="https://www.phidgets.com/?prodid=103&amp;ref=tech.scarey.net">ORP Adapter</a></li><li><a href="https://www.phidgets.com/?tier=3&amp;catid=11&amp;pcid=9&amp;prodid=415&amp;ref=tech.scarey.net">ORP Industrial Electrode</a> or cheaper from <a href="https://www.aliexpress.us/item/2251801224764651.html?spm=a2g0o.productlist.main.1.239c6b81oA9fkI&amp;algo_pvid=c7d6e813-e1a5-4e52-9b69-1061bf57eb04&amp;algo_exp_id=c7d6e813-e1a5-4e52-9b69-1061bf57eb04-0&amp;pdp_npi=4%40dis%21USD%2125.50%2125.5%21%21%2125.50%21%21%402101d8b516930000717731009e67f7%2166231649399%21sea%21US%212739922527%21&amp;curPageLogUid=RHtiAzG5AabN&amp;ref=tech.scarey.net">Aliexpress.com</a> (choose &quot;ORP sensor BNC&quot;)</li><li>2x <a href="https://amzn.to/3OPUXAz?ref=tech.scarey.net">Temperature sensor</a></li><li><a href="https://amzn.to/3QpaR6k?ref=tech.scarey.net" rel="noreferrer">4.7k resistor</a></li><li>2x 0.5&quot; <a href="https://amzn.to/3RxJatI?ref=tech.scarey.net">grommets</a> or similar for sealing around the temp sensor and power wires</li><li><a href="https://amzn.to/45VytoH?ref=tech.scarey.net">pH Calibration Solution</a></li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><p>The ESP32 and ORP Adapter need 5V, everything else is 3.3V.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/10/HotTub_bb.png" class="kg-image" alt="Hot Tub Monitor" loading="lazy" width="1164" height="1411" srcset="https://tech.scarey.net/content/images/size/w600/2023/10/HotTub_bb.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/10/HotTub_bb.png 1000w, https://tech.scarey.net/content/images/2023/10/HotTub_bb.png 1164w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="assembly">Assembly</h2><p>I mounted it under a shelf and run the probes into the tub near a filter.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/08/20230802_104303.jpg" width="2000" height="2667" loading="lazy" alt="Hot Tub Monitor" srcset="https://tech.scarey.net/content/images/size/w600/2023/08/20230802_104303.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/08/20230802_104303.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/08/20230802_104303.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/08/20230802_104303.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/08/20230817_093753.jpg" width="2000" height="1500" loading="lazy" alt="Hot Tub Monitor" srcset="https://tech.scarey.net/content/images/size/w600/2023/08/20230817_093753.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/08/20230817_093753.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/08/20230817_093753.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/08/20230817_093753.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/08/20230817_093341.jpg" width="2000" height="1500" loading="lazy" alt="Hot Tub Monitor" srcset="https://tech.scarey.net/content/images/size/w600/2023/08/20230817_093341.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/08/20230817_093341.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/08/20230817_093341.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/08/20230817_093341.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/09/20230826_091006.jpg" width="2000" height="2667" loading="lazy" alt="Hot Tub Monitor" srcset="https://tech.scarey.net/content/images/size/w600/2023/09/20230826_091006.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/09/20230826_091006.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/09/20230826_091006.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/09/20230826_091006.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption><p><span style="white-space: pre-wrap;">The guts, calibration mode, and sensor data display</span></p></figcaption></figure><h3 id="project-box">Project Box</h3><p>It started life as this:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:4921568?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Waterproof electronic box / enclosure by pbtec</div><div class="kg-bookmark-description">Stable and waterproof / watertight OpenSCAD customizer case / box / enclosure V6.1 by pbtec
Edit December 2022: Updated Version 6.1 --&gt; Seems Openscad has in certain circumstances problem with special characters (like &#xE4;) in comments&#x2026;. Created new fixed version 6.1 (Nothing else has changed)
Latest n&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Hot Tub Monitor"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/49/b7/28/da/94/featured_preview_Sample1-UltimateWaterproofCase_V6.png" alt="Hot Tub Monitor"></div></a></figure><p>And I tweaked it in OpenSCAN and then ran out of filament during the print. I used some electrical tape to seal the gap. But you should make sure you have enough and pause the print around layer 187 and drop M4 nuts in each of the corners.  Toss in a desiccant packet to help with moisture.  I glued a clear piece of plastic to the box over the screen to hopefully keep the water out and the shelf provides some protection.</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2023/09/HottubMonitorBox.stl" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">HottubMonitorBox</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">HottubMonitorBox.stl</div><div class="kg-file-card-filesize">311 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><h3 id="orp-adapter">ORP Adapter</h3><p>Ensure the dip switch is set for ORP.</p><h3 id="sensors">Sensors</h3><p>I just put the PH, ORP, and water temp sensors up and over the side and into the tub near a filter.  The air temp sensor should be somewhere out of the sun and away from other objects.  Mine&apos;s hanging over one of the shelf supports. </p><h3 id="cover-openedclosed-sensor">Cover opened/closed sensor</h3><p>I haven&apos;t hooked this up on my setup yet but adding support for it in the code was simple enough.  I figured I&apos;d glue or maybe sew some magnets into the flap of the cover and try to line up a reed switch near where the magnets should end up. The cover state gets sent along with all the other data. Then it&apos;s easy to add some alerts like the cover has been open for a long time or is open at bedtime, etc.</p><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Hot Tub Monitor"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Hot Tub Monitor"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/57e183199732349c7d1cc8a929bcb3ce90f7bc9f19584c99ba0215025aabbc13/peterhinch/micropython-mqtt" alt="Hot Tub Monitor"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="ssd1306-driver">ssd1306 driver</h3><p>Grab that from <a href="https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/Others/OLED/ssd1306.py?ref=scareys-tech">here</a> and upload to the root of the ESP32.</p><h3 id="ota-library-optional">OTA library (optional)</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/simple-ota-updater?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/simple-ota-updater: Micropython code to read updated code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-description">Micropython code to read updated code via MQTT and update the ESP32 filesystem - GitHub - scarey/simple-ota-updater: Micropython code to read updated code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Hot Tub Monitor"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/0943b1414c7c4390e8d575e7016204a762c41522788ec08af52bf315197fe6e8/scarey/simple-ota-updater" alt="Hot Tub Monitor"></div></a></figure><p>If you want to be able to remotely update the code, grab ota.py and upload to the root of the ESP32.  See this <a href="https://tech.scarey.net/ota-updates-via-mqtt/">post</a> for more details.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/hot-tub-monitor?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/hot-tub-monitor: Micropython code for monitoring PH, ORP, and temperature of your hot tub using ESP32, Home Assistant, and InfluxDB2</div><div class="kg-bookmark-description">Micropython code for monitoring PH, ORP, and temperature of your hot tub using ESP32, Home Assistant, and InfluxDB2 - GitHub - scarey/hot-tub-monitor: Micropython code for monitoring PH, ORP, and t&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Hot Tub Monitor"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/366a450cb25503cda4af85655aed2e58d2369e63fadd24e505cb810a321398b0/scarey/hot-tub-monitor" alt="Hot Tub Monitor"></div></a></figure><p>Copy *.py to the root of the ESP32.  If you don&apos;t want the automatic Home Assistant device and entity creation you can get rid of ha.py. </p><hr><h2 id="configuration">Configuration</h2><p>When you have multiple temperature sensors using the 1-Wire protocol you need to know the serial numbers of each sensor so you know if it&apos;s the air or water temp sensor.  The first time you run the code it will output the serial numbers of the sensors it sees and you add those to the MQTT configuration in the &apos;esp32/hottub/config&apos; topic (set retain for the config).  It looks something like:<br></p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;ph_acid_calibration&quot;: 2032.44,
  &quot;water_rom_reg_num&quot;: &quot;2863c65704e13c56&quot;,
  &quot;ph_neutral_calibration&quot;: 1500.0,
  &quot;air_rom_reg_num&quot;: &quot;28c3005704e13cb4&quot;,
  &quot;temp_unit&quot;: &quot;F&quot;
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample esp32/hottub/config</span></p></figcaption></figure><p>The calibration values above are a good starting point so use those and just update the &apos;rom_reg_num&apos; values with what was output during startup.  If you find you mixed them up you can just swap them and publish (don&apos;t forget retain) the config again. </p><hr><h2 id="calibration">Calibration</h2><p>The two-point PH calibration process involves using PH 4.0 and PH 7.0 standard buffer solutions.  The usual suggestion is to do this monthly.</p><ul><li>Rinse the probe with distilled water, then absorb the residual water-drops with soft paper. Insert the pH probe into the standard buffer solution of 7.0 (we do the neutral readings first so the calibration process doesn&apos;t think the distilled water is the standard buffer solution)</li><li>Press the calibrate button in Home Assistant or publish &apos;{&quot;command&quot;: &quot;calibrate&quot;}&apos; to &apos;esp32/hottub/command&apos; but don&apos;t set retain.</li><li>The calibration process will begin within 1 minute and then you can see the progress on the display</li><li>Stir gently until the final neutral reading is taken</li><li>Rinse the probe again as in step 1 and insert into the 4.0 solution and stir gently until the final acid reading is taken</li><li>The previous MQTT config gets backed up to &apos;esp32/hottub/configbak&apos; and the updated calibration values and the timestamp of the calibration are stored in &apos;esp32/hottub/config&apos;.</li><li>Put the probe back in the hot tub and you&apos;re done.  </li></ul><hr><h2 id="home-assistant">Home Assistant</h2><p>If you uploaded ha.py to your ESP32 then the code will use MQTT Discovery to create a device and entities for the 4 sensors, and calibrate button.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/08/ha_tub_sensors2.jpg" class="kg-image" alt="Hot Tub Monitor" loading="lazy" width="1440" height="964" srcset="https://tech.scarey.net/content/images/size/w600/2023/08/ha_tub_sensors2.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/08/ha_tub_sensors2.jpg 1000w, https://tech.scarey.net/content/images/2023/08/ha_tub_sensors2.jpg 1440w" sizes="(min-width: 720px) 720px"></figure><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/08/ha_calibrate.jpg" class="kg-image" alt="Hot Tub Monitor" loading="lazy" width="1440" height="307" srcset="https://tech.scarey.net/content/images/size/w600/2023/08/ha_calibrate.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/08/ha_calibrate.jpg 1000w, https://tech.scarey.net/content/images/2023/08/ha_calibrate.jpg 1440w" sizes="(min-width: 720px) 720px"></figure><h3 id="notifications">Notifications</h3><p>I haven&apos;t bothered setting up any alerts yet but off the top of my head:</p><ul><li>PH / ORP out of range</li><li>Cover open too long or at an unlikely time</li><li>Water temp too low or high</li><li>Calibration reminder using &quot;last_calibration&quot; in the config</li></ul><hr><h2 id="historical-data">Historical Data</h2><p>If you&apos;d like historical temp, PH and/or ORP data here&apos;s some InfluxDB config that will let you make dashboards similar to this.  The data is all in MQTT so you can grab the data however you like and use your own visualization tools.</p><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/09/influx.png" class="kg-image" alt="Hot Tub Monitor" loading="lazy" width="950" height="874" srcset="https://tech.scarey.net/content/images/size/w600/2023/09/influx.png 600w, https://tech.scarey.net/content/images/2023/09/influx.png 950w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">You can see when I added spa down and chlorine</span></figcaption></figure><figure class="kg-card kg-code-card"><pre><code class="language-yaml">[[outputs.influxdb_v2]]
  urls = [&quot;http://&lt;host&gt;:8086&quot;]
  token = &quot;&lt;your token&gt;&quot;
  organization = &quot;&lt;your org&gt;&quot;
  bucket = &quot;iot&quot;

[[inputs.mqtt_consumer]]
  servers = [&quot;mqtts://&lt;host&gt;:&lt;port&gt;&quot;]
  topics = [
    &quot;esp32/hottub/readings&quot;,
  ]
  qos = 0
  username = &quot;telegraf&quot;
  password = &quot;&lt;mqtt password&gt;&quot;
  insecure_skip_verify = false
  data_format = &quot;value&quot;
  data_type = &quot;string&quot;
  topic_tag = &quot;&quot;
  [[inputs.mqtt_consumer.topic_parsing]]
    topic = &quot;esp32/hottub/readings&quot;
    tags = &quot;source/_/_&quot;
    measurement = &quot;_/what/_&quot;

  [[processors.starlark]]
     namepass = [&quot;hottub&quot;]
     script = &quot;/scripts/hottub.star&quot;
</code></pre><figcaption><p><span style="white-space: pre-wrap;">telegraf.conf example</span></p></figcaption></figure><p>You&apos;ll also need the Starlark processor script that parses the JSON payload.  Save it to the &quot;script&quot; path in the telegraf config (&quot;/scripts/hottub.star&quot; for mine).</p><figure class="kg-card kg-code-card"><pre><code class="language-python">load(&quot;json.star&quot;, &quot;json&quot;)
 
#{
#  &quot;orp&quot;: 545.8052,
#  &quot;air_temp&quot;: 64.3,
#  &quot;cover_state&quot;: 1,
#  &quot;ph&quot;: 6.931918,
#  &quot;temp_error&quot;: &quot;&quot;,
#  &quot;water_temp&quot;: 90.80001
#} 
 
def apply(metric):
   j = json.decode(metric.fields.get(&quot;value&quot;))
   metrics = []

   stow_metric = Metric(&quot;stow&quot;)
   stow_metric.fields[&quot;temp&quot;] = float(j[&quot;air_temp&quot;])
   stow_metric.tags[&quot;source&quot;] = &quot;esp32&quot;

   new_metric = Metric(&quot;hottub&quot;)
   new_metric.fields[&quot;orp&quot;] = float(j[&quot;orp&quot;])
   new_metric.fields[&quot;water_temp&quot;] = float(j[&quot;water_temp&quot;])
   new_metric.fields[&quot;ph&quot;] = float(j[&quot;ph&quot;])
   stow_metric.tags[&quot;source&quot;] = &quot;esp32&quot;

   metrics.append(stow_metric)
   metrics.append(new_metric)
  
   return metrics
</code></pre><figcaption><p><span style="white-space: pre-wrap;">hottub.star</span></p></figcaption></figure><hr><h2 id="notes">Notes</h2><ul><li>Replacement probes from Aliexpress.com seem to work well and are pretty cheap (~$20 for PH, ~$40 for ORP).  Make sure to choose the industrial probe with the BNC connector.  They likely need to be replaced each year.  My 14 month old ORP sensor is taking 2 days to settle its reading after a reboot though it&apos;s working well other than that.  The PH sensor thought most everything was 6.9-7.0 after a year and needed replacement.</li><li>I couldn&apos;t find any temperature correction data on the sensor page but at hot tub temps there seems to be minimal correction needed. We&apos;ve got the water temp available so it should be easy to add if we can figure that out in the future.</li></ul><p></p><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Simple ESP32 OTA Code updates via MQTT]]></title><description><![CDATA[<p>This is a very basic system for remotely updating files on an ESP32 and optionally triggering a reboot.  Lots of other projects do something similar and have more features but I wanted something lightweight that didn&apos;t depend on a web server.   The device just needs to listen to</p>]]></description><link>https://tech.scarey.net/ota-updates-via-mqtt/</link><guid isPermaLink="false">64d23e159e300400011592a6</guid><category><![CDATA[esp32]]></category><category><![CDATA[MQTT]]></category><category><![CDATA[micropython]]></category><category><![CDATA[OTA]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Thu, 10 Aug 2023 13:25:41 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1547190027-9156686aa2f0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDk4fHxzb2Z0d2FyZXxlbnwwfHx8fDE2OTE1MDA3MDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1547190027-9156686aa2f0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDk4fHxzb2Z0d2FyZXxlbnwwfHx8fDE2OTE1MDA3MDR8MA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Simple ESP32 OTA Code updates via MQTT"><p>This is a very basic system for remotely updating files on an ESP32 and optionally triggering a reboot.  Lots of other projects do something similar and have more features but I wanted something lightweight that didn&apos;t depend on a web server.   The device just needs to listen to an OTA topic and pass the message to the OTA module which will handle the filesystem updates and rebooting.</p><p>There are no fancy features here.  No rolling back broken code if the updated code is so broken that it can no longer connect to MQTT. So you&apos;ll want to be careful and test your changes.</p><p>Any file can be updated not just python so can also update configuration text or JSON files, etc.  If you&apos;re updating multiple python files you probably don&apos;t want to request a reboot until they are all updated.</p><hr><h2 id="how-it-works">How it works</h2><p>We need some way to get the new code on the device.  Since it seems most of my networked projects use MQTT I figured I&apos;d use that to deliver the new code.  No need for a separate web server.  If we just put the contents of the new file into a topic then we wouldn&apos;t know what file we want to update and whether it should reboot after the new code was there.</p><h3 id="headers">Headers</h3><p>We basically just need some metadata along with the file contents.  I thought about putting the file contents in a field in a JSON document but there would be too many special characters that would be a pain to escape.  Base64 encoding would also be a pain and make the content a good bit larger.  In the end I just went with some header lines in a specific format (# OTA:&lt;name&gt;:&lt;value&gt;) that let you pass arbitrary name/value pairs.</p><pre><code class="language-python"># OTA:file:main.py
# OTA:reboot:true
from machine import Pin
import time
...</code></pre><h3 id="mqtt-code">MQTT code</h3><p>The application code just needs to listen to an OTA topic of its choice and pass those messages to the code in this project.  It will parse the headers, write the file, and maybe reboot.</p><pre><code class="language-python">    if topic == self.ota_topic:
        ota.process_ota_msg(msg_string)</code></pre><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Simple ESP32 OTA Code updates via MQTT"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Simple ESP32 OTA Code updates via MQTT"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/a22cea85bc63ca23d9117667d9ef9433223b4f669563b5ee63399dd5e75c81ed/peterhinch/micropython-mqtt" alt="Simple ESP32 OTA Code updates via MQTT"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/simple-ota-updater?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/simple-ota-updater: Micropython code to read updated code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-description">Micropython code to read updated code via MQTT and update the ESP32 filesystem - GitHub - scarey/simple-ota-updater: Micropython code to read updated code via MQTT and update the ESP32 filesystem</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Simple ESP32 OTA Code updates via MQTT"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/60a81edfb7c1ed96dae308373924cae36daa9a6d7585ef514366fed9f9e7c80e/scarey/simple-ota-updater" alt="Simple ESP32 OTA Code updates via MQTT"></div></a></figure><p>Copy main.py, ota.py, and mqtt_handler.py to the root of the ESP32. The example will blink the LED at 1 second intervals.  Modify main.py to with any changes you want.  Maybe change the &quot;version&quot; variable to 2 and &quot;led_sleep_time&quot; to 0.5 and publish the contents of main.py to esp32/otatest/ota.  The new code should be written to main.py and the ESP32 rebooted.  The LED should blink at 0.5 second intervals and esp32/otatest/version should be updated to 2.  Cool.</p><hr><h2 id="notes">Notes</h2><ul><li>Any other headers that might be handy?</li></ul>]]></content:encoded></item><item><title><![CDATA[Awning Control]]></title><description><![CDATA[<p>My deck gets a lot of sun so I figured an awning might help with the glare and keep it cool enough let me and the doggies walk around without getting 3rd degree burns. I ordered a highly rated one off Amazon, installed it, and quickly got to witness how</p>]]></description><link>https://tech.scarey.net/awning-control/</link><guid isPermaLink="false">6498741d51c5ed00012a96dc</guid><category><![CDATA[BTS7960]]></category><category><![CDATA[esp32]]></category><category><![CDATA[GY-521]]></category><category><![CDATA[Home Assistant]]></category><category><![CDATA[micropython]]></category><category><![CDATA[MQTT]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Wed, 05 Jul 2023 17:21:53 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1525284572756-ee781c4f221e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDIyM3x8YXduaW5nfGVufDB8fHx8MTY4OTI5MDA4OHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1525284572756-ee781c4f221e?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDIyM3x8YXduaW5nfGVufDB8fHx8MTY4OTI5MDA4OHww&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Awning Control"><p>My deck gets a lot of sun so I figured an awning might help with the glare and keep it cool enough let me and the doggies walk around without getting 3rd degree burns. I ordered a highly rated one off Amazon, installed it, and quickly got to witness how the wind threatens to tear it right off the house.  After that I was almost afraid to use it...maybe I&apos;d forget to close it and later find it and my fascia board in my neighbor&apos;s yard.  Time for some technological help.  My main goal was to automatically close the awning if it got too windy and that of course meant motorizing it.  Fun!</p><p>The main features are:</p><ul><li>Auto-close based on an accelerometer</li><li>MQTT to allow integration with Home Assistant or other front ends and monitoring systems</li><li>Automation (Node-RED) to automatically close it at night (maybe open in the morning if there&apos;s rain or sun in the forecast?).</li><li>No permanent modifications to the awning</li></ul><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>, <a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, or whatever ESP32 you prefer</li><li><a href="https://amzn.to/3NvFHYY?ref=tech.scarey.net">24V high torque motor</a></li><li><a href="https://amzn.to/3QPLYRR?ref=tech.scarey.net" rel="noreferrer">BTS7960 high power motor driver</a></li><li><a href="https://amzn.to/3GDBGiB?ref=tech.scarey.net">GY-521</a> - Accelerometer/Gyroscope</li><li>2x <a href="https://amzn.to/3ULrgUj?ref=tech.scarey.net" rel="noreferrer">reed switches</a></li><li><a href="https://amzn.to/44DS6kP?ref=tech.scarey.net">8mm to 10mm shaft coupler</a></li><li>5/16&quot; stainless eye screw (~8mm) depending on your awning</li><li><a href="https://amzn.to/46mNBfZ?ref=tech.scarey.net">Awning</a> - mine is 13&apos;x8&apos; though they also have <a href="https://amzn.to/3NYZmlD?ref=tech.scarey.net">10&apos;x8&apos;</a> and <a href="https://amzn.to/3NZAdqQ?ref=tech.scarey.net">12&apos;x10&apos;</a> but you&apos;d have to check if the opening mechanism is the same.</li><li><a href="https://amzn.to/44cOI04?ref=tech.scarey.net">24V Waterproof power supply</a></li><li><a href="https://amzn.to/44mNwaa?ref=tech.scarey.net">Buck converter</a></li><li><a href="https://amzn.to/3qWhymK?ref=tech.scarey.net">Waterproof project box</a></li><li><a href="https://amzn.to/3O1fPpq?ref=tech.scarey.net">Dielectric grease</a> - optional but will help protect the reed switch contacts</li><li>Various wire - At least 15&apos; of 4 conductor wire for the accelerometer, maybe 10&apos; of <a href="https://amzn.to/45vVM9f?ref=tech.scarey.net">2 conductor wire</a> for the reed switches, <a href="https://amzn.to/43knm8x?ref=scareys-tech">dupont wires</a> for the motor controller, etc.</li><li>Motor mount and various hardware - I used some PVC board I had lying around but PT or stained wood would work too</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/07/Awning_bb-1.png" class="kg-image" alt="Awning Control" loading="lazy" width="1899" height="1670" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/Awning_bb-1.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/Awning_bb-1.png 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/Awning_bb-1.png 1600w, https://tech.scarey.net/content/images/2023/07/Awning_bb-1.png 1899w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Forgive my Fritzing skills. Right-click and open in new tab to see a larger version.</span></figcaption></figure><hr><h2 id="assembly">Assembly</h2><p>I didn&apos;t want to permanently modify the awning so if I sell my house or something I can just revert things back to using the hooked rod.  The eye the hooked rod goes through is riveted on so I needed to figure out a way for the motor to turn the eye. In the end I decided to make a hook that could be attached to the motor using a coupler.  To make sure the grub screws in the coupler would hold I used some Loctite and also used my drill press and drilled dimples in the hook where the grub screws made contact. There is a good amount of pressure on the coupling especially when closing so drill in as far as you can and use longer screws to make the connection as solid as possible.</p><p>For the motor mount I used a scrap piece of PVC board I had laying around and drilled 3 holes for the bolts that secure the motor and one for the coupler. </p><p>The close reed switch was easy with the switch on the awning frame near the house and the magnet zip tied to an arm.  The open reed switch I put at the elbow of the arm with a short extension since the arms don&apos;t make a straight line when fully opened.</p><p>The accelerometer I placed at the end of an arm.  The code just adds up the XYZ acceleration so you don&apos;t need to worry about orientation.  I initially didn&apos;t weatherproof the accelerometer at all and it lasted about 2 years.  I&apos;ve current got a poor man&apos;s setup with a Ziploc bag and desiccant pack and I&apos;m curious to see how long that will last.  Once that dies I&apos;ll try some marine epoxy or maybe just print a small enclosure.</p><figure class="kg-card kg-gallery-card kg-width-wide kg-card-hascaption"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/07/Awning-1.png" width="2000" height="1129" loading="lazy" alt="Awning Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/Awning-1.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/Awning-1.png 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/Awning-1.png 1600w, https://tech.scarey.net/content/images/size/w2400/2023/07/Awning-1.png 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/07/20230627_113530.jpg" width="2000" height="2667" loading="lazy" alt="Awning Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/20230627_113530.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/20230627_113530.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/20230627_113530.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/07/20230627_113530.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/07/20230705_093445.jpg" width="2000" height="1500" loading="lazy" alt="Awning Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/20230705_093445.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/20230705_093445.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/20230705_093445.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/07/20230705_093445.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/07/20230705_092852.jpg" width="2000" height="2667" loading="lazy" alt="Awning Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/20230705_092852.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/20230705_092852.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/20230705_092852.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/07/20230705_092852.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div></div><figcaption><p><span style="white-space: pre-wrap;">Neat wiring is not my strong suit</span></p></figcaption></figure><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Awning Control"></div></div></a></figure><h3 id="mpu6050-esp8266-micropython">MPU6050-ESP8266-MicroPython</h3><figure class="kg-card kg-bookmark-card kg-card-hascaption"><a class="kg-bookmark-container" href="https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - adamjezek98/MPU6050-ESP8266-MicroPython: Simple library for MPU6050 on ESP8266 with micropython</div><div class="kg-bookmark-description">Simple library for MPU6050 on ESP8266 with micropython - GitHub - adamjezek98/MPU6050-ESP8266-MicroPython: Simple library for MPU6050 on ESP8266 with micropython</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Awning Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">adamjezek98</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/c99e482ccf7bb3293b8b72039677afc563c1c2d05747a7b955c2ecea52ed2c40/adamjezek98/MPU6050-ESP8266-MicroPython" alt="Awning Control"></div></a><figcaption><p><span style="white-space: pre-wrap;">https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython</span></p></figcaption></figure><p>Grab mpu6050.py and upload that to your ESP32.</p><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Awning Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/57e183199732349c7d1cc8a929bcb3ce90f7bc9f19584c99ba0215025aabbc13/peterhinch/micropython-mqtt" alt="Awning Control"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/awning-control?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/awning-control: Micropython code for controlling a motor to open/close an awning and automatically close it when it&#x2019;s too windy.</div><div class="kg-bookmark-description">Micropython code for controlling a motor to open/close an awning and automatically close it when it&amp;#39;s too windy. - GitHub - scarey/awning-control: Micropython code for controlling a motor to op&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Awning Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/726a37b7d9b83a1091e0994b8540b9a0abfe6d29761a5cd58ea4f3abede735e5/scarey/awning-control" alt="Awning Control"></div></a></figure><p>Copy main.py and bts7960.py to the root of the ESP32.</p><h3 id="configuration">Configuration</h3><p>Publish your config (with retain) to the &quot;esp32/awning/config&quot; topic.  &quot;windThreshold&quot; is the value the sum of the accelerometer changes needs to be above to trigger the close.  Increase it if you think it&apos;s closing when it&apos;s not that windy or decrease it if it&apos;s getting blown around and not closing.  You can check the value history in an MQTT client.  The &quot;sampleFrequency&quot; is how ofter to check the wind readings.  I&apos;ve been using 3 seconds and it seems to work well.</p><pre><code class="language-json">{&quot;windThreshold&quot;: 2400, &quot;sampleFrequency&quot;: 3}</code></pre><hr><h2 id="home-assistant">Home Assistant</h2><p>I&apos;m just using the MQTT Cover and sensor interfaces and default widgets to control things and see what the wind readings look like.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/07/HAAwning.jpg" class="kg-image" alt="Awning Control" loading="lazy" width="1424" height="839" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/HAAwning.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/HAAwning.jpg 1000w, https://tech.scarey.net/content/images/2023/07/HAAwning.jpg 1424w" sizes="(min-width: 720px) 720px"></figure><pre><code class="language-yaml">mqtt:
  cover:
  - unique_id: &apos;awning&apos;
    name: &quot;Deck awning&quot;
    command_topic: &quot;esp32/awning/set&quot;
    state_topic: &quot;esp32/awning/state&quot;
    availability:
      - topic: &quot;esp32/awning/availability&quot;
    payload_open: &quot;open&quot;
    payload_close: &quot;close&quot;
    payload_stop: &quot;stop&quot;
    optimistic: false
  sensor:
  - unique_id: awningvib
    name: &quot;Awning wind&quot;
    state_topic: &quot;esp32/awning/readings&quot;
    unit_of_measurement: &quot;XYZ sum&quot;
    value_template: &gt;-
      {%- set parts = value[1:-1].split(&quot;,&quot;) -%}
      {{ int(parts[0]) + int(parts[1]) + int(parts[2]) }}
</code></pre><h3 id="alexa">Alexa</h3><p>If you managed to configure Alexa for your Home Assistant then congrats!  It&apos;s kind of a pain as seen here:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.home-assistant.io/integrations/alexa/?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Amazon Alexa</div><div class="kg-bookmark-description">Instructions on how to connect Alexa/Amazon Echo to Home Assistant.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.home-assistant.io/images/favicon-192x192.png" alt="Awning Control"><span class="kg-bookmark-author">Home Assistant</span><span class="kg-bookmark-publisher">Home Assistant</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.home-assistant.io/images/default-social.png" alt="Awning Control"></div></a></figure><p>But once you have completed said suffering controlling your awning with Alexa is as simple as:</p><pre><code class="language-yaml">alexa:
  smart_home:
    locale: en-US
    endpoint: https://api.amazonalexa.com/v3/events
    filter:
      include_entities:
        - cover.deck_awning
    entity_config:
      cover.deck_awning:
        name: &quot;Awning&quot;</code></pre><hr><h2 id="notes">Notes</h2><ul><li>You need to be very careful while you&apos;re testing.  If the close reed switch isn&apos;t working right the motor will keep trying to close and put a lot of strain on everything.  If the open reed switch isn&apos;t working the spool will completely unwind and begin winding with the fabric on the underside of the spool which will stress the fabric against the middle roller.  Be prepared to pull the plug while you&apos;re testing!</li><li>I&apos;ve had the awning motorized for 3 years now.  I just needed to replace the fabric and you can contact the seller on Amazon and it cost $45 shipped.  Not bad.</li><li>The loop that the hooked pole goes through is riveted on but last year the rivet rusted off.  If I had to do this again I&apos;d probably try to couple the motor straight to the post where the loop was but I ended up just putting a nail through where the rivet was and keeping the loop.  But it may be simplest to just remove the eye from the start.</li><li>I could add a rotary encoder and then exact positioning could be used, e.g. open the awning to 75%.  Maybe magnets and hall effect sensors like in the <a href="https://tech.scarey.net/ultimate-garage-door-control/">Ultimate Garage Door Control</a>.</li><li>9/7/23 - I just updated to Home Assistant 2023.9.0 and it didn&apos;t like how I was separating the acceleration values so I updated the config above to combine XYZ into a single number.</li></ul><p></p><p></p>]]></content:encoded></item><item><title><![CDATA[Temperature Controller]]></title><description><![CDATA[<p>I used to brew at my neighbor&apos;s place and we&apos;d ferment in his unfinished basement.  We&apos;d have trouble keeping the fermentation temperature up when it was cold out and we ended up putting a shop light underneath the fermenter to try warming things up.</p>]]></description><link>https://tech.scarey.net/temp-control/</link><guid isPermaLink="false">647f1aeb7fbd0c00014b137e</guid><category><![CDATA[esp32]]></category><category><![CDATA[relay]]></category><category><![CDATA[micropython]]></category><category><![CDATA[MQTT]]></category><category><![CDATA[Home Assistant]]></category><category><![CDATA[InfluxDB]]></category><category><![CDATA[Telegraf]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Sun, 11 Jun 2023 12:00:55 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1532634708-5a010d438d01?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGJyZXdpbmd8ZW58MHx8fHwxNjg2MDUxNjg0fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1532634708-5a010d438d01?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3wxMTc3M3wwfDF8c2VhcmNofDN8fGJyZXdpbmd8ZW58MHx8fHwxNjg2MDUxNjg0fDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Temperature Controller"><p>I used to brew at my neighbor&apos;s place and we&apos;d ferment in his unfinished basement.  We&apos;d have trouble keeping the fermentation temperature up when it was cold out and we ended up putting a shop light underneath the fermenter to try warming things up.  Obviously that wasn&apos;t a great solution and I ended up using an ESP8266, relay, and temperature probe to control the shop light.  That was years ago and I thought it could use a refresh.  Out with the shop light and in with a heating belt.  I&apos;ve added a separate relay for controlling a cooling system, support for fermentation temp schedules, adjustable temp differential, compressor delay, and all the fun data is available via MQTT.  A controller with similar features goes for $75 and has no network connectivity.</p><p><em>This project requires dealing with AC wiring which is dangerous if you&apos;re not careful.</em></p><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, <a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>, or whatever ESP32 you prefer</li><li>2x <a href="https://amzn.to/3MbRr2e?ref=tech.scarey.net">Single channel relay</a> - I like these since they trigger high</li><li><a href="https://amzn.to/3MSWXHq?ref=tech.scarey.net">Waterproof thermal probe</a> - this kit comes with the 4.7k resistors you&apos;ll need</li><li><a href="https://amzn.to/3qBiNI2?ref=tech.scarey.net">Thermowell</a> - maybe something like that depending on what works for your fermenter</li><li><a href="https://amzn.to/3NmeKrP?ref=tech.scarey.net">Fermentation heater</a> - or something similar</li><li><a href="https://amzn.to/3MWNBul?ref=tech.scarey.net">Fermentation cooler</a> - I figure a cooler full of ice water and a pump to circulate through the coil.  Another option is a fridge</li><li><a href="https://www.homedepot.com/p/Leviton-15-Amp-Residential-Grade-Grounding-Duplex-Outlet-White-R52-05320-00W/202066670?ref=tech.scarey.net">AC wall outlet</a> and cover</li><li><a href="https://amzn.to/3J2x07d?ref=tech.scarey.net">14 gauge extension cord</a> (or the cord from a power strip or dead UPS you might have lying around)  16 gauge would also work as long as you&apos;re not heating or cooling with something that uses lots of watts.  Just don&apos;t forget later on when you decide a blow dryer might work really well...:)</li><li>Wire nuts</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><p></p><hr><h2 id="wiring">Wiring</h2><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/06/TempControl_bb-5.png" class="kg-image" alt="Temperature Controller" loading="lazy" width="1338" height="1936" srcset="https://tech.scarey.net/content/images/size/w600/2023/06/TempControl_bb-5.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/06/TempControl_bb-5.png 1000w, https://tech.scarey.net/content/images/2023/06/TempControl_bb-5.png 1338w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="assembly">Assembly</h2><p>A double gang old work box works well, provides strain relief, and has plenty of room for the ESP32, relays, and outlet.  Take the 14 gauge extension cord and cut off the female end.  You&apos;ll be left with the male end and the cut end with 3 wires, hot, neutral and ground.  If you don&apos;t have any spare 14 gauge wire to use for pigtails you can cut some out of the extension cord.  You&apos;ll need 4 short pieces (2 to split the hot so they can go to the C terminals on the relays, and 2 out of the relay NO to the outlet).  A wire nut is a good way to connect the hot wire to the 2 pigtails.  Strip about 6&quot; of the outer insulation and push the 3 wires through a strain relief tab in the box until a little of the outer jacket enters the box.  Wire the 3 wires to the outlet as show in the diagram above.  Push the temp sensor wire through another strain relief tab on the opposite side of the box and connect it to the ESP32. Connect the relays to the ESP32.  I guess you could use an AC/DC converter to power the ESP32 but I just ran a USB cable into the box and power it separately.</p><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Temperature Controller"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Temperature Controller"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/57e183199732349c7d1cc8a929bcb3ce90f7bc9f19584c99ba0215025aabbc13/peterhinch/micropython-mqtt" alt="Temperature Controller"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="datetime">datetime</h3><p>Grab <a href="https://raw.githubusercontent.com/lorcap/upy-micropython-lib/datetime/python-stdlib/datetime/datetime.py?ref=tech.scarey.net">datetime.py</a> and upload it to the root of the ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/temp-control?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/temp-control: Micropython code for heating/cooling control including temp schedules and compressor delay</div><div class="kg-bookmark-description">Micropython code for heating/cooling control including temp schedules and compressor delay - GitHub - scarey/temp-control: Micropython code for heating/cooling control including temp schedules and&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Temperature Controller"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/821174cd09612ccdd76ef3f5c4cac29f266c1daa438fb3922b50e8b93f04d38b/scarey/temp-control" alt="Temperature Controller"></div></a></figure><h3 id="configuration">Configuration</h3><p>config.py contains a constant where you define the base topic name. I&apos;m using &quot;esp32/conical5g&quot; for this example.  If you want to have more than one controller you would just give them different base topics.</p><p>Publish your config (with retain) to the &quot;esp32/conical5g/config&quot; topic. &quot;lowTempLimit&quot; controls when the heat relay will active and &quot;highTempLimit&quot; does the same for cooling.  Keep them at least 1 degree apart to keep the heating and cooling from fighting.  Add 0 or more &quot;tempChanges&quot; if you&apos;d like the temp limits to auto adjust based on how many days after the &quot;startTimeUTC&quot; it is.  The code uses NTP to make sure it knows the correct date and time.</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;startTimeUTC&quot;: &quot;2023-05-31T12:00:00&quot;,
  &quot;lowTempLimit&quot;: 64,
  &quot;highTempLimit&quot;: 66,
  &quot;minimumOffMins&quot;: 3,
  &quot;tempChanges&quot;: [
    {
      &quot;daysLater&quot;: 2,
      &quot;tempChange&quot;: 2
    },
    {
      &quot;daysLater&quot;: 3,
      &quot;tempChange&quot;: 4
    }
  ]
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">esp32/conical5g/config</span></p></figcaption></figure><p>You can also tweak the config and publish at any point and the changes will immediately apply.</p><hr><h2 id="home-assistant">Home Assistant</h2><p>I use some simple MQTT config so HA can display the current data.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/06/HomeAssistantTempControl.png" class="kg-image" alt="Temperature Controller" loading="lazy" width="1440" height="1197" srcset="https://tech.scarey.net/content/images/size/w600/2023/06/HomeAssistantTempControl.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/06/HomeAssistantTempControl.png 1000w, https://tech.scarey.net/content/images/2023/06/HomeAssistantTempControl.png 1440w" sizes="(min-width: 720px) 720px"></figure><h3 id="configuration-1">Configuration</h3><pre><code class="language-yaml">mqtt:
  sensor:
  - unique_id: ferm0temp
    state_topic: &apos;esp32/conical5g/status&apos;
    name: &apos;5 gallon fermenter temperature&apos;
    unit_of_measurement: &apos;&#xC2;&#xB0;F&apos;
    value_template: &quot;{{ value_json.currentTemp }}&quot;
  - unique_id: &apos;ferm0heat&apos;
    name: &apos;5 gal fermenter heating&apos;
    state_topic: &apos;esp32/conical5g/status&apos;
    value_template: &gt;-
      {% if value_json.heatOn == 0 %}Off
      {% elif value_json.heatOn == 1 %}On
      {% endif %}
  - unique_id: &apos;ferm0cool&apos;
    name: &apos;5 gal fermenter cooling&apos;
    state_topic: &apos;esp32/conical5g/status&apos;
    value_template: &gt;-
      {% if value_json.coolOn == 0 %}Off
      {% elif value_json.coolOn == 1 %}On
      {% endif %}
  - unique_id: ferm0low
    state_topic: &apos;esp32/conical5g/status&apos;
    name: &apos;5 gallon fermenter low limit&apos;
    unit_of_measurement: &apos;&#xC2;&#xB0;F&apos;
    value_template: &quot;{{ value_json.lowTempLimit }}&quot;
  - unique_id: ferm0high
    state_topic: &apos;esp32/conical5g/status&apos;
    name: &apos;5 gallon fermenter high limit&apos;
    unit_of_measurement: &apos;&#xC2;&#xB0;F&apos;
    value_template: &quot;{{ value_json.highTempLimit }}&quot;</code></pre><h3 id="notifications">Notifications</h3><p>There are lots of options here based on the 5 pieces of data that get published every minute.  Whether the heating or cooling are active, the current limits, and the current temp are available.</p><ul><li>Current temp is a certain number of degrees outside the limits</li><li>Heating and cooling are both on?  That could be a bug in the code or messed up configuration.</li><li>Controller went offline (esp32/conical5g/availability topic)</li><li>Schedule changed the limits</li><li>Large change in the current temp</li></ul><p>Node-RED is my favorite way to set these up but HA automations will work too.</p><hr><h2 id="historical-data">Historical Data</h2><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/06/Belgian-Ferment2.png" class="kg-image" alt="Temperature Controller" loading="lazy" width="882" height="770" srcset="https://tech.scarey.net/content/images/size/w600/2023/06/Belgian-Ferment2.png 600w, https://tech.scarey.net/content/images/2023/06/Belgian-Ferment2.png 882w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Zabbix</span></figcaption></figure><p>This was from my old heat only setup.  The top graph is the outside temp, the middle is the beer temp, and the bottom is calling for heat.  My neighbor forgot to turn the shop light on until 6/9.  After that the temp was very stable.</p><h3 id="influxdb">InfluxDB</h3><p>For the upgrade setup I&apos;m using Telegraf to import the 5 pieces of data into InfluxDB.  Here&apos;s the Telegraf config:</p><figure class="kg-card kg-code-card"><pre><code class="language-toml">[[outputs.influxdb_v2]]
  urls = [&quot;http://&lt;host&gt;:8086&quot;]
  token = &quot;&lt;your token&gt;&quot;
  organization = &quot;&lt;your org&gt;&quot;
  bucket = &quot;iot&quot;

[[inputs.mqtt_consumer]]
  servers = [&quot;mqtts://&lt;host&gt;:&lt;port&gt;&quot;]
  topics = [
    &quot;esp32/conical5g/status&quot;,
  ]
  qos = 0
  username = &quot;telegraf&quot;
  password = &quot;&lt;mqtt password&gt;&quot;
  insecure_skip_verify = false
  data_format = &quot;value&quot;
  data_type = &quot;string&quot;
  topic_tag = &quot;&quot;
  [[inputs.mqtt_consumer.topic_parsing]]
    topic = &quot;esp32/conical5g/status&quot;
    tags = &quot;source/_/_&quot;
    measurement = &quot;_/what/_&quot;

  [[processors.starlark]]
     namepass = [&quot;conical5g&quot;]
     script = &quot;/scripts/tempcontrol.star&quot;
</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample telegraf configuration</span></p></figcaption></figure><p>You&apos;ll also need the Starlark processor script that parses the JSON payload.  Save it to the &quot;script&quot; path in the telegraf config (&quot;/scripts/tempcontrol.star&quot; for mine).</p><pre><code class="language-python">load(&quot;json.star&quot;, &quot;json&quot;)
 
def apply(metric):
   j = json.decode(metric.fields.get(&quot;value&quot;))
   metrics = []

   new_metric = Metric(&quot;conical5g&quot;)
   new_metric.fields[&quot;temp&quot;] = float(j[&quot;currentTemp&quot;])
   new_metric.fields[&quot;low&quot;] = float(j[&quot;lowTempLimit&quot;])
   new_metric.fields[&quot;high&quot;] = float(j[&quot;highTempLimit&quot;])
   new_metric.fields[&quot;heating&quot;] = int(j[&quot;heatOn&quot;])
   new_metric.fields[&quot;cooling&quot;] = int(j[&quot;coolOn&quot;])
   new_metric.tags[&quot;unit&quot;] = j[&quot;tempUnit&quot;]
   metrics.append(new_metric)
  
   return metrics</code></pre><p>Telegraf converts the JSON payload to the line protocol that InfluxDB likes.  It looks something like this (measurement, tags, fields, timestamp):</p><pre><code>conical5g,unit=F temp=73.7375,low=80,high=82,heating=1i,cooling=0i 1686452040495794428</code></pre><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/06/TempControlInfluxDB.png" class="kg-image" alt="Temperature Controller" loading="lazy" width="803" height="859" srcset="https://tech.scarey.net/content/images/size/w600/2023/06/TempControlInfluxDB.png 600w, https://tech.scarey.net/content/images/2023/06/TempControlInfluxDB.png 803w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">InfluxDB</span></figcaption></figure><p>This was from the test setup on my couch and not connected to any heating/cooling.  In the upper graph the orange is the current temp (my dog sat on the sensor and made that 90 degree spike) and the blue and purplish lines are the temp limits.  The bottom graph shows when the cooling and heating are active.</p><hr><h2 id="notes">Notes</h2><p>Now I just need to do some brewing...</p>]]></content:encoded></item><item><title><![CDATA[Ultimate Garage Door Control]]></title><description><![CDATA[<p>I&apos;ve had an Insteon Garage Door Control and Status kit for over a decade and I have never trusted it.  It consists of an Insteon controllable relay and a single reed switch that could tell you if the door was closed.  It would occasionally stop opening after about</p>]]></description><link>https://tech.scarey.net/ultimate-garage-door-control/</link><guid isPermaLink="false">6457bc7cd3a0fc0001461bc9</guid><category><![CDATA[Quadrature]]></category><category><![CDATA[esp32]]></category><category><![CDATA[micropython]]></category><category><![CDATA[relay]]></category><category><![CDATA[MQTT]]></category><category><![CDATA[Home Assistant]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Mon, 29 May 2023 20:31:10 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1512944957543-f119975934e0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIzOXx8Z2FyYWdlfGVufDB8fHx8MTY4MzQ3MTkyOQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1512944957543-f119975934e0?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIzOXx8Z2FyYWdlfGVufDB8fHx8MTY4MzQ3MTkyOQ&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Ultimate Garage Door Control"><p>I&apos;ve had an Insteon Garage Door Control and Status kit for over a decade and I have never trusted it.  It consists of an Insteon controllable relay and a single reed switch that could tell you if the door was closed.  It would occasionally stop opening after about a quarter of the way and with the single reed switch the interface indicated everything was great even though the neighbor you were trying to remotely let in had to do some crawling. Integration with Alexa is done via my ISY994 (just discontinued) and when Alexa recently decided to ignore one of my doors I thought I should <s>waste</s> spend some time looking for a new solution.</p><p>After motorizing the awing over my deck and integrating it with Home Assistant&apos;s MQTT Cover interface I noticed it supported positioning so it could tell you exactly what percent open it was if you could somehow supply that info. I knew then I wanted to track whether the garage is opening/closing, what percent opened/closed it is, if it got stuck in the middle, and whether it&apos;s definitely fully opened or closed.  And with many other ways of controlling things (car clickers, wall controls, outdoor keypad, safety sensors, and previously mentioned ISY control) I didn&apos;t want the code to assume it knew what was going on, just accurately report the current state of things.</p><p>I decided on a couple reed switches so I could tell for certain when it was fully open or fully closed and planned to measure the rotation of the sprocket (mine&apos;s chain driven though should similar for belt and might need some creative magnet placement for screw) with some magnets and hall effect sensors.  A DIY rotary encoder I guess.  From the direction of rotation we can determine whether the door is opening or closing and its position based on the rotation count.  Toss in a relay, ESP32 and some micropython code and the next stop should be the Ultimate Garage Door Control.</p><p>See it in action below.  Obviously a run-away scooter is no match for the Ultimate Garage Door Control...</p><figure class="kg-card kg-video-card kg-width-regular kg-card-hascaption" data-kg-thumbnail="https://tech.scarey.net/content/images/2023/05/media-thumbnail-ember2088.jpg" data-kg-custom-thumbnail>
            <div class="kg-video-container">
                <video src="https://tech.scarey.net/content/media/2023/05/UltimateGarageDoorControl-2.mp4" poster="https://img.spacergif.org/v1/720x1248/0a/spacer.png" width="720" height="1248" playsinline preload="metadata" style="background: transparent url(&apos;https://tech.scarey.net/content/images/2023/05/media-thumbnail-ember2088.jpg&apos;) 50% 50% / cover no-repeat;"></video>
                <div class="kg-video-overlay">
                    <button class="kg-video-large-play-icon">
                        <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                            <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                        </svg>
                    </button>
                </div>
                <div class="kg-video-player-container">
                    <div class="kg-video-player">
                        <button class="kg-video-play-icon">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M23.14 10.608 2.253.164A1.559 1.559 0 0 0 0 1.557v20.887a1.558 1.558 0 0 0 2.253 1.392L23.14 13.393a1.557 1.557 0 0 0 0-2.785Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-pause-icon kg-video-hide">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <rect x="3" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                                <rect x="14" y="1" width="7" height="22" rx="1.5" ry="1.5"/>
                            </svg>
                        </button>
                        <span class="kg-video-current-time">0:00</span>
                        <div class="kg-video-time">
                            /<span class="kg-video-duration">0:45</span>
                        </div>
                        <input type="range" class="kg-video-seek-slider" max="100" value="0">
                        <button class="kg-video-playback-rate">1&#xD7;</button>
                        <button class="kg-video-unmute-icon">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M15.189 2.021a9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h1.794a.249.249 0 0 1 .221.133 9.73 9.73 0 0 0 7.924 4.85h.06a1 1 0 0 0 1-1V3.02a1 1 0 0 0-1.06-.998Z"/>
                            </svg>
                        </button>
                        <button class="kg-video-mute-icon kg-video-hide">
                            <svg xmlns="http://www.w3.org/2000/svg" viewbox="0 0 24 24">
                                <path d="M16.177 4.3a.248.248 0 0 0 .073-.176v-1.1a1 1 0 0 0-1.061-1 9.728 9.728 0 0 0-7.924 4.85.249.249 0 0 1-.221.133H5.25a3 3 0 0 0-3 3v2a3 3 0 0 0 3 3h.114a.251.251 0 0 0 .177-.073ZM23.707 1.706A1 1 0 0 0 22.293.292l-22 22a1 1 0 0 0 0 1.414l.009.009a1 1 0 0 0 1.405-.009l6.63-6.631A.251.251 0 0 1 8.515 17a.245.245 0 0 1 .177.075 10.081 10.081 0 0 0 6.5 2.92 1 1 0 0 0 1.061-1V9.266a.247.247 0 0 1 .073-.176Z"/>
                            </svg>
                        </button>
                        <input type="range" class="kg-video-volume-slider" max="100" value="100">
                    </div>
                </div>
            </div>
            <figcaption><p><span style="white-space: pre-wrap;">Home Assistant custom cards. No cats were harmed during the production of this video.</span></p></figcaption>
        </figure><p>The rotation and position sensing could also be useful (perhaps more useful since you&apos;d rarely want to open your garage 30%...) for control of other covers such as awnings, etc.</p><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, <a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>, or whatever ESP32 you prefer (can handle up to 3 garage doors)</li><li>2x <a href="https://amzn.to/44PNQ2W?ref=tech.scarey.net" rel="noreferrer">Reed Switches</a> per door</li><li>2x <a href="https://amzn.to/3BDS8fO?ref=tech.scarey.net">Hall Effect Sensors</a> per door</li><li><a href="https://amzn.to/3OnuBaO?ref=tech.scarey.net">Small magnets</a> - at least 2x per door depending on mounting (6x per door for me, 8x for quadrature encoding)</li><li><a href="https://amzn.to/3MbRr2e?ref=tech.scarey.net">Single channel relay</a> or <a href="https://amzn.to/3OFgKMT?ref=tech.scarey.net">Mini Relay Shield</a> - 1x per door, though a <a href="https://amzn.to/42MdzXX?ref=tech.scarey.net">2 channel relay</a> simplifies things for a 2 door setup</li><li><a href="https://amzn.to/45vVM9f?ref=tech.scarey.net">Extension wire</a> - this is handy for the reed switches</li><li><a href="https://amzn.to/3J5LGmb?ref=tech.scarey.net">CAT6 cable</a> - optional, handy for 8x 23 gauge wires to a second door</li><li><a href="https://amzn.to/43knm8x?ref=scareys-tech">Dupont wires</a></li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="which-way-is-the-door-really-moving">Which way is the door really moving?</h2><p>Maybe new garage door controllers are smart let you know exactly what&apos;s going on but mine is dumb.  Let&apos;s face it...with my only interface to the garage door being a button, all I can command it to do is &quot;GO&quot; and it decides based on its internal state what it should do.  Here&apos;s what my Chamberlain Liftmaster Professional will do when you press the button:</p><ul><li>Open if fully closed, close if fully opened (perfect)</li><li>Stop if it was opening, open if it was closing (interesting)</li><li>Close if it was stopped (makes sense after the above bullet)</li></ul><p>I figured if I could detect the direction it was moving and whether it was fully opened, or fully closed I&apos;d be in great shape to build some smart controls.  Fully opened or closed?  Pretty simple.  Moving and in what direction?  Hmmm.  After some googling I found posts 9 and 17 here:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://forum.arduino.cc/t/how-to-tell-direction-of-rotation-using-x2-hall-effect-sensors/899590/8?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">How to tell direction of rotation using X2 hall effect sensors?</div><div class="kg-bookmark-description">Not when the pulses don&#x2019;t overlap. On both A edges the B input will be LOW. On both B edges the A input will be LOW. I can see how it might work if the pulses overlapped. The &#x201C;rising&#x201D; edge of A would have B LOW in one direction and B HIGH in the other. The &#x201C;falling&#x201D; edge would have the opposite&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://europe1.discourse-cdn.com/arduino/optimized/3X/1/f/1f6eb1c9b79d9518d1688c15fe9a4b7cdd5636ae_2_180x180.svg" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">Arduino Forum</span><span class="kg-bookmark-publisher">altha</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://europe1.discourse-cdn.com/arduino/original/3X/1/f/1f6eb1c9b79d9518d1688c15fe9a4b7cdd5636ae.svg" alt="Ultimate Garage Door Control"></div></a></figure><p>It was very helpful and offered 2 basic ways of figuring out direction of rotation. One way for each of my garage doors...lovely!  Both ways involve 2 hall effect sensors with one way using timing and a single magnet, and the other using 2 magnets and precise positioning.  If you think you can achieve the precise positioning for your setup then go with the quadrature encoding, otherwise the timing based method is perfectly good too.  The config.json let&apos;s you specify which rotation algorithm you want per door.</p><p>There were some good comments on Hackaday about other ways to detect direction of movement using an <a href="https://amzn.to/3N6D1Cb?ref=tech.scarey.net">Absolute Value Encoder</a> or magnetic or inductive proximity switches though it&apos;s likely you&apos;d have to update the rotation code.</p><hr><h2 id="wiring">Wiring</h2><p>There&apos;s are good amount of wiring to be done...2 per reed switch, 3 per hall effect sensor, 5 per relay so 15 per door.  5 are ground, 3 are power, 5 are IO, and 2 for the garage opener relay.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/05/Garage_bb-2.png" class="kg-image" alt="Ultimate Garage Door Control" loading="lazy" width="963" height="1571" srcset="https://tech.scarey.net/content/images/size/w600/2023/05/Garage_bb-2.png 600w, https://tech.scarey.net/content/images/2023/05/Garage_bb-2.png 963w" sizes="(min-width: 720px) 720px"></figure><h3 id="relay-wiring">Relay Wiring</h3><p>On the relay you need wires from NO (normally open) and C (common). You&apos;ll have to find the contacts on the opener that will trigger the door. See assembly pics below for what mine looked like.  If you can follow a wire from the wall buttons wherever that wire goes would be the terminals you want.  For a proper connection you should pigtail the new relay wires to whatever wires are currently connected.  I didn&apos;t bother with a latching relay since I figured the opener itself would lose power along with the relay.  If you are worried about the relay accidentally triggering when the ESP32 loses power then feel free to tweak the code and get a latching relay instead.  I just noticed the single channel relays I link to above let you set whether to trigger high or low and default to high.  The trigger high won&apos;t have the problem of triggering when the ESP32 loses power but you&apos;ll have to change the code to initialize to low and the trigger code to set high then low. </p><h3 id="additional-doors">Additional doors</h3><p>The ESP32 has enough IO to handle 3 doors though the farther away they are the more you&apos;ll need to worry about wire gauge. Power-wise you can add a 5v source closer to the other doors, just make sure to run that ground back to the ESP32 as well.  You can also put an ESP32 at each door and would just need to adjust the base topic name. </p><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Ultimate Garage Door Control"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/0bce9f5a4c2f1875cdc15a33f26c7c3ab7d5de32030fdc6b3dfea72e728874a4/peterhinch/micropython-mqtt" alt="Ultimate Garage Door Control"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/ultimate-garage-door-control?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/ultimate-garage-door-control: Micropython code for controlling your garage door including direction and position sensing.</div><div class="kg-bookmark-description">Micropython code for controlling your garage door including direction and position sensing. - GitHub - scarey/ultimate-garage-door-control: Micropython code for controlling your garage door includi&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/db9a01b1375bfd375e17ed2cebf208c393f7bd727a6b20852948f320f4108de1/scarey/ultimate-garage-door-control" alt="Ultimate Garage Door Control"></div></a></figure><p>Grab *.py and upload them to the root of the ESP32.  Copy config.json.example to config.json and update the pin config if necessary and the &quot;clockwiseOpen&quot; and &quot;quadrature&quot; based on your installation.  Upload the config.json to the root of the ESP32.  To change the relay timing and the number of rotations it takes to fully open/close the door you publish a JSON document to the esp32/garage/config topic and code will reconfigure on the fly.</p><pre><code class="language-json">{
  &quot;relay_ms&quot;: 500,
  &quot;full_rotations&quot;: 21
}</code></pre><hr><h2 id="assembly">Assembly</h2><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/05/timing.png" width="2000" height="1038" loading="lazy" alt="Ultimate Garage Door Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/05/timing.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/05/timing.png 1000w, https://tech.scarey.net/content/images/size/w1600/2023/05/timing.png 1600w, https://tech.scarey.net/content/images/size/w2400/2023/05/timing.png 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/05/control_terminals.png" width="2000" height="1316" loading="lazy" alt="Ultimate Garage Door Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/05/control_terminals.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/05/control_terminals.png 1000w, https://tech.scarey.net/content/images/size/w1600/2023/05/control_terminals.png 1600w, https://tech.scarey.net/content/images/size/w2400/2023/05/control_terminals.png 2400w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/05/20230528_145616.jpg" width="2000" height="2667" loading="lazy" alt="Ultimate Garage Door Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/05/20230528_145616.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/05/20230528_145616.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/05/20230528_145616.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/05/20230528_145616.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/05/20230519_102850.jpg" width="2000" height="2667" loading="lazy" alt="Ultimate Garage Door Control" srcset="https://tech.scarey.net/content/images/size/w600/2023/05/20230519_102850.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/05/20230519_102850.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/05/20230519_102850.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/05/20230519_102850.jpg 2400w" sizes="(min-width: 720px) 720px"></div></div></div></figure><p>A lot of the assembly depends on your garage door setup.  For the door reed switches I put the closed switch at the top center and the opened switch on the rail using a 3d printed rail bracket.  You&apos;ll have to figure out what works best for your setup.  </p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:4715574?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Clip for garage door tracks by fantadler</div><div class="kg-bookmark-description">Recently bought a smart garage door opener that required a magnetic sensor to determine closed state. The magnetic sensor comes in pairs. One screwed into the garage door wood frame and the other taped to the door track. The double sided tape didn&#x2019;t really work. Too many vibrations and it fell off a&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/96/30/ea/22/e9/featured_preview_garage_door_track_clip.png" alt="Ultimate Garage Door Control"></div></a></figure><p>I was trying to figure out a good way of placing the hall effect sensors above the sprocket and my initial thought was something like helping hands.  I don&apos;t remember how but I ended up finding this gantry crane for model trains and thought this could work!</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:535197?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Gantry Crane by nrandal</div><div class="kg-bookmark-description">A gantry crane for loading and unloading train cars. The CAD drawings are of the latest version, which match the STL files. The pictures of the printed crane are of my first version. The main difference are improvements to the winch.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/renders/d9/17/6e/ad/a6/Gantry_preview_featured.jpg" alt="Ultimate Garage Door Control"></div></a></figure><p>I modified the legs to be shorter and accept magnets to keep it solidly attached above the sprocket.  I&apos;ll post that STL file below.  I printed a carriage for each sensor and a small case to hold the sensor and taped that to the carriage.</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2023/05/short_gantry_leg.stl" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">Short gantry leg</div><div class="kg-file-card-caption"></div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">short_gantry_leg.stl</div><div class="kg-file-card-filesize">29 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:2902487?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Hall Effect Sensor Case Wheel Speed Sensors by UCI_FSAE_3DPrinting</div><div class="kg-bookmark-description">This case is used to enclose KY-003 hall effect sensors to be used as wheel speed sensors. The headers were removed from the board and wires were soldered on. A trigger wheel with magnets is attached to the hub on the inside of the upright and the wheel speed sensor is bonded to the upright itself w&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/renders/01/6d/cc/51/ad/d5d7082a7702f778a739a2a5ce0541a1_preview_featured.jpg" alt="Ultimate Garage Door Control"></div></a></figure><p><em>A note of warning:  It&apos;s a good idea to unplug the opener while working near the drive mechanism.  My sprocket has a protective cover that I had to remove. You&apos;ll have to be extra careful now and in the future as the sprocket is more exposed than it would normally be.</em></p><h3 id="magnet-positioning">Magnet positioning</h3><p><strong>Timing algorithm</strong></p><p>With the timing based method you can place a single magnet (I double stack them for a stronger magnetic field and to allow the sensors to be farther from the sprocket) anywhere near the outer edge of the sprocket.  You want to offset the hall effect sensors so they are closer to the edge of the sprocket.   In general you want the magnet to trigger one sensor and then the second after about 90&#xB0; rotation.  The remaining 270&#xB0; shouldn&apos;t trigger anything.  Positioning isn&apos;t that important as long they don&apos;t trigger close to 180&#xB0; apart.</p><p><strong>Quadrature encoding algorithm</strong></p><p>You need two magnets on opposite edges of the sprocket.  Try to arrange them in a perfect line across the center of the sprocket.  Place the hall effect sensors above them then push one magnet a little to one side.  The goal is to make sure the sensors are triggering in the proper pattern A on, B on, A off, B off.  You may need to adjust the magnets a little more until it works.  And if you don&apos;t want to bother with such precision the Timing algorithm works just fine.</p><hr><h2 id="home-assistant">Home Assistant</h2><h3 id="mqtt-cover-config">MQTT Cover config</h3><pre><code class="language-yaml">mqtt:
  cover:
  - unique_id: &apos;garage0&apos;
    name: &quot;Dads Garage&quot;
    command_topic: &quot;esp32/garage/0/set&quot;
    position_topic: &quot;esp32/garage/0/position&quot;
    state_topic: &quot;esp32/garage/0/state&quot;
    availability:
      - topic: &quot;esp32/garage/availability&quot;
    payload_open: &quot;open&quot;
    payload_close: &quot;close&quot;
    payload_stop: &quot;stop&quot;
    optimistic: false</code></pre><h3 id="custom-cover-module">Custom Cover module</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/marcelhoogantink/enhanced-shutter-card?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - marcelhoogantink/enhanced-shutter-card: A Enhanced Shutter Card for Home Assistant</div><div class="kg-bookmark-description">A Enhanced Shutter Card for Home Assistant. Contribute to marcelhoogantink/enhanced-shutter-card development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.githubassets.com/assets/pinned-octocat-093da3e6fa40.svg" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">marcelhoogantink</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/0a27f8c11c4196de3d5cda8d25fe0a1209f15933310c53f815abe5d0316bddb7/marcelhoogantink/enhanced-shutter-card" alt="Ultimate Garage Door Control"></div></a></figure><p>The default cover card should work fine but this module is much cooler than that since we have exact position information and it can show exactly how much the door is open in real time.  The card config looks something like this.  You would need to tweak the state settings if your garage doesn&apos;t behave like mine.</p><pre><code class="language-yaml">type: custom:enhanced-shutter-card
entities:
  - entity: cover.dads_garage
    name: Dad&apos;s Garage
    buttons_position: left
    title_position: top
    stop_disabled_states:
      - open
      - closed
      - closing
    up_disabled_states:
      - open
      - opening
    down_disabled_states:
      - closed
      - closing
      - opening</code></pre><h3 id="stopped-state">Stopped state</h3><p>The Home Assistant cover interface doesn&apos;t support the stopped state as an end state.  It assumes stopped means that it finished whatever the last action was.  For my garage door&apos;s behavior it would make more sense to have stopped as a real end state so I could disable up and stop actions when the door is stopped. As it is, it will show the stop and close buttons when it&apos;s stopped and pressing either will make the door close. Oh well, maybe I need to put in a request for a new Home Assistant cover feature. </p><h3 id="notification-options">Notification options</h3><p>MQTT makes it easy to setup notification for whatever you want.</p><ul><li>I&apos;ve got some Node-RED automation that texts me if the garage doors are open at midnight.  I should probably just change that to send a closed to the doors at midnight.  The safety sensors should prevent squashing anyone.</li><li>You could also set up a rule to let you know if the door is open for more than a certain amount of time.</li><li>Simple opened/closed notifications if you are interested knowing every time there&apos;s a state change</li></ul><h3 id="alexa">Alexa</h3><p>I guess I&apos;d have to recommend the Home Assistant Cloud even though it&apos;s $65 a year.  The DIY part of me is unhappy but the manual integration is not for the faint of heart.  I did get things working and it helped that I have already developed some simple Alexa Skills.  Here&apos;s the guide showing both options.  If you&apos;re using something other than Home Assistant there might be simpler/cheaper integration.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.home-assistant.io/integrations/alexa/?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Amazon Alexa</div><div class="kg-bookmark-description">Instructions on how to connect Alexa/Amazon Echo to Home Assistant.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.home-assistant.io/images/favicon-192x192.png" alt="Ultimate Garage Door Control"><span class="kg-bookmark-author">Home Assistant</span><span class="kg-bookmark-publisher">Home Assistant</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.home-assistant.io/images/default-social.png" alt="Ultimate Garage Door Control"></div></a></figure><pre><code class="language-yaml">alexa:
  smart_home:
    locale: en-US
    endpoint: https://api.amazonalexa.com/v3/events
    filter:
      include_entities:
        - cover.dads_garage
        - cover.moms_garage
    entity_config:
      cover.dads_garage:
        name: &quot;Dads Garage&quot;
      cover.moms_garage:
        name: &quot;Moms Garage&quot;</code></pre><hr><h2 id="notes">Notes</h2><ul><li>A LoRa based clicker for the car would be cool.  The range on my normal car clicker is pretty poor.</li><li>I should integrate the rotation stuff with my awning controller.</li><li>Now that I&apos;m exhausted from pressing garage buttons and telling Alexa to open and close the garage I&apos;m thinking it would be cool if the door would auto-close once it detects the car left.  And I guess auto-open when it gets back home. Some kind of proximity sensor in the car...how does the Bat Cave work anyway?</li></ul>]]></content:encoded></item><item><title><![CDATA[Time-lapse - Intervalometer]]></title><description><![CDATA[<p>I guess one of the few good things about COVID is you find new stuff to do while you&apos;re stuck at home.  I had previously taken  some decent pics of a blood moon and while I was googling the best camera settings to use for that I came</p>]]></description><link>https://tech.scarey.net/time-lapse/</link><guid isPermaLink="false">64370011de203c00016881d0</guid><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Sun, 30 Apr 2023 15:39:30 GMT</pubDate><media:content url="https://tech.scarey.net/content/images/2023/04/StarStaX_IMG_9883-IMG_9988_gap_filling.jpg" medium="image"/><content:encoded><![CDATA[<img src="https://tech.scarey.net/content/images/2023/04/StarStaX_IMG_9883-IMG_9988_gap_filling.jpg" alt="Time-lapse - Intervalometer"><p>I guess one of the few good things about COVID is you find new stuff to do while you&apos;re stuck at home.  I had previously taken  some decent pics of a blood moon and while I was googling the best camera settings to use for that I came across stuff about star trail photography.  It turns out the best way to get a good one is to take a lot of pics over time and stitch them all together.  It&apos;s like time lapse photography except you take all the photos and combine them into one instead of making a movie or something out of all the individual pics.</p><p>And the best way to do that is with an intervalometer, which is basically an automated shutter release.  Tell it to press the shutter button for 30 seconds and release...and repeat that 100 more times please.  A little bit more googling and it turns out I just need to complete the circuit to the shutter release pin on my Canon DSLR camera...sounds like a piece of cake!</p><p>The tricky part is mainly what kind of interface you want to dial in your settings. How long to hold the shutter open, how much of a delay between pics, and how many pics to take?  Battery life could be a concern depending on how long of a time lapse you have in mind.  I just needed something that could last an hour or so to get star movement like you see above.</p><p>I&apos;d guess the camera built into your phone wouldn&apos;t do a great job with these dark, long exposure pics.  What we&apos;ll be building here is for SLR cameras with a manual shutter release option.</p><p><em>Disclaimer: I&apos;ve tested this with my Canon 6D but you need to verify the pinouts for the camera you have!</em></p><hr><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/04/StarStaX_IMG_0867-IMG_0964_gap_filling2-1.jpg" class="kg-image" alt="Time-lapse - Intervalometer" loading="lazy" width="2000" height="1333" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/StarStaX_IMG_0867-IMG_0964_gap_filling2-1.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/StarStaX_IMG_0867-IMG_0964_gap_filling2-1.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/04/StarStaX_IMG_0867-IMG_0964_gap_filling2-1.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/04/StarStaX_IMG_0867-IMG_0964_gap_filling2-1.jpg 2400w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Facing north</span></figcaption></figure><p>There&apos;s a cool looking dilapidated house from the 1800&apos;s(?) a little right of center at the bottom but it came out completely black.  I think I&apos;ll try it again and shine a flashlight on it in a frame at the beginning of the time-lapse. </p><hr><h2 id="supplies">Supplies</h2><p>I&apos;m tempted to suggest some ESP32 dev board with a built in display but I&apos;m just going to describe what I&apos;ve already got working.</p><ul><li><a href="https://www.dfrobot.com/product-1590.html?ref=tech.scarey.net">FireBeetle ESP32</a> - very good for low power consumption</li><li><a href="https://amzn.to/41T6qoy?ref=tech.scarey.net">KY-040 Rotary Encoder</a> - For selection of config options</li><li><a href="https://amzn.to/41LCHhc?ref=tech.scarey.net">OLED Display</a> - 0.96&quot; 128x64 - Display config menu and status</li><li><a href="https://amzn.to/3HIBW0v?ref=tech.scarey.net">Battery with JST connector</a> - or something similar (the FireBeetle has built-in charging circuitry for a solar panel, etc.)  You also need to be careful as sometimes the +/- the FireBeetle wants are swapped on the battery.</li><li>Optional - <a href="https://amzn.to/40M3hFD?ref=tech.scarey.net">JST wires</a> - I used these to make an adapter to switch the battery +/- instead of permanently rewiring the battery</li><li>Optional - <a href="https://amzn.to/3HIBW0v?ref=tech.scarey.net">LiPo battery charger</a> - you can plug a USB cable into the FireBeetle and it will charge the attached battery.  This will work if you want an external charger for whatever reason.</li><li>Optional - <a href="https://amzn.to/3HIBW0v?ref=tech.scarey.net">Solar panel</a> - this is an option for a long timelapse session during the day</li><li><a href="https://amzn.to/3HIBW0v?ref=tech.scarey.net">Shutter release</a> - get a cheap one since we just want the camera connector.  This works for my Canon camera.  I would assume other camera manufacturers are similar but you&apos;ll need to figure out what pinouts are right for your brand/model.</li><li><a href="https://amzn.to/40M3hFD?ref=tech.scarey.net">Optocoupler</a> - this provides a small measure of isolation between the ESP32 and the camera and could protect the camera in case of a short circuit.</li><li><a href="https://amzn.to/43knm8x?ref=scareys-tech">Dupont wires</a></li><li><a href="https://amzn.to/40UtUYW?ref=tech.scarey.net">Multimeter</a> - helpful for finding the correct shutter release wires </li><li>Soldering iron</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><hr><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/04/Timelapse_bb-2.png" width="916" height="1324" loading="lazy" alt="Time-lapse - Intervalometer" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/Timelapse_bb-2.png 600w, https://tech.scarey.net/content/images/2023/04/Timelapse_bb-2.png 916w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/04/Timelapse_schem-1.png" width="845" height="1072" loading="lazy" alt="Time-lapse - Intervalometer" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/Timelapse_schem-1.png 600w, https://tech.scarey.net/content/images/2023/04/Timelapse_schem-1.png 845w" sizes="(min-width: 720px) 720px"></div></div></div></figure><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Time-lapse - Intervalometer"></div></div></a></figure><h3 id="ssd1306-driver">ssd1306 driver</h3><p>Grab that from <a href="https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/Others/OLED/ssd1306.py?ref=scareys-tech">here</a> and upload to the root of the ESP32.</p><h3 id="micropython-rotary">micropython-rotary</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/MikeTeachman/micropython-rotary?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - miketeachman/micropython-rotary: MicroPython module to read a rotary encoder.</div><div class="kg-bookmark-description">MicroPython module to read a rotary encoder. . Contribute to miketeachman/micropython-rotary development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Time-lapse - Intervalometer"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">miketeachman</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/f5380e67b56be555359227c8620f87c129174f13ff94177673c2e60dbdf2f5d0/miketeachman/micropython-rotary" alt="Time-lapse - Intervalometer"></div></a></figure><p>Grab rotary.py and rotary_irq_esp.py and upload them to the ESP32.</p><h3 id="micropython-encoder-based-menu">Micropython encoder based menu</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/sgall17a/encodermenu?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - sgall17a/encodermenu: Simple GUI menu for micropython using a rotary encoder and basic display.</div><div class="kg-bookmark-description">Simple GUI menu for micropython using a rotary encoder and basic display. - GitHub - sgall17a/encodermenu: Simple GUI menu for micropython using a rotary encoder and basic display.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Time-lapse - Intervalometer"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">sgall17a</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://repository-images.githubusercontent.com/350277372/81678d00-9868-11eb-9fce-9536fecb1bd0" alt="Time-lapse - Intervalometer"></div></a></figure><p>For reference only.  The configuration isn&apos;t well decoupled so I&apos;ve included a modified copy in my repo below.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/time-lapse?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/time-lapse: Micropython code for taking time-lapse photos with your SLR</div><div class="kg-bookmark-description">Micropython code for taking time-lapse photos with your SLR - GitHub - scarey/time-lapse: Micropython code for taking time-lapse photos with your SLR</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Time-lapse - Intervalometer"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/0c6aa846164ca3dcfb52e0f1ca8ced2dce2eefab37e339f46bf7ba2d79f1155a/scarey/time-lapse" alt="Time-lapse - Intervalometer"></div></a></figure><p>Grab main.py and encoder_menu.py and upload them to the root of the ESP32.</p><hr><h2 id="assembly">Assembly</h2><ul>
<li>Cut the shutter release cable a few inches below the controls.  I figured having that few inches would make it easier to re-use the controls for some other project.</li>
<li>Find your camera&apos;s shutter release pinouts.  You need to determine the ground and shutter pins.  A lot of info can be found here: <a href="https://web.archive.org/web/20250216001855/http://doc-diy.net/photo/eos_wired_remote/">https://web.archive.org/web/20250216001855/http://doc-diy.net/photo/eos_wired_remote/</a></li>
<li>Figure out which wires are shutter and ground in the shutter release cable you cut.  The multimeter comes in handy here along with a staple or some other thin piece of metal to poke into the small holes in the shutter release connector.</li>
<li>Solder the optocoupler (orient so the small dot in the corner is at the top left) :
<ul>
<li>pin 1 (top left) - to IO25 on the FireBeetle.</li>
<li>pin 2 (bottom left) - to ground on the FireBeetle.</li>
<li>pin 3 (bottom right) - to ground wire of shutter release cable</li>
<li>pin 4 (top right) - to shutter release wire of shutter release cable</li>
</ul>
</li>
<li>Connect the OLED display and rotary encoder as shown in the wiring diagram.</li>
</ul>
<hr><h2 id="camera-settings">Camera Settings</h2><p>A great reference is:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.davemorrowphotography.com/2012/03/StarTrailsPhotographyTutorial.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Star Trails Photography in 7 SIMPLE Steps [2023]</div><div class="kg-bookmark-description">In this guide, you&#x2019;ll learn star trails photography in 7 simple steps. See what&#x2019;s working in 2023 for: Camera settings Equipment Shooting locations And more Scroll down &amp; get started... Table of Contents
Click on the section of your choice or scroll down &amp; rea</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://www.davemorrowphotography.com/wp-content/uploads/2021/04/cropped-icon-1-270x270.png" alt="Time-lapse - Intervalometer"><span class="kg-bookmark-author">Dave Morrow Photography</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://www.davemorrowphotography.com/wp-content/uploads/2021/01/star-trails-photography3.jpg" alt="Time-lapse - Intervalometer"></div></a></figure><p>The intervalometer settings I use are 100 pictures, 30 second exposure, 1 second delay in between and the camera set to:</p><ul><li>Shutter speed: Manual/Bulb</li><li>Aperture: 2.8 if no moonlight, 5.6 if some moonlight</li><li>ISO: 300</li><li>Manual focus - infinity works well for me though there are devices like this to help with accurate focus.  See below.</li></ul><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:1308669?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Bahtinov Mask for astro-photography by adibadro</div><div class="kg-bookmark-description">Perfect for astro-photography! If your camera has a long lens, enough pixels and you enjoy the night sky, this is for you!
Based on a 58mm Canon lens cap. Should fit any camera lens by resizing it in the XY plane. Easy to use:
place it on the lens
point towards a bright object
manually focus for the&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Time-lapse - Intervalometer"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/renders/e9/a4/58/be/94/f986f19de1a12462adc694cd18fd809e_preview_featured.jpg" alt="Time-lapse - Intervalometer"></div></a></figure><hr><h2 id="software">Software</h2><p>I liked this free software that can stitch the individual photos together.  I used Blending Mode -&gt; Gap Filling but feel free to play around with the settings.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://markus-enzweiler.de/software/starstax/?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">StarStaX &#x2013; Markus Enzweiler</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://markus-enzweiler.de/wp-content/uploads/2019/12/cropped-cityscapes-example-270x270.jpg" alt="Time-lapse - Intervalometer"></div></div><div class="kg-bookmark-thumbnail"><img src="https://markus-enzweiler.de/wp-content/uploads/2019/12/starstax-icon.png" alt="Time-lapse - Intervalometer"></div></a></figure>]]></content:encoded></item><item><title><![CDATA[Mail's Here!]]></title><description><![CDATA[<p>I can&apos;t see my mailbox from my house so I thought it might be nice to get a notification when it opens.  Initially I had an ESP32 connecting over WiFi but it had poor signal strength and I wanted to try LoRa and it&apos;s working well.</p>]]></description><link>https://tech.scarey.net/mail-is-here/</link><guid isPermaLink="false">64448c04de203c000168820c</guid><category><![CDATA[LoRa]]></category><category><![CDATA[esp32]]></category><category><![CDATA[micropython]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Mon, 24 Apr 2023 00:54:50 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1595087012935-124877078142?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fG1haWxib3h8ZW58MHx8fHwxNjgyMjU2MTM3&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1595087012935-124877078142?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDV8fG1haWxib3h8ZW58MHx8fHwxNjgyMjU2MTM3&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Mail&apos;s Here!"><p>I can&apos;t see my mailbox from my house so I thought it might be nice to get a notification when it opens.  Initially I had an ESP32 connecting over WiFi but it had poor signal strength and I wanted to try LoRa and it&apos;s working well.  I added a solar panel and rechargable battery and use deep sleep mode and it&apos;s been running itself for months.  I&apos;m using Micropython, MQTT, Node-RED, and Twilio.</p><hr><h2 id="supplies">Su<strong>p</strong>plies</h2><h3 id="lora-dev-boards">Lora Dev Boards</h3><p>You need one board to transmit and another to receive.  If you already have a LoRa Gateway (I don&apos;t) then you would only need 1 dev board.  You also need to make sure you get a board that uses the frequencies allowed in your country.  See <a href="https://www.thethingsnetwork.org/docs/lorawan/frequencies-by-country/?ref=tech.scarey.net">here</a> for what frequencies are allowed in what countries.</p><p><em>Make sure to attach the LoRa antenna before powering up!  Not having the antenna connected can damage the LoRa chip.</em></p><p>For the US and others this board does 868 or 915MHz:</p><ul><li>2x <a href="https://amzn.to/3n5AXjz?ref=tech.scarey.net">ESP32 Development Board SX1262 868 915MHz LoRaWAN</a></li></ul><p>See some other frequency options can be found here:</p><ul><li>2x <a href="https://heltec.org/project/wifi-lora-32-v3/?ref=tech.scarey.net">WiFi LoRa 32 (V3)</a></li></ul><h3 id="common-components">Common components</h3><ul><li><a href="https://amzn.to/40vGCgz?ref=tech.scarey.net">Reed switch</a></li><li><a href="https://www.amazon.com/dp/B0867KDMY7?ref=ppx_yo2ov_dt_b_product_details&amp;th=1">3.7V 1100mAh Lithium Rechargeable Battery Micro JST 1.25</a> or the LoRa boards come with a JST 1.25 wire connector you could attach to some other rechargable battery like an <a href="https://amzn.to/3oEge71?ref=tech.scarey.net">18650</a> but you should get something with built-in charge protection.</li><li>Optional <a href="https://amzn.to/40yduFi?ref=tech.scarey.net">Solar panel</a></li><li>Soldering iron - The dev board comes without the header pins soldered.  The solar panel would also need some wire soldered on.</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><p>The Heltec dev board is pretty cool with the integrated display and battery charging though the documentation was lacking.  For the V3 board even the pinout diagram was incorrect but hopefully they&apos;ll fix it soon.  I looked through the Meshtastic firmware code to find the correct ports for the display and SX1262 LoRa module.</p><p>Only the sender board near the mailbox needs any wiring.  The receiver board simply relays anything it gets from the transmitter to MQTT.</p><p>The only required wiring is for the reed switch.  One wire from the reed switch normally open goes to pin 6 and the other wire to ground.</p><p>The solar panel I wired into 5V and ground.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/07/20230715_100233--2023-07-15T14_53_28.486-.png" class="kg-image" alt="Mail&apos;s Here!" loading="lazy" width="2000" height="1503" srcset="https://tech.scarey.net/content/images/size/w600/2023/07/20230715_100233--2023-07-15T14_53_28.486-.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/07/20230715_100233--2023-07-15T14_53_28.486-.png 1000w, https://tech.scarey.net/content/images/size/w1600/2023/07/20230715_100233--2023-07-15T14_53_28.486-.png 1600w, https://tech.scarey.net/content/images/size/w2400/2023/07/20230715_100233--2023-07-15T14_53_28.486-.png 2400w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="code">Code</h2><p>I made the receiver code generic and it will pass whatever LoRa messages it receives to a default MQTT topic or if the message contains a &quot;source&quot; field it will use that as the sub topic.  I figure some future project might need long range wireless and I wanted to be able to re-use the same receiver.</p><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Mail&apos;s Here!"></div></div></a></figure><h3 id="micropysx126x">micropySX126X</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/ehong-tl/micropySX126X?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - ehong-tl/micropySX126X: Semtech SX126X LoRa driver for Micropython and CircuitPython.</div><div class="kg-bookmark-description">Semtech SX126X LoRa driver for Micropython and CircuitPython. - GitHub - ehong-tl/micropySX126X: Semtech SX126X LoRa driver for Micropython and CircuitPython.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">ehong-tl</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/82875c74a30effabfa767482256ac3857de017816ca7b2037943d7eabd0b9b55/ehong-tl/micropySX126X" alt="Mail&apos;s Here!"></div></a></figure><p>Grab sx1262.py, sx126x.py, and _sx126x.py, make the changes sx126x.py described below, and upload them to the root of the ESP32 without the subdirs.</p><pre><code class="language-text">6c6
&lt;     from machine import SPI, Pin
---
&gt;     from machine import SoftSPI, Pin
44c44
&lt;               self.spi = SPI(spi_bus, mode=SPI.MASTER, baudrate=2000000, pins=(clk, mosi, miso))        # Pycom variant uPy
---
&gt;               self.spi = SoftSPI(spi_bus, mode=SPI.MASTER, baudrate=2000000, pins=(clk, mosi, miso))        # Pycom variant uPy
46c46
&lt;               self.spi = SPI(spi_bus, baudrate=2000000, sck=Pin(clk), mosi=Pin(mosi), miso=Pin(miso))   # Generic variant uPy
---
&gt;               self.spi = SoftSPI(baudrate=2000000, sck=Pin(clk), mosi=Pin(mosi), miso=Pin(miso))   # Generic variant uPy</code></pre><h3 id="receiver-only-micropython-mqtt">Receiver only: micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/b5e7500b7706496ce43acf186a81dfc713281479c1604277c92d2be2e730ed5e/peterhinch/micropython-mqtt" alt="Mail&apos;s Here!"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><figure class="kg-card kg-code-card"><pre><code class="language-python">config[&apos;server&apos;] = &apos;&lt;broker hostname&gt;&apos;

config[&apos;ssid&apos;] = &apos;&lt;SSID&gt;&apos;
config[&apos;wifi_pw&apos;] = &apos;&lt;WiFi password&gt;&apos;
config[&apos;ssl&apos;] = &lt;True | False&gt;
config[&apos;port&apos;] = &lt;broker port&gt;
config[&apos;user&apos;] = &apos;&lt;broker user&gt;&apos;
config[&apos;password&apos;] = &apos;&lt;broker password&gt;&apos;</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample mqtt_local.py updates.</span></p></figcaption></figure><h3 id="receiver-only-ssd1306-driver">Receiver only: ssd1306 driver</h3><p>Grab that from <a href="https://raw.githubusercontent.com/RuiSantosdotme/ESP-MicroPython/master/code/Others/OLED/ssd1306.py?ref=tech.scarey.net">here</a> and upload to the root of the ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/mail-is-here?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/mail-is-here: Micropython code for sending notifications when your mailbox opens.</div><div class="kg-bookmark-description">Micropython code for sending notifications when your mailbox opens. - GitHub - scarey/mail-is-here: Micropython code for sending notifications when your mailbox opens.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/074d9b755e623c7ecfda4b2eaa5351e171dc6f2110e1bcbd0111cc4e26c81c4e/scarey/mail-is-here" alt="Mail&apos;s Here!"></div></a></figure><p>Grab jram.py and either sender or receiver main.py and upload them to the root of the ESP32.</p><hr><h2 id="mounting">Mounting</h2><ul><li>Figure out a good spot for the reed switch.  I put the magnet on the left side of the lid near the hinge and the switch nearby on the body.</li><li>Stuff the ESP32 and battery in a small project box.  I used double sided tape and mounted the box under the mailbox.</li><li>I 3D printed some bits and pieces to mount the solar panel behind the mailbox.</li></ul><figure class="kg-card kg-bookmark-card kg-card-hascaption"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:5819772?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Heltec WiFi LoRa 32 (V3) minimal case, more room for antenna cable by mrtamer</div><div class="kg-bookmark-description">I slightly modified the great original design to fit the 10cm antenna cable better to the enclosure.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/03/ca/d8/e9/95/featured_preview_8873ddd4-12be-4674-bad5-cf85bf0a9bf9.png" alt="Mail&apos;s Here!"></div></a><figcaption><p><span style="white-space: pre-wrap;">Cute case for the receiver</span></p></figcaption></figure><figure class="kg-card kg-bookmark-card kg-card-hascaption"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:4921568/files?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Waterproof electronic box / enclosure by pbtec</div><div class="kg-bookmark-description">Stable and waterproof / watertight OpenSCAD customizer case / box / enclosure V6.1 by pbtec
Edit December 2022: Updated Version 6.1 --&gt; Seems Openscad has in certain circumstances problem with special characters (like &#xE4;) in comments&#x2026;. Created new fixed version 6.1 (Nothing else has changed)
Latest n&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/49/b7/28/da/94/featured_preview_Sample1-UltimateWaterproofCase_V6.png" alt="Mail&apos;s Here!"></div></a><figcaption><p><span style="white-space: pre-wrap;">I used this near the mailbox</span></p></figcaption></figure><hr><h2 id="notifications">Notifications</h2><p>See my Laundry&apos;s Done post for some notification options.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://tech.scarey.net/laundry-is-done"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Laundry&#x2019;s Done!</div><div class="kg-bookmark-description">Well there&#x2019;s still folding and stuff left but getting notified when the washer/dryer cycle finished was one of my first projects and is a big hit with the wife. An accelerometer detects when motion has ceased and sends a notification. I&#x2019;m using micropython with an ESP32, MQTT, Home Assistant,</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://tech.scarey.net/content/images/size/w256h256/2023/04/cpu.png" alt="Mail&apos;s Here!"><span class="kg-bookmark-author">Scarey&apos;s Tech</span><span class="kg-bookmark-publisher">Stephen Carey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1626806819282-2c1dc01a5e0c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHdhc2hlcnxlbnwwfHx8fDE2Nzk3NzE4NjE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Mail&apos;s Here!"></div></a></figure><p>I use Node-RED to keep track of how many times the mailbox has opened each day and send a different message to different recipients.  I included my kids in the hopes that they might actually be helpful and get the mail some days but they seemed to ignore them along with all my other texts.  I included my neighbors on the first open of the day and they did appreciate that.</p><p>And one day I didn&apos;t get a package I was expecting via USPS and noticed that they said it was delivered 1 minute before I got my notification.  I pinged my neighbor and sure enough he got it.  Just a happy benefit of knowing when your mailbox opens.</p><p>Here&apos;s what my Node-RED flow looks like.  Let me know if it could be improved...I&apos;m not yet an expert:</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/04/mail-flow-1.png" class="kg-image" alt="Mail&apos;s Here!" loading="lazy" width="1212" height="494" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/mail-flow-1.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/mail-flow-1.png 1000w, https://tech.scarey.net/content/images/2023/04/mail-flow-1.png 1212w" sizes="(min-width: 720px) 720px"></figure><p>Download the flow here:</p><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2023/05/mail-flow.json" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">Mail flow</div><div class="kg-file-card-caption">Node-RED mail flow</div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">mail-flow.json</div><div class="kg-file-card-filesize">10 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><p>Here&apos;s what the texts look like:</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/04/tempFileForShare_20230423-150307.jpg" class="kg-image" alt="Mail&apos;s Here!" loading="lazy" width="1205" height="601" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/tempFileForShare_20230423-150307.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/tempFileForShare_20230423-150307.jpg 1000w, https://tech.scarey.net/content/images/2023/04/tempFileForShare_20230423-150307.jpg 1205w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="notes">Notes</h2><ul><li>Feel free to tweak what&apos;s on the display and/or add display for the sender.  I figured I would just stuff it somewhere out of sight though it&apos;s handy for initial debugging.</li></ul>]]></content:encoded></item><item><title><![CDATA[Ultrasonic Home Heating Oil Gauge]]></title><description><![CDATA[<p>An ultrasonic sensor sends a sound pulse that bounces off the oil and returns to the sensor.  The amount of time that it takes can be measured and based on the speed of sound you can figure out the distance.  Neat.  It&apos;s nothing as grand as the pic</p>]]></description><link>https://tech.scarey.net/ultrasonic-sensing-of-heating-oil-tank-level/</link><guid isPermaLink="false">642b5e5c9274c70001ba91ee</guid><category><![CDATA[HC-SR04]]></category><category><![CDATA[micropython]]></category><category><![CDATA[esp32]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Wed, 12 Apr 2023 02:50:41 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1516199423456-1f1e91b06f25?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fG9pbHxlbnwwfHx8fDE2ODA1NjYwNDE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1516199423456-1f1e91b06f25?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDF8fG9pbHxlbnwwfHx8fDE2ODA1NjYwNDE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Ultrasonic Home Heating Oil Gauge"><p>An ultrasonic sensor sends a sound pulse that bounces off the oil and returns to the sensor.  The amount of time that it takes can be measured and based on the speed of sound you can figure out the distance.  Neat.  It&apos;s nothing as grand as the pic above, I&apos;m just measuring the levels in my 275 gallon tank at home. I once caught the oil guy filling my tank and he was impressed when I guessed within 2 gallons of his fill reading.</p><p>I&apos;m using micropython with an ESP32, MQTT, and Zabbix to keep historical data though I recently switched to InfluxDB.</p><hr><figure class="kg-card kg-gallery-card kg-width-wide"><div class="kg-gallery-container"><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/04/sensor-1.jpg" width="1396" height="1802" loading="lazy" alt="Ultrasonic Home Heating Oil Gauge" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/sensor-1.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/sensor-1.jpg 1000w, https://tech.scarey.net/content/images/2023/04/sensor-1.jpg 1396w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/04/sight-glass-1.jpg" width="1081" height="1622" loading="lazy" alt="Ultrasonic Home Heating Oil Gauge" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/sight-glass-1.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/sight-glass-1.jpg 1000w, https://tech.scarey.net/content/images/2023/04/sight-glass-1.jpg 1081w" sizes="(min-width: 720px) 720px"></div></div><div class="kg-gallery-row"><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/04/zabbix-oil.jpg" width="2000" height="762" loading="lazy" alt="Ultrasonic Home Heating Oil Gauge" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/zabbix-oil.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/zabbix-oil.jpg 1000w, https://tech.scarey.net/content/images/size/w1600/2023/04/zabbix-oil.jpg 1600w, https://tech.scarey.net/content/images/size/w2400/2023/04/zabbix-oil.jpg 2400w" sizes="(min-width: 720px) 720px"></div><div class="kg-gallery-image"><img src="https://tech.scarey.net/content/images/2023/06/influxdb-oil.png" width="803" height="439" loading="lazy" alt="Ultrasonic Home Heating Oil Gauge" srcset="https://tech.scarey.net/content/images/size/w600/2023/06/influxdb-oil.png 600w, https://tech.scarey.net/content/images/2023/06/influxdb-oil.png 803w" sizes="(min-width: 720px) 720px"></div></div></div></figure><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/403CMLg?ref=tech.scarey.net">ESP32 Mini</a></li><li><a href="https://amzn.to/3zRXB1D?ref=tech.scarey.net">HC-SR04</a> Ultrasonic Sensor</li><li><a href="https://amzn.to/3mwYCsT?ref=tech.scarey.net">OLED Display</a> - 0.91 Inch I2C SSD1306 (Optional, could be added later w/o much trouble)</li><li>Soldering iron</li><li><a href="https://amzn.to/43knm8x?ref=tech.scarey.net">Dupont wires</a></li><li><a href="https://www.mclendons.com/2717278/product/plumb-pak-pp855-41?ref=tech.scarey.net">Rubber packing sheet</a> (1/16&quot; - holds and seals the ultrasonic sensor)</li><li>PVC parts: <a href="https://www.homedepot.com/p/Charlotte-Pipe-2-in-PVC-Schedule-40-MPT-x-S-Male-Adapter-PVC-02109-1600HD/203825431?ref=tech.scarey.net">male threaded adapter</a> (bottom), <a href="https://www.homedepot.com/p/Charlotte-Pipe-2-in-PVC-DWV-FTG-Cleanout-Adapter-with-Cleanout-Plug-PVC-00105X-0800HD/203944996?ref=tech.scarey.net">cleanout adapter</a> (top) for whatever size your tank needs.  Mine was 2&quot;.</li><li><a href="https://amzn.to/43nhuv3?ref=tech.scarey.net">PVC Cement</a></li><li><a href="https://amzn.to/43snp2c?ref=tech.scarey.net">Pipe Thread Sealant</a></li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/04/OilMonitor_bb_crop.png" class="kg-image" alt="Ultrasonic Home Heating Oil Gauge" loading="lazy" width="641" height="876" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/OilMonitor_bb_crop.png 600w, https://tech.scarey.net/content/images/2023/04/OilMonitor_bb_crop.png 641w"></figure><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Ultrasonic Home Heating Oil Gauge"></div></div></a></figure><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/013e68098f110670486ce8396c4ddcd6cbb1374b0d44542acd3861a35099c270/peterhinch/micropython-mqtt" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and mqtt_as/mqtt_local.py and upload them to the root of the ESP32 without the subdirs.  We&apos;ll need to tweak mqtt_local.py with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><figure class="kg-card kg-code-card"><pre><code class="language-python">config[&apos;server&apos;] = &apos;&lt;broker hostname&gt;&apos;

config[&apos;ssid&apos;] = &apos;&lt;SSID&gt;&apos;
config[&apos;wifi_pw&apos;] = &apos;&lt;WiFi password&gt;&apos;
config[&apos;ssl&apos;] = &lt;True | False&gt;
config[&apos;port&apos;] = &lt;broker port&gt;
config[&apos;user&apos;] = &apos;&lt;broker user&gt;&apos;
config[&apos;password&apos;] = &apos;&lt;broker password&gt;&apos;</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample mqtt_local.py updates.</span></p></figcaption></figure><h3 id="micropython-hcsr04">micropython-hcsr04</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/rsc1975/micropython-hcsr04?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - rsc1975/micropython-hcsr04: Micropython driver for ultrasonic sensor HC-SR04</div><div class="kg-bookmark-description">Micropython driver for ultrasonic sensor HC-SR04. Contribute to rsc1975/micropython-hcsr04 development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">rsc1975</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/b79c3b36877caf36369a5f89bffffb77dba9991a8801a7dc5e4b9be08493d862/rsc1975/micropython-hcsr04" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><p>Grab hcsr04.py and upload it.</p><h3 id="micropython-ssd1306-optional-if-not-using-display">micropython-ssd1306 (optional if not using display)</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/stlehmann/micropython-ssd1306?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - stlehmann/micropython-ssd1306: A fork of the driver for SSD1306 displays to make it installable via upip</div><div class="kg-bookmark-description">A fork of the driver for SSD1306 displays to make it installable via upip - GitHub - stlehmann/micropython-ssd1306: A fork of the driver for SSD1306 displays to make it installable via upip</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">stlehmann</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/809c764f04ebc4dd5ca7620499db0c01ef6961b81bc4c5f338f0c15bb5470a92/stlehmann/micropython-ssd1306" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><p>Grab ssd1306.py and upload it.</p><h3 id="micropython-nano-gui-optional-if-not-using-display">micropython-nano-gui (optional if not using display)</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-nano-gui?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-nano-gui: A lightweight MicroPython GUI library for display drivers based on framebuf class</div><div class="kg-bookmark-description">A lightweight MicroPython GUI library for display drivers based on framebuf class - GitHub - peterhinch/micropython-nano-gui: A lightweight MicroPython GUI library for display drivers based on fram&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/a440656aec40aa09a230534af26aa82f58603564b7e0142edcc55f7d66c24ac4/peterhinch/micropython-nano-gui" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><p>Grab drivers/boolpalette.py and gui/core/writer.py and upload them to the root of your ESP32 without the subdirs.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/heating-oil-gauge?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/heating-oil-gauge: Micropython code for reading home heating oil levels with an ultrasonic sensor.</div><div class="kg-bookmark-description">Micropython code for reading home heating oil levels with an ultrasonic sensor. - GitHub - scarey/heating-oil-gauge: Micropython code for reading home heating oil levels with an ultrasonic sensor.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/cd0f6366cc9ca85143b3fe0d27a8c883578fe11a0a64ba6820b878ae8ded93cb/scarey/heating-oil-gauge" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><hr><h2 id="historical-data">Historical Data</h2><p>I have a old Zabbix server which has a couple years of oil data but I&apos;m moving to InfluxDB and Telegraf for new projects.  In the images above you can see a sample of each. </p><p>A dashboard with the outside temperature, thermostat call history, and oil tank levels can be very interesting to look at.  Or maybe after your teenager just took a 45 minute shower you can take a peek at how much that just cost &#x1F926;.</p><figure class="kg-card kg-code-card"><pre><code class="language-toml">[[outputs.influxdb_v2]]
  urls = [&quot;http://&lt;host&gt;:8086&quot;]
  token = &quot;&lt;your token&gt;&quot;
  organization = &quot;&lt;your org&gt;&quot;
  bucket = &quot;iot&quot;

[[inputs.mqtt_consumer]]
  servers = [&quot;mqtts://&lt;host&gt;:&lt;port&gt;&quot;]
  topics = [
    &quot;esp32/oil/gallons&quot;,
  ]
  qos = 0
  username = &quot;telegraf&quot;
  password = &quot;&lt;mqtt password&gt;&quot;
  insecure_skip_verify = false
  data_format = &quot;value&quot;
  data_type = &quot;float&quot;
  topic_tag = &quot;&quot;

[[inputs.mqtt_consumer.topic_parsing]]
  topic = &quot;esp32/oil/gallons&quot;
  tags = &quot;source/_/field&quot;
  measurement = &quot;_/measurement/_&quot;
  fields = &quot;_/_/gallons&quot;
  [[processors.pivot]]
    tag_key = &quot;field&quot;
    value_key = &quot;value&quot;
</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample telegraf configuration</span></p></figcaption></figure><hr><h2 id="notifications">Notifications</h2><p>See my Laundry&apos;s Done post for some notification options.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://tech.scarey.net/laundry-is-done/"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Laundry&#x2019;s Done!</div><div class="kg-bookmark-description">Well there&#x2019;s still folding and stuff left but getting notified when the washer/dryer cycle finished was one of my first projects and is a big hit with the wife. An accelerometer detects when motion has ceased and sends a notification. I&#x2019;m using micropython with an ESP32, MQTT, Home Assistant,</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://tech.scarey.net/content/images/size/w256h256/2023/04/cpu.png" alt="Ultrasonic Home Heating Oil Gauge"><span class="kg-bookmark-author">Scarey&apos;s Tech</span><span class="kg-bookmark-publisher">Stephen Carey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://images.unsplash.com/photo-1626806819282-2c1dc01a5e0c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHdhc2hlcnxlbnwwfHx8fDE2Nzk3NzE4NjE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Ultrasonic Home Heating Oil Gauge"></div></a></figure><p>An obvious notification would be when your tank meets some low level threshold and it&apos;s time to order a fill.  A fun one could be a fill notification maybe using InfluxDB to detect a large increase over a short time.  Or a more frightening large decrease over a short time! </p><hr><h2 id="assembly">Assembly</h2><h3 id="pvc">PVC</h3><p>The ultrasonic sensor is mounted face down on a rubber disc with the transmitter and receiver pushed through holes in the disc.  The rubber disc is inserted into the lower adapter and the cleanout adapter is cemented on top to form the enclosure. The ESP32 will be inside the cleanout and the whole thing will be screwed into an available spot in the top of the tank. The top plug will allow easy access to the ESP32 and the rubber disc isolates the oil from the majority of the electronics. Mine&apos;s been running non-stop for more than 3 years now.</p><ol><li>Use the inside of the wide end of the lower adapter as a template (probably about 2.375&quot;) and cut a circle out of the rubber sheet.  The goal is to have a rubber disc that can fit nicely inside the lower adapter.</li><li>Using the ultrasonic sensor as a template, center it on the newly cut rubber disc and mark a circle for the transmitter and one for the receiver.  Cut those circles and insert the sensor into the holes.  To give yourself more room you could change out the sensor pins so they point straight out the back of the sensor.</li><li>Connect your dupont wires to the sensor and insert the disc into the lower adapter as far down as it will go.  Maybe use some thread sealant around the edge of the rubber disc if it isn&apos;t making a good seal.</li><li>Cement the cleanout adapter to the upper side of the lower adapter.  I added some duct tape around the 2 pieces for some added elegance.</li><li>Drill a hole below the threads of the cleanout adapter so you can run the power wiring.  I made a hole big enough to fit a micro USB cable through.</li><li>Remove a plug from the top of the oil tank, put some pipe thread sealant around the threads of the lower adapter of the enclosure and screw it on the tank.</li><li>Estimate how far the ultrasonic sensor is from the top of the inside of the tank and save that number for SENSOR_OFFSET in main.py.</li></ol><h3 id="display-mount-optional-if-not-using-display">Display mount (optional if not using display)</h3><ol><li>Figure out which side you want the power wiring to exit and drill another hole where you&apos;d like the display.</li><li>You can 3D print the display mount that I modified if you like or come up with some other mount.  You can grab it below.</li></ol><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2023/04/OLED-Oil.stl" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">OLED Oil</div><div class="kg-file-card-caption">OLED display mount with a curved base that will be pretty flush with PVC column.</div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">OLED-Oil.stl</div><div class="kg-file-card-filesize">59 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><hr><h2 id="notes">Notes</h2><ul><li>My tank is an upright 275 gallon tank that&apos;s pretty common for residential use in the US.  The inches_to_gallons.py contains a dictionary of oil height in 0.1 inch increments to the number of gallons of oil that represents.  If you&apos;re tank is different you&apos;ll have to create your own dictionary and also tweak MAX_INCHES in main.py which is used to detect bad readings.  And of course rename stuff if you&apos;re using cm and liters, etc.  You also don&apos;t need to go that crazy with the precision as long as you round the measurement to a value in the inches_to_gallons dictionary.</li><li>I&apos;ve included some code to detect readings that seem off and do a retry.  That seems to work well for my setup but you could change that to averaging multiple readings or whatever you think would work better.</li></ul>]]></content:encoded></item><item><title><![CDATA[Laundry's Done!]]></title><description><![CDATA[<p>Well there&apos;s still folding and stuff left but getting notified when the washer/dryer cycle finished was one of my first projects and is a big hit with the wife.  An accelerometer detects when motion has ceased and sends a notification.  I&apos;m using micropython with an</p>]]></description><link>https://tech.scarey.net/laundry-is-done/</link><guid isPermaLink="false">641f4845e3d57f0001781744</guid><category><![CDATA[GY-521]]></category><category><![CDATA[micropython]]></category><category><![CDATA[esp32]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Mon, 03 Apr 2023 01:47:53 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1626806819282-2c1dc01a5e0c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHdhc2hlcnxlbnwwfHx8fDE2Nzk3NzE4NjE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<img src="https://images.unsplash.com/photo-1626806819282-2c1dc01a5e0c?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDN8fHdhc2hlcnxlbnwwfHx8fDE2Nzk3NzE4NjE&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Laundry&apos;s Done!"><p>Well there&apos;s still folding and stuff left but getting notified when the washer/dryer cycle finished was one of my first projects and is a big hit with the wife.  An accelerometer detects when motion has ceased and sends a notification.  I&apos;m using micropython with an ESP32, MQTT, Home Assistant, and Twilio to send text messages but you can adapt any or all of those to suit your needs.</p><hr><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/03/mini-accel.jpg" class="kg-image" alt="Laundry&apos;s Done!" loading="lazy" width="1471" height="1086" srcset="https://tech.scarey.net/content/images/size/w600/2023/03/mini-accel.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/03/mini-accel.jpg 1000w, https://tech.scarey.net/content/images/2023/03/mini-accel.jpg 1471w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Cute huh?</span></figcaption></figure><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/3GDBGiB?ref=tech.scarey.net">GY-521</a> - Accelerometer/Gyroscope</li><li><a href="https://amzn.to/3nZSBoZ?ref=tech.scarey.net">ESP32 Mini</a> - Perfect small package to mount the GY-521 on</li><li>Soldering iron</li><li>Double sided tape</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><h2 id="wiring">Wiring</h2><p>There are no actual wires per se...  Solder one of the female pin headers to the ESP32 Mini row that has VCC/GND.  Then break off a 4 pin strip of male headers and solder that to VCC&lt;-&gt;SDA on the GY-521 (make sure the pins are oriented properly so the GY-521 will hang above the ESP32).  Then insert the GY-521 onto the ESP32 Mini making sure you&apos;ve lined up VCC/GND and you&apos;ll end up with SCL on IO16 and SDA on IO17.  That&apos;s it!</p><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Laundry&apos;s Done!"></div></div></a></figure><h3 id="mpu6050-esp8266-micropython">MPU6050-ESP8266-MicroPython</h3><figure class="kg-card kg-bookmark-card kg-card-hascaption"><a class="kg-bookmark-container" href="https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - adamjezek98/MPU6050-ESP8266-MicroPython: Simple library for MPU6050 on ESP8266 with micropython</div><div class="kg-bookmark-description">Simple library for MPU6050 on ESP8266 with micropython - GitHub - adamjezek98/MPU6050-ESP8266-MicroPython: Simple library for MPU6050 on ESP8266 with micropython</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Laundry&apos;s Done!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">adamjezek98</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/c99e482ccf7bb3293b8b72039677afc563c1c2d05747a7b955c2ecea52ed2c40/adamjezek98/MPU6050-ESP8266-MicroPython" alt="Laundry&apos;s Done!"></div></a><figcaption><p><span style="white-space: pre-wrap;">https://github.com/adamjezek98/MPU6050-ESP8266-MicroPython</span></p></figcaption></figure><p>Grab mpu6050.py and upload that to your ESP32.</p><h3 id="micropython-mqtt">micropython-mqtt</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/peterhinch/micropython-mqtt?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - peterhinch/micropython-mqtt: A &#x2018;resilient&#x2019; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets.</div><div class="kg-bookmark-description">A &amp;#39;resilient&amp;#39; asynchronous MQTT driver. Plus a means of using an ESP8266 to bring MQTT to non-networked targets. - GitHub - peterhinch/micropython-mqtt: A &amp;#39;resilient&amp;#39; asynchronous M&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Laundry&apos;s Done!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">peterhinch</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/122a57140371d1332de0719d92ff759dbc8ac7de0fa83f8dd41d5749d0ad32c5/peterhinch/micropython-mqtt" alt="Laundry&apos;s Done!"></div></a></figure><p>Grab mqtt_as/mqtt_as.py and upload that to your ESP32.  Grab mqtt_as/mqtt_local.py but we&apos;ll need to tweak that with your WiFi and MQTT broker settings.</p><p>Update 4/20/25: The latest version of micropython-mqtt has been restructured.  Now grab mqtt_as/__init__.py and upload it to the same path on the ESP32.  Tweak mqtt_local_example.py with your WiFi and MQTT broker settings and upload that as mqtt_local.py to the root of your ESP32.</p><figure class="kg-card kg-code-card"><pre><code class="language-python">config[&apos;server&apos;] = &apos;&lt;broker hostname&gt;&apos;

config[&apos;ssid&apos;] = &apos;&lt;SSID&gt;&apos;
config[&apos;wifi_pw&apos;] = &apos;&lt;WiFi password&gt;&apos;
config[&apos;ssl&apos;] = &lt;True | False&gt;
config[&apos;port&apos;] = &lt;broker port&gt;
config[&apos;user&apos;] = &apos;&lt;broker user&gt;&apos;
config[&apos;password&apos;] = &apos;&lt;broker password&gt;&apos;</code></pre><figcaption><p><span style="white-space: pre-wrap;">Sample mqtt_local.py updates.</span></p></figcaption></figure><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/laundry-is-done?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/laundry-is-done</div><div class="kg-bookmark-description">Contribute to scarey/laundry-is-done development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Laundry&apos;s Done!"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/15e9cb6beaf1efb528762b8fd00c391e434d1993cd98b774bd9e49ecee9bf82d/scarey/laundry-is-done" alt="Laundry&apos;s Done!"></div></a></figure><p>Grab main.py and upload it to the root of your ESP32.</p><p><em>Update 06/25/23</em>: Publish configuration to esp32/washer/config with retain set. You need to tweak the &quot;sensitivity&quot; based on your washer/dryer and lower it if it thinks it&apos;s done too early.  Increase it if it never thinks it&apos;s done.  You can also increase the &quot;maxIdlePeriods&quot; if necessary (it&apos;s the number of samples in a row that need to be less than the &quot;sensitivity&quot; to be considered all done).</p><figure class="kg-card kg-code-card"><pre><code class="language-json">{
  &quot;sensitivity&quot;: 100,
  &quot;sampleSecs&quot;: 10,
  &quot;maxIdlePeriods&quot;: 6
}</code></pre><figcaption><p><span style="white-space: pre-wrap;">esp32/washer/config</span></p></figcaption></figure><hr><h2 id="home-assistant">Home Assistant</h2><h3 id="mqtt-integration">MQTT Integration</h3><p>I have a <a href="https://mosquitto.org/?ref=tech.scarey.net">Mosquitto </a>MQTT broker running and integrated with HA.  For the interface I just added a text field to show the last acceleration values to make fine-tuning easier and a switch to enable the monitoring.</p><figure class="kg-card kg-code-card"><pre><code class="language-yaml">mqtt:
  sensor:
  - unique_id: dryervib
    name: &quot;Dryer vibration&quot;
    unit_of_measurement: &quot;XYZ sum&quot;
    value_template: &gt;-
      {%- set parts = value[1:-1].split(&quot;,&quot;) -%}
      {{ int(parts[0]) + int(parts[1]) + int(parts[2]) }}
    state_topic: &quot;esp32/washer/readings/1&quot;

  switch:
  - unique_id: dryermon
    name: &quot;Dryer monitor&quot;
    state_topic: &quot;esp32/washer/active/1&quot;
    command_topic: &quot;esp32/washer/active/1/set&quot;
    availability:
    - topic: &quot;esp32/washer/status&quot;
    payload_on: &quot;on&quot;
    payload_off: &quot;off&quot;
    optimistic: false</code></pre><figcaption><p><span style="white-space: pre-wrap;">Home Assistant configuration.yaml</span></p></figcaption></figure><figure class="kg-card kg-image-card kg-card-hascaption"><img src="https://tech.scarey.net/content/images/2023/04/dryer-ha.jpg" class="kg-image" alt="Laundry&apos;s Done!" loading="lazy" width="1440" height="465" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/dryer-ha.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/dryer-ha.jpg 1000w, https://tech.scarey.net/content/images/2023/04/dryer-ha.jpg 1440w" sizes="(min-width: 720px) 720px"><figcaption><span style="white-space: pre-wrap;">Android Home Assistant app</span></figcaption></figure><h3 id="notification">Notification</h3><p>I use <a href="https://www.twilio.com/?ref=tech.scarey.net">Twilio</a> to send texts when motion has ceased.  It has good <a href="https://www.home-assistant.io/integrations/twilio_sms/?ref=tech.scarey.net">integration</a> with Home Assistant and you can use a simple HA Automation or I prefer <a href="https://nodered.org/?ref=tech.scarey.net">Node-Red</a>.</p><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/04/laundry-is-done-text.jpg" class="kg-image" alt="Laundry&apos;s Done!" loading="lazy" width="1175" height="380" srcset="https://tech.scarey.net/content/images/size/w600/2023/04/laundry-is-done-text.jpg 600w, https://tech.scarey.net/content/images/size/w1000/2023/04/laundry-is-done-text.jpg 1000w, https://tech.scarey.net/content/images/2023/04/laundry-is-done-text.jpg 1175w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="notes">Notes</h2><ul><li>You may need to tune the sensitivity and/or the number of idle periods if you find it is notifying before the cycle is done or never notifies.</li><li>If desired, separate accelerometers could be used for independent sensing of washer and dryer.  I haven&apos;t tried it but for the GY-521 I linked to it says connecting VCC to AD0 will change the address of the second module so they can both be used at the same time.</li><li>MQTT is my preferred way to have the ESP32 communicate.  You could have the ESP32 handle everything by maybe adding a physical button to start monitoring and directly make a request to Twilio or your wireless carrier to send a notification.</li><li>9/7/23 - I just updated to Home Assistant 2023.9.0 and it didn&apos;t like how I was separating the acceleration values so I updated the config above to combine XYZ into a single number.</li></ul>]]></content:encoded></item><item><title><![CDATA[Bass Reactive LEDs with Micropython and ESP32]]></title><description><![CDATA[<figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="200" height="113" src="https://www.youtube.com/embed/7DLm5iV5B64?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Bass Reactive LED demo"></iframe><figcaption><p><span style="white-space: pre-wrap;">A sampling of some different kinds of music &#xAB; Music: bensound.com &#xBB;</span></p></figcaption></figure><p>This is my take on creating some cool lighting for my car.  I thought it would be more interesting if the LEDs reacted only to the bass instead of simply the volume.  After a bunch of googling</p>]]></description><link>https://tech.scarey.net/bass-reactive-leds/</link><guid isPermaLink="false">6404b3a085eb760001d48f62</guid><category><![CDATA[GY-MAX4466]]></category><category><![CDATA[micropython]]></category><category><![CDATA[esp32]]></category><category><![CDATA[ulab]]></category><dc:creator><![CDATA[Stephen Carey]]></dc:creator><pubDate>Sun, 05 Mar 2023 15:41:31 GMT</pubDate><media:content url="https://images.unsplash.com/photo-1572249930263-64fc5bbdb14b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIxMXx8bGVkJTIwc3RyaXB8ZW58MHx8fHwxNjgyMzY4MTcw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" medium="image"/><content:encoded><![CDATA[<figure class="kg-card kg-embed-card kg-card-hascaption"><iframe width="200" height="113" src="https://www.youtube.com/embed/7DLm5iV5B64?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" allowfullscreen title="Bass Reactive LED demo"></iframe><figcaption><img src="https://images.unsplash.com/photo-1572249930263-64fc5bbdb14b?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=MnwxMTc3M3wwfDF8c2VhcmNofDIxMXx8bGVkJTIwc3RyaXB8ZW58MHx8fHwxNjgyMzY4MTcw&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=2000" alt="Bass Reactive LEDs with Micropython and ESP32"><p><span style="white-space: pre-wrap;">A sampling of some different kinds of music &#xAB; Music: bensound.com &#xBB;</span></p></figcaption></figure><p>This is my take on creating some cool lighting for my car.  I thought it would be more interesting if the LEDs reacted only to the bass instead of simply the volume.  After a bunch of googling I couldn&apos;t really find exactly what I wanted but I managed to piece things together from a bunch of sources.  See for yourself!</p><hr><h2 id="supplies">Supplies</h2><ul><li><a href="https://amzn.to/3wYcdyc?ref=tech.scarey.net" rel="noreferrer">GY-MAX4466</a> - Electret Microphone Amplifier Sensor Sound Module with Adjustable Gain Control</li><li><a href="https://amzn.to/3mp2Umj?ref=tech.scarey.net">ESP32 development board</a>, <a href="https://amzn.to/40382u6?ref=tech.scarey.net">ESP32 Mini</a>, or whatever ESP32 you prefer</li><li><a href="https://amzn.to/3mnkVBw?ref=tech.scarey.net">Neopixel strip</a> - You could go with IP65 or IP67 waterproofing but I went with the cheaper IP30 and so far so good.  I used 18 LEDs per footwell, 60 pixels per meter.</li><li><a href="https://amzn.to/41T6qoy?ref=tech.scarey.net">KY-040 Rotary Encoder Module</a></li><li>Capacitor (500&#x2013;1000 &#xB5;F at 6.3V or higher)</li><li>2 resistors (300-500&#x3A9;)</li><li>Soldering iron</li><li>Wire</li></ul><p><em>When you purchase through links on this site, I may earn an affiliate commission.</em></p><hr><h2 id="wiring">Wiring</h2><figure class="kg-card kg-image-card"><img src="https://tech.scarey.net/content/images/2023/03/ReactiveAudio_bb.png" class="kg-image" alt="Bass Reactive LEDs with Micropython and ESP32" loading="lazy" width="1364" height="1658" srcset="https://tech.scarey.net/content/images/size/w600/2023/03/ReactiveAudio_bb.png 600w, https://tech.scarey.net/content/images/size/w1000/2023/03/ReactiveAudio_bb.png 1000w, https://tech.scarey.net/content/images/2023/03/ReactiveAudio_bb.png 1364w" sizes="(min-width: 720px) 720px"></figure><hr><h2 id="compiling-the-firmware">Compiling the firmware</h2><p>The library I&apos;m using to analyze the sound is too big to be used as a normal module on the ESP32 and needs to be frozen into the firmware. Here&apos;s the guide I followed:</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/v923z/micropython-ulab?ref=tech.scarey.net#esp32-based-boards"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - v923z/micropython-ulab: a numpy-like fast vector module for micropython, circuitpython, and their derivatives</div><div class="kg-bookmark-description">a numpy-like fast vector module for micropython, circuitpython, and their derivatives - GitHub - v923z/micropython-ulab: a numpy-like fast vector module for micropython, circuitpython, and their de&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">v923z</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/8ca5357d8cb5f027fbf8f99f9936d94845fe7e310748915e38ae4fe71d23f37f/v923z/micropython-ulab" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><h3 id="this-did-the-trick-to-freeze-ulab-into-micropython-1191-on-my-ubuntu-22042-lts-system">This did the trick to freeze ulab into micropython 1.19.1 on my Ubuntu 22.04.2 LTS system :</h3><pre><code class="language-bash">sudo apt install cmake
cd ~/dev/git
git clone https://github.com/micropython/micropython.git
git clone https://github.com/v923z/micropython-ulab.git ulab
export BUILD_DIR=$(pwd)
cd micropython
git checkout v1.19.1
git clone -b v4.0.2 --recursive https://github.com/espressif/esp-idf.git
cd esp-idf/
sudo apt install python-is-python3
./install.sh 
. ./export.sh 
cd $BUILD_DIR/micropython/mpy-cross
make
cd $BUILD_DIR/micropython/ports/esp32
make submodules

# The next 6 lines are a single command
cat &lt;&lt;EOT &gt;&gt; makefile
BOARD = GENERIC
USER_C_MODULES = \$(BUILD_DIR)/ulab/code/micropython.cmake

include Makefile
EOT

make</code></pre><p>After building it will spit out the command to flash the firmware.</p><h3 id="or-download-the-firmware-i-built-here">Or download the firmware I built here:</h3><div class="kg-card kg-file-card"><a class="kg-file-card-container" href="https://tech.scarey.net/content/files/2023/03/build.tgz" title="Download" download><div class="kg-file-card-contents"><div class="kg-file-card-title">Build</div><div class="kg-file-card-caption">ESP32 micropython firmware 1.19.1 + ulab</div><div class="kg-file-card-metadata"><div class="kg-file-card-filename">build.tgz</div><div class="kg-file-card-filesize">982 KB</div></div></div><div class="kg-file-card-icon"><svg viewbox="0 0 24 24"><defs><style>.a{fill:none;stroke:currentColor;stroke-linecap:round;stroke-linejoin:round;stroke-width:1.5px;}</style></defs><title>download-circle</title><polyline class="a" points="8.25 14.25 12 18 15.75 14.25"/><line class="a" x1="12" y1="6.75" x2="12" y2="18"/><circle class="a" cx="12" cy="12" r="11.25"/></svg></div></a></div><p>After unpacking the files the flash command might look something like (replace &lt;PORT&gt; with your device&apos;s port, e.g. /dev/ttyUSB0):</p><pre><code class="language-bash">esptool.py -p &lt;PORT&gt; -b 460800 --before default_reset --after hard_reset write_flash --flash_mode dio --flash_size detect --flash_freq 40m 0x1000 build-GENERIC/bootloader/bootloader.bin 0x8000 build-GENERIC/partition_table/partition-table.bin 0x10000 build-GENERIC/micropython.bin</code></pre><hr><h2 id="code">Code</h2><h3 id="getting-started-with-micropython">Getting Started With Micropython</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://docs.micropython.org/en/latest/esp32/tutorial/intro.html?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">1. Getting started with MicroPython on the ESP32 &#x2014; MicroPython latest documentation</div><div class="kg-bookmark-description"></div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://docs.micropython.org/en/latest/_static/favicon.ico" alt="Bass Reactive LEDs with Micropython and ESP32"></div></div></a></figure><h3 id="micropython-rotary">micropython-rotary</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/MikeTeachman/micropython-rotary?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - miketeachman/micropython-rotary: MicroPython module to read a rotary encoder.</div><div class="kg-bookmark-description">MicroPython module to read a rotary encoder. . Contribute to miketeachman/micropython-rotary development by creating an account on GitHub.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">miketeachman</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/dd0d457039a9ca404f73a1479622bd61aaef1d54f535d116dcf68201af9de266/miketeachman/micropython-rotary" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><p>Grab rotary.py and rotary_irq_esp.py and upload them to the ESP32.</p><h3 id="this-projects-code">This project&apos;s code</h3><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://github.com/scarey/bass-reactive-leds?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">GitHub - scarey/bass-reactive-leds: Micropython code for bass reactive NeoPixel strips with an ESP32.</div><div class="kg-bookmark-description">Micropython code for bass reactive NeoPixel strips with an ESP32. - GitHub - scarey/bass-reactive-leds: Micropython code for bass reactive NeoPixel strips with an ESP32.</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://github.com/fluidicon.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">GitHub</span><span class="kg-bookmark-publisher">scarey</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://opengraph.githubassets.com/6005456c765024ed6af084719df20b8ea3e8c04bc87ceba37eb102a6be6f4b29/scarey/bass-reactive-leds" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><hr><h2 id="controls">Controls</h2><ul><li>Pressing on the rotary encoder will cycle through the modes</li><li>In the reactive mode, turning counter-clockwise will increase the sensitivity (higher brightness for less bass)</li><li>In the other modes, turning counter-clockwise will speed up the rainbow effects.</li></ul><hr><h2 id="notes">Notes</h2><h3 id="adc">ADC</h3><p>Note: The ESP32 has 2 ADC chips and ADC2 is shared with Wifi.  This project isn&apos;t using Wifi but if you wanted to tweak the code to add Wifi support you&apos;d want to move the mic to a pin using ADC1.  See <a href="https://docs.espressif.com/projects/esp-idf/en/v4.4/esp32/api-reference/peripherals/adc.html?ref=tech.scarey.net">here</a> for more details.</p><h3 id="mic">Mic</h3><p>There&apos;s a sensitivity adjustment on the back.  Turn counter-clockwise for more sensitivity.  Play with it and see what works best.</p><h3 id="power">Power</h3><p>With a 2 footwell setup I&apos;m powering from a USB port integrated into my car.  Depending on how many pixels you&apos;ve got planned you may want a 5V cigarette lighter adapter with at least 2 amps.</p><h3 id="more-strips">More strips</h3><p>The code assumes 2 strips.  If you wanted to add strips to the rear footwell or elsewhere you can just chain off the end of the left/right strip and increase the NUM_LEDS_PER by how many you&apos;re adding. </p><hr><h2 id="assembly-ideas">Assembly ideas</h2><p>For the car I went with a separate mic enclosure so I could more easily position it.</p><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:5634236?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">Mic Amp MAX4466 Enclosure by jgutz20</div><div class="kg-bookmark-description">a simple compact case for Max4466 breakout board/microphone. I&#x2019;m using mine attached to a project box for a WLED Sound Reactive setup. The enclosure has 2 small pins to line up the circuit board and hold it in place, on the bottom is a &#x201C;key&#x201D; for the lid to help keep the bottom end secured. Unde&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/5f/88/2f/b9/b8/featured_preview_1694643a-1ae4-4f43-a4f1-822137e5583a.jpg" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:4053731?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">KY-040 rotary encoder mounting block by The__Captain</div><div class="kg-bookmark-description">A simple mounting block for a KY-040 rotary encoder. This is basically useless by itself; it is meant to be attached to the inside of a device case/housing where a rotary encoder is needed. Just snug this up to the inside of your case model, and pop a 3.6mm radius hole in the case model with your&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/ef/ff/f9/f5/62/featured_preview_scsl7j0m.bmp" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><figure class="kg-card kg-bookmark-card"><a class="kg-bookmark-container" href="https://www.thingiverse.com/thing:5631371?ref=tech.scarey.net"><div class="kg-bookmark-content"><div class="kg-bookmark-title">ESP32 WLED Sound Reactive Box by jgutz20</div><div class="kg-bookmark-description">I&#x2019;ve seen quite a few ESP32 boxes out there, and even some that can accommodate a speaker for running WLED SR (Sound Reactive), but i wanted a box with a little bit more room.
I made this container/enclosure for those that want a little bit more room for using breadboard jumpers instead of soldering&#x2026;</div><div class="kg-bookmark-metadata"><img class="kg-bookmark-icon" src="https://cdn.thingiverse.com/site/img/favicons/favicon-192x192.png" alt="Bass Reactive LEDs with Micropython and ESP32"><span class="kg-bookmark-author">Thingiverse</span></div></div><div class="kg-bookmark-thumbnail"><img src="https://cdn.thingiverse.com/assets/b4/13/41/0f/87/featured_preview_2dcfd315-bf60-4257-bbf6-e3b85b6dc8b0.jpg" alt="Bass Reactive LEDs with Micropython and ESP32"></div></a></figure><h2 id="future-plans">Future plans</h2><ul><li>More modes</li><li>Bluetooth control?</li><li>Any suggestions?</li></ul>]]></content:encoded></item></channel></rss>