Files
swangnice_site/public/projects/embedded/pet_feeder/index.html

1488 lines
61 KiB
HTML
Raw Normal View History

2025-05-20 02:59:55 -04:00
<!DOCTYPE html>
2025-07-25 02:15:37 +08:00
<html lang="en" dir="ltr" class="scroll-smooth" data-default-appearance="light"
2025-08-05 13:24:21 +08:00
data-auto-appearance="true"><head>
2025-05-20 02:59:55 -04:00
<meta charset="utf-8" />
2025-07-25 02:15:37 +08:00
<meta http-equiv="content-language" content="en" />
2025-05-20 02:59:55 -04:00
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
2025-08-05 13:24:21 +08:00
<title>A pet feeder &middot; SWangNice</title>
<meta name="title" content="A pet feeder &middot; SWangNice" />
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<meta name="description" content="My awesome website (English)" />
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<link rel="canonical" href="http://localhost:1313/projects/embedded/pet_feeder/" />
<link rel="alternate" type="application/rss+xml" href="/projects/embedded/pet_feeder/index.xml" title="SWangNice" />
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<link type="text/css" rel="stylesheet" href="/css/main.bundle.min.3d98b0e3c7886b2be13facfb539c8f79843dd3cff84d1c41763deb363c668c308c7c7ac9ecb3923f8602e257866ff553de4228ff50492074acc6d07b3d232fb1.css"
integrity="sha512-PZiw48eIayvhP6z7U5yPeYQ908/4TRxBdj3rNjxmjDCMfHrJ7LOSP4YC4leGb/VT3kIo/1BJIHSsxtB7PSMvsQ==" />
2025-05-20 02:59:55 -04:00
<script type="text/javascript" src="/js/appearance.min.516a16745bea5a9bd011138d254cc0fd3973cd55ce6e15f3dec763e7c7c2c7448f8fe7b54cca811cb821b0c7e12cd161caace1dd794ac3d34d40937cbcc9ee12.js"
integrity="sha512-UWoWdFvqWpvQERONJUzA/TlzzVXObhXz3sdj58fCx0SPj&#43;e1TMqBHLghsMfhLNFhyqzh3XlKw9NNQJN8vMnuEg=="></script>
2025-07-25 02:15:37 +08:00
<script defer type="text/javascript" id="script-bundle" src="/js/main.bundle.min.f8f2cec11308434554dfdbe3a0963bc19265192ebb9e2d644f3f9250731c879dfb09b44d2d58fcd06e8a1c9051b57f594719b37d21689d366ffd2db050df40a0.js"
integrity="sha512-&#43;PLOwRMIQ0VU39vjoJY7wZJlGS67ni1kTz&#43;SUHMch537CbRNLVj80G6KHJBRtX9ZRxmzfSFonTZv/S2wUN9AoA==" data-copy="Copy" data-copied="Copied"></script>
2025-05-20 02:59:55 -04:00
<script src="/lib/zoom/zoom.min.f592a181a15d2a5b042daa7f746c3721acf9063f8b6acd175d989129865a37d400ae0e85b640f9ad42cd98d1f8ad30931718cf8811abdcc5fcb264400d1a2b0c.js" integrity="sha512-9ZKhgaFdKlsELap/dGw3Iaz5Bj&#43;Las0XXZiRKYZaN9QArg6FtkD5rULNmNH4rTCTFxjPiBGr3MX8smRADRorDA=="></script>
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png" />
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png" />
<link rel="manifest" href="/site.webmanifest" />
2025-08-05 13:24:21 +08:00
<meta property="og:url" content="http://localhost:1313/projects/embedded/pet_feeder/">
2025-07-25 02:15:37 +08:00
<meta property="og:site_name" content="SWangNice">
2025-08-05 13:24:21 +08:00
<meta property="og:title" content="A pet feeder">
<meta property="og:description" content="1. Project Photos &amp; Screenshots # The final project photo.">
2025-07-25 02:15:37 +08:00
<meta property="og:locale" content="en">
2025-05-20 02:59:55 -04:00
<meta property="og:type" content="website">
2025-08-05 13:24:21 +08:00
<meta property="og:image" content="http://localhost:1313/projects/embedded/pet_feeder/feature.jpg">
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<meta name="twitter:card" content="summary_large_image">
2025-08-05 13:24:21 +08:00
<meta name="twitter:image" content="http://localhost:1313/projects/embedded/pet_feeder/feature.jpg">
<meta name="twitter:title" content="A pet feeder">
<meta name="twitter:description" content="1. Project Photos &amp; Screenshots # The final project photo.">
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<meta name="author" content="SWang" />
<link href="https://swangnice.com" rel="me" />
<link href="https://github.com/swangnice" rel="me" />
2025-05-20 02:59:55 -04:00
<script src="/lib/jquery/jquery.slim.min.b0dca576e87d7eaa5850ae4e61759c065786cdb6489d68fcc82240539eebd5da522bdb4fda085ffd245808c8fe2acb2516408eb774ef26b5f6015fc6737c0ea8.js" integrity="sha512-sNylduh9fqpYUK5OYXWcBleGzbZInWj8yCJAU57r1dpSK9tP2ghf/SRYCMj&#43;KsslFkCOt3TvJrX2AV/Gc3wOqA=="></script>
<meta name="theme-color"/>
</head>
<body
class="flex flex-col h-screen px-6 m-auto text-lg leading-7 max-w-7xl bg-neutral text-neutral-900 dark:bg-neutral-800 dark:text-neutral sm:px-14 md:px-24 lg:px-32 scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600">
<div id="the-top" class="absolute flex self-center">
<a class="px-3 py-1 text-sm -translate-y-8 rounded-b-lg bg-primary-200 focus:translate-y-0 dark:bg-neutral-600"
href="#main-content"><span
2025-07-25 02:15:37 +08:00
class="font-bold text-primary-600 ltr:pr-2 rtl:pl-2 dark:text-primary-400">&darr;</span>Skip to main content</a>
2025-05-20 02:59:55 -04:00
</div>
<div style="padding-left:0;padding-right:0;padding-top:2px;padding-bottom:3px"
class="main-menu flex items-center justify-between px-4 py-6 sm:px-6 md:justify-start gap-x-3">
<div class="flex flex-1 items-center justify-between">
<nav class="flex space-x-3">
2025-07-25 02:15:37 +08:00
<a href="/" class="text-base font-medium text-gray-500 hover:text-gray-900">SWangNice</a>
2025-05-20 02:59:55 -04:00
</nav>
<nav class="hidden md:flex items-center gap-x-5 md:ml-12 h-12">
2025-08-05 13:24:21 +08:00
<a href="/about/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<p class="text-base font-medium" title="About">
About
2025-05-20 02:59:55 -04:00
</p>
</a>
2025-07-25 02:15:37 +08:00
<div>
<div class="cursor-pointer flex items-center nested-menu">
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<a href="/notes/" class="text-base font-medium text-gray-500 hover:text-primary-600 dark:hover:text-primary-400" title="Notes">
Notes
</a>
<span>
<span class="relative block icon">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
</span>
</span>
</div>
<div class="absolute menuhide">
<div class="pt-2 p-5 mt-2 rounded-xl backdrop-blur shadow-2xl">
<div class="flex flex-col space-y-3">
<a href="/notes/coding/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
Coding
</p>
</a>
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<a href="/notes/pdf/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
PDF Collection
</p>
</a>
</div>
</div>
</div>
</div>
<div>
<div class="cursor-pointer flex items-center nested-menu">
<a href="/projects/" class="text-base font-medium text-gray-500 hover:text-primary-600 dark:hover:text-primary-400" title="Projects">
Projects
</a>
<span>
2025-05-20 02:59:55 -04:00
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
2025-05-20 02:59:55 -04:00
</span>
</span>
2025-07-25 02:15:37 +08:00
</div>
<div class="absolute menuhide">
<div class="pt-2 p-5 mt-2 rounded-xl backdrop-blur shadow-2xl">
<div class="flex flex-col space-y-3">
<a href="/projects/embedded/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
Fancy Things on Boards
</p>
</a>
<a href="/projects/self_host/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
Self-host
</p>
</a>
</div>
</div>
</div>
</div>
<div>
<div class="cursor-pointer flex items-center nested-menu">
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<a href="/life/" class="text-base font-medium text-gray-500 hover:text-primary-600 dark:hover:text-primary-400" title="Rest Here">
2025-07-25 02:15:37 +08:00
RestHere
</a>
<span>
<span class="relative block icon">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
</span>
</span>
</div>
<div class="absolute menuhide">
<div class="pt-2 p-5 mt-2 rounded-xl backdrop-blur shadow-2xl">
<div class="flex flex-col space-y-3">
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<a href="/life/pet/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
My Pet
</p>
</a>
<a href="/life/travel/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-sm" title="">
My Travel
</p>
</a>
</div>
</div>
</div>
</div>
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<a href="https://swangnice.com" target="_blank" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
<span >
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M172.5 131.1C228.1 75.51 320.5 75.51 376.1 131.1C426.1 181.1 433.5 260.8 392.4 318.3L391.3 319.9C381 334.2 361 337.6 346.7 327.3C332.3 317 328.9 297 339.2 282.7L340.3 281.1C363.2 249 359.6 205.1 331.7 177.2C300.3 145.8 249.2 145.8 217.7 177.2L105.5 289.5C73.99 320.1 73.99 372 105.5 403.5C133.3 431.4 177.3 435 209.3 412.1L210.9 410.1C225.3 400.7 245.3 404 255.5 418.4C265.8 432.8 262.5 452.8 248.1 463.1L246.5 464.2C188.1 505.3 110.2 498.7 60.21 448.8C3.741 392.3 3.741 300.7 60.21 244.3L172.5 131.1zM467.5 380C411 436.5 319.5 436.5 263 380C213 330 206.5 251.2 247.6 193.7L248.7 192.1C258.1 177.8 278.1 174.4 293.3 184.7C307.7 194.1 311.1 214.1 300.8 229.3L299.7 230.9C276.8 262.1 280.4 306.9 308.3 334.8C339.7 366.2 390.8 366.2 422.3 334.8L534.5 222.5C566 191 566 139.1 534.5 108.5C506.7 80.63 462.7 76.99 430.7 99.9L429.1 101C414.7 111.3 394.7 107.1 384.5 93.58C374.2 79.2 377.5 59.21 391.9 48.94L393.5 47.82C451 6.731 529.8 13.25 579.8 63.24C636.3 119.7 636.3 211.3 579.8 267.7L467.5 380z"/></svg>
2025-05-20 02:59:55 -04:00
</span>
</span>
<p class="text-base font-medium" title="">
</p>
</a>
2025-07-25 02:15:37 +08:00
<a href="https://github.com/swangnice" target="_blank" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
<span >
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
2025-05-20 02:59:55 -04:00
</span>
</span>
<p class="text-base font-medium" title="">
</p>
</a>
<button id="search-button" aria-label="Search" class="text-base hover:text-primary-600 dark:hover:text-primary-400"
title="">
<span class="relative block icon">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg>
</span>
</button>
<div
class=" flex items-center">
<button id="appearance-switcher" aria-label="Dark mode switcher" type="button" class="text-base hover:text-primary-600 dark:hover:text-primary-400">
<div class="flex items-center justify-center dark:hidden">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M32 256c0-123.8 100.3-224 223.8-224c11.36 0 29.7 1.668 40.9 3.746c9.616 1.777 11.75 14.63 3.279 19.44C245 86.5 211.2 144.6 211.2 207.8c0 109.7 99.71 193 208.3 172.3c9.561-1.805 16.28 9.324 10.11 16.95C387.9 448.6 324.8 480 255.8 480C132.1 480 32 379.6 32 256z"/></svg>
</span>
</div>
<div class="items-center justify-center hidden dark:flex">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 159.1c-53.02 0-95.1 42.98-95.1 95.1S202.1 351.1 256 351.1s95.1-42.98 95.1-95.1S309 159.1 256 159.1zM509.3 347L446.1 255.1l63.15-91.01c6.332-9.125 1.104-21.74-9.826-23.72l-109-19.7l-19.7-109c-1.975-10.93-14.59-16.16-23.72-9.824L256 65.89L164.1 2.736c-9.125-6.332-21.74-1.107-23.72 9.824L121.6 121.6L12.56 141.3C1.633 143.2-3.596 155.9 2.736 164.1L65.89 256l-63.15 91.01c-6.332 9.125-1.105 21.74 9.824 23.72l109 19.7l19.7 109c1.975 10.93 14.59 16.16 23.72 9.824L256 446.1l91.01 63.15c9.127 6.334 21.75 1.107 23.72-9.822l19.7-109l109-19.7C510.4 368.8 515.6 356.1 509.3 347zM256 383.1c-70.69 0-127.1-57.31-127.1-127.1c0-70.69 57.31-127.1 127.1-127.1s127.1 57.3 127.1 127.1C383.1 326.7 326.7 383.1 256 383.1z"/></svg>
</span>
</div>
</button>
</div>
</nav>
<div class="flex md:hidden items-center gap-x-5 md:ml-12 h-12">
<span></span>
<button id="search-button-mobile" aria-label="Search" class="text-base hover:text-primary-600 dark:hover:text-primary-400"
title="">
<span class="relative block icon">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg>
</span>
</button>
<button id="appearance-switcher-mobile" aria-label="Dark mode switcher" type="button" class="text-base hover:text-primary-600 dark:hover:text-primary-400 ltr:mr-1 rtl:ml-1">
<div class="flex items-center justify-center dark:hidden">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M32 256c0-123.8 100.3-224 223.8-224c11.36 0 29.7 1.668 40.9 3.746c9.616 1.777 11.75 14.63 3.279 19.44C245 86.5 211.2 144.6 211.2 207.8c0 109.7 99.71 193 208.3 172.3c9.561-1.805 16.28 9.324 10.11 16.95C387.9 448.6 324.8 480 255.8 480C132.1 480 32 379.6 32 256z"/></svg>
</span>
</div>
<div class="items-center justify-center hidden dark:flex">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M256 159.1c-53.02 0-95.1 42.98-95.1 95.1S202.1 351.1 256 351.1s95.1-42.98 95.1-95.1S309 159.1 256 159.1zM509.3 347L446.1 255.1l63.15-91.01c6.332-9.125 1.104-21.74-9.826-23.72l-109-19.7l-19.7-109c-1.975-10.93-14.59-16.16-23.72-9.824L256 65.89L164.1 2.736c-9.125-6.332-21.74-1.107-23.72 9.824L121.6 121.6L12.56 141.3C1.633 143.2-3.596 155.9 2.736 164.1L65.89 256l-63.15 91.01c-6.332 9.125-1.105 21.74 9.824 23.72l109 19.7l19.7 109c1.975 10.93 14.59 16.16 23.72 9.824L256 446.1l91.01 63.15c9.127 6.334 21.75 1.107 23.72-9.822l19.7-109l109-19.7C510.4 368.8 515.6 356.1 509.3 347zM256 383.1c-70.69 0-127.1-57.31-127.1-127.1c0-70.69 57.31-127.1 127.1-127.1s127.1 57.3 127.1 127.1C383.1 326.7 326.7 383.1 256 383.1z"/></svg>
</span>
</div>
</button>
</div>
</div>
<div class="-my-2 md:hidden">
<label id="menu-button" class="block">
<div class="cursor-pointer hover:text-primary-600 dark:hover:text-primary-400">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 448 512"><path fill="currentColor" d="M0 96C0 78.33 14.33 64 32 64H416C433.7 64 448 78.33 448 96C448 113.7 433.7 128 416 128H32C14.33 128 0 113.7 0 96zM0 256C0 238.3 14.33 224 32 224H416C433.7 224 448 238.3 448 256C448 273.7 433.7 288 416 288H32C14.33 288 0 273.7 0 256zM416 448H32C14.33 448 0 433.7 0 416C0 398.3 14.33 384 32 384H416C433.7 384 448 398.3 448 416C448 433.7 433.7 448 416 448z"/></svg>
</span>
</div>
<div id="menu-wrapper" style="padding-top:5px;"
class="fixed inset-0 z-30 invisible w-screen h-screen m-0 overflow-auto transition-opacity opacity-0 cursor-default bg-neutral-100/50 backdrop-blur-sm dark:bg-neutral-900/50">
<ul
class="flex space-y-2 mt-3 flex-col items-end w-full px-6 py-6 mx-auto overflow-visible list-none ltr:text-right rtl:text-left max-w-7xl">
<li id="menu-close-button">
<span
class="cursor-pointer inline-block align-text-bottom hover:text-primary-600 dark:hover:text-primary-400">
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>
</span>
</span>
</li>
<li class="mt-1">
2025-08-05 13:24:21 +08:00
<a href="/about/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<p class="text-bg font-bg" title="About">
About
2025-05-20 02:59:55 -04:00
</p>
</a>
</li>
2025-07-25 02:15:37 +08:00
<li class="mt-1">
<a href="/notes/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-bg font-bg" title="Notes">
Notes
</p>
<span>
<span class="relative block icon">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
</span>
</span>
</a>
</li>
<li class="mt-1">
<a href="/notes/coding/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
Coding
</p>
</a>
</li>
<li class="mt-1">
<a href="/notes/pdf/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
PDF Collection
</p>
</a>
</li>
<li class="mb-2"></li>
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
2025-05-20 02:59:55 -04:00
<li class="mt-1">
2025-07-25 02:15:37 +08:00
<a href="/projects/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<p class="text-bg font-bg" title="Projects">
Projects
</p>
<span>
2025-05-20 02:59:55 -04:00
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
2025-05-20 02:59:55 -04:00
</span>
2025-07-25 02:15:37 +08:00
</span>
</a>
</li>
<li class="mt-1">
<a href="/projects/embedded/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
Fancy Things on Boards
</p>
</a>
</li>
<li class="mt-1">
<a href="/projects/self_host/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
Self-host
</p>
</a>
</li>
<li class="mb-2"></li>
<li class="mt-1">
2025-08-05 13:24:21 +08:00
<a href="/life/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<p class="text-bg font-bg" title="Rest Here">
2025-07-25 02:15:37 +08:00
RestHere
</p>
<span>
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
<span class="relative block icon">
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
aria-hidden="true"
>
<path
fill-rule="evenodd"
d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z"
clip-rule="evenodd"
/>
</svg>
</span>
</span>
</a>
</li>
<li class="mt-1">
<a href="/life/pet/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
My Pet
2025-05-20 02:59:55 -04:00
</p>
</a>
</li>
2025-07-25 02:15:37 +08:00
<li class="mt-1">
<a href="/life/travel/" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
<p class="text-sm font-small" title="">
My Travel
</p>
</a>
</li>
<li class="mb-2"></li>
2025-05-20 02:59:55 -04:00
<li class="mt-1">
2025-07-25 02:15:37 +08:00
<a href="https://swangnice.com" target="_blank" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
<div >
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path fill="currentColor" d="M172.5 131.1C228.1 75.51 320.5 75.51 376.1 131.1C426.1 181.1 433.5 260.8 392.4 318.3L391.3 319.9C381 334.2 361 337.6 346.7 327.3C332.3 317 328.9 297 339.2 282.7L340.3 281.1C363.2 249 359.6 205.1 331.7 177.2C300.3 145.8 249.2 145.8 217.7 177.2L105.5 289.5C73.99 320.1 73.99 372 105.5 403.5C133.3 431.4 177.3 435 209.3 412.1L210.9 410.1C225.3 400.7 245.3 404 255.5 418.4C265.8 432.8 262.5 452.8 248.1 463.1L246.5 464.2C188.1 505.3 110.2 498.7 60.21 448.8C3.741 392.3 3.741 300.7 60.21 244.3L172.5 131.1zM467.5 380C411 436.5 319.5 436.5 263 380C213 330 206.5 251.2 247.6 193.7L248.7 192.1C258.1 177.8 278.1 174.4 293.3 184.7C307.7 194.1 311.1 214.1 300.8 229.3L299.7 230.9C276.8 262.1 280.4 306.9 308.3 334.8C339.7 366.2 390.8 366.2 422.3 334.8L534.5 222.5C566 191 566 139.1 534.5 108.5C506.7 80.63 462.7 76.99 430.7 99.9L429.1 101C414.7 111.3 394.7 107.1 384.5 93.58C374.2 79.2 377.5 59.21 391.9 48.94L393.5 47.82C451 6.731 529.8 13.25 579.8 63.24C636.3 119.7 636.3 211.3 579.8 267.7L467.5 380z"/></svg>
2025-05-20 02:59:55 -04:00
</span>
</div>
<p class="text-bg font-bg" title="">
</p>
</a>
</li>
<li class="mt-1">
2025-07-25 02:15:37 +08:00
<a href="https://github.com/swangnice" target="_blank" class="flex items-center text-gray-500 hover:text-primary-600 dark:hover:text-primary-400">
2025-05-20 02:59:55 -04:00
<div >
<span class="relative block icon">
2025-07-25 02:15:37 +08:00
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 496 512"><path fill="currentColor" d="M165.9 397.4c0 2-2.3 3.6-5.2 3.6-3.3.3-5.6-1.3-5.6-3.6 0-2 2.3-3.6 5.2-3.6 3-.3 5.6 1.3 5.6 3.6zm-31.1-4.5c-.7 2 1.3 4.3 4.3 4.9 2.6 1 5.6 0 6.2-2s-1.3-4.3-4.3-5.2c-2.6-.7-5.5.3-6.2 2.3zm44.2-1.7c-2.9.7-4.9 2.6-4.6 4.9.3 2 2.9 3.3 5.9 2.6 2.9-.7 4.9-2.6 4.6-4.6-.3-1.9-3-3.2-5.9-2.9zM244.8 8C106.1 8 0 113.3 0 252c0 110.9 69.8 205.8 169.5 239.2 12.8 2.3 17.3-5.6 17.3-12.1 0-6.2-.3-40.4-.3-61.4 0 0-70 15-84.7-29.8 0 0-11.4-29.1-27.8-36.6 0 0-22.9-15.7 1.6-15.4 0 0 24.9 2 38.6 25.8 21.9 38.6 58.6 27.5 72.9 20.9 2.3-16 8.8-27.1 16-33.7-55.9-6.2-112.3-14.3-112.3-110.5 0-27.5 7.6-41.3 23.6-58.9-2.6-6.5-11.1-33.3 2.6-67.9 20.9-6.5 69 27 69 27 20-5.6 41.5-8.5 62.8-8.5s42.8 2.9 62.8 8.5c0 0 48.1-33.6 69-27 13.7 34.7 5.2 61.4 2.6 67.9 16 17.7 25.8 31.5 25.8 58.9 0 96.5-58.9 104.2-114.8 110.5 9.2 7.9 17 22.9 17 46.4 0 33.7-.3 75.4-.3 83.6 0 6.5 4.6 14.4 17.3 12.1C428.2 457.8 496 362.9 496 252 496 113.3 383.5 8 244.8 8zM97.2 352.9c-1.3 1-1 3.3.7 5.2 1.6 1.6 3.9 2.3 5.2 1 1.3-1 1-3.3-.7-5.2-1.6-1.6-3.9-2.3-5.2-1zm-10.8-8.1c-.7 1.3.3 2.9 2.3 3.9 1.6 1 3.6.7 4.3-.7.7-1.3-.3-2.9-2.3-3.9-2-.6-3.6-.3-4.3.7zm32.4 35.6c-1.6 1.3-1 4.3 1.3 6.2 2.3 2.3 5.2 2.6 6.5 1 1.3-1.3.7-4.3-1.3-6.2-2.2-2.3-5.2-2.6-6.5-1zm-11.4-14.7c-1.6 1-1.6 3.6 0 5.9 1.6 2.3 4.3 3.3 5.6 2.3 1.6-1.3 1.6-3.9 0-6.2-1.4-2.3-4-3.3-5.6-2z"/></svg>
2025-05-20 02:59:55 -04:00
</span>
</div>
<p class="text-bg font-bg" title="">
</p>
</a>
</li>
</ul>
</div>
</label>
</div>
</div>
<div class="relative flex flex-col grow">
<main id="main-content" class="grow">
2025-07-25 02:15:37 +08:00
<header>
2025-08-05 13:24:21 +08:00
<h1 class="mt-5 text-4xl font-extrabold text-neutral-900 dark:text-neutral">A pet feeder</h1>
2025-07-25 02:15:37 +08:00
<div class="mt-1 mb-2 text-base text-neutral-500 dark:text-neutral-400 print:hidden">
<div class="flex flex-row flex-wrap items-center">
</div>
</div>
<script>
2025-08-05 13:24:21 +08:00
var oid = "views_projects\/embedded\/pet_feeder\/_index.md"
var oid_likes = "likes_projects\/embedded\/pet_feeder\/_index.md"
2025-07-25 02:15:37 +08:00
</script>
<script type="text/javascript" src="/js/page.min.0860cf4e04fa2d72cc33ddba263083464d48f67de06114529043cb4623319efed4f484fd7f1730df5abea0e2da6f3538855634081d02f2d6e920b956f063e823.js" integrity="sha512-CGDPTgT6LXLMM926JjCDRk1I9n3gYRRSkEPLRiMxnv7U9IT9fxcw31q&#43;oOLabzU4hVY0CB0C8tbpILlW8GPoIw=="></script>
</header>
<section class="mt-12 prose flex max-w-full flex-col dark:prose-invert lg:flex-row">
<div class="order-first px-0 lg:order-last lg:max-w-xs ltr:lg:pl-8 rtl:lg:pr-8">
<div class="toc ltr:pl-5 rtl:pr-5 lg:sticky lg:top-10">
<details open id="TOCView"
class="toc-right mt-0 overflow-y-scroll overscroll-contain scrollbar-thin scrollbar-track-neutral-200 scrollbar-thumb-neutral-400 dark:scrollbar-track-neutral-800 dark:scrollbar-thumb-neutral-600 rounded-lg ltr:-ml-5 ltr:pl-5 rtl:-mr-5 rtl:pr-5 hidden lg:block">
<summary
class="block py-1 text-lg font-semibold cursor-pointer bg-neutral-100 text-neutral-800 ltr:-ml-5 ltr:pl-5 rtl:-mr-5 rtl:pr-5 dark:bg-neutral-700 dark:text-neutral-100 lg:hidden">
Table of Contents
</summary>
<div
class="min-w-[220px] py-2 border-dotted ltr:-ml-5 ltr:border-l ltr:pl-5 rtl:-mr-5 rtl:border-r rtl:pr-5 dark:border-neutral-600">
<nav id="TableOfContents">
<ul>
<li>
<ul>
2025-08-05 13:24:21 +08:00
<li><a href="#1-project-photos--screenshots">1. Project Photos &amp; Screenshots</a></li>
<li><a href="#2-project-summary">2. Project Summary</a>
<ul>
<li><a href="#device-description">Device Description</a></li>
<li><a href="#inspiration">Inspiration</a></li>
<li><a href="#device-functionality">Device Functionality</a></li>
<li><a href="#challenges">Challenges</a></li>
<li><a href="#prototype-learnings">Prototype Learnings</a></li>
<li><a href="#next-steps">Next Steps</a></li>
<li><a href="#takeaways-from-ese5160">Takeaways from ESE5160</a></li>
<li><a href="#project-links">Project links</a></li>
</ul>
</li>
<li><a href="#3-hardware--software-requirements">3. Hardware &amp; Software Requirements</a>
<ul>
<li><a href="#hardware-requirements">Hardware Requirements</a></li>
<li><a href="#software-requirements">Software Requirements</a></li>
</ul>
</li>
2025-07-25 02:15:37 +08:00
</ul>
</li>
</ul>
</nav>
</div>
</details>
<details class="toc-inside mt-0 overflow-hidden rounded-lg ltr:-ml-5 ltr:pl-5 rtl:-mr-5 rtl:pr-5 lg:hidden">
<summary
class="py-1 text-lg font-semibold cursor-pointer bg-neutral-100 text-neutral-800 ltr:-ml-5 ltr:pl-5 rtl:-mr-5 rtl:pr-5 dark:bg-neutral-700 dark:text-neutral-100 lg:hidden">
Table of Contents
</summary>
<div
class="py-2 border-dotted border-neutral-300 ltr:-ml-5 ltr:border-l ltr:pl-5 rtl:-mr-5 rtl:border-r rtl:pr-5 dark:border-neutral-600">
<nav id="TableOfContents">
<ul>
<li>
<ul>
2025-08-05 13:24:21 +08:00
<li><a href="#1-project-photos--screenshots">1. Project Photos &amp; Screenshots</a></li>
<li><a href="#2-project-summary">2. Project Summary</a>
<ul>
<li><a href="#device-description">Device Description</a></li>
<li><a href="#inspiration">Inspiration</a></li>
<li><a href="#device-functionality">Device Functionality</a></li>
<li><a href="#challenges">Challenges</a></li>
<li><a href="#prototype-learnings">Prototype Learnings</a></li>
<li><a href="#next-steps">Next Steps</a></li>
<li><a href="#takeaways-from-ese5160">Takeaways from ESE5160</a></li>
<li><a href="#project-links">Project links</a></li>
</ul>
</li>
<li><a href="#3-hardware--software-requirements">3. Hardware &amp; Software Requirements</a>
<ul>
<li><a href="#hardware-requirements">Hardware Requirements</a></li>
<li><a href="#software-requirements">Software Requirements</a></li>
</ul>
</li>
2025-07-25 02:15:37 +08:00
</ul>
</li>
</ul>
</nav>
</div>
</details>
<script>
var margin = 200;
var marginError = 50;
2025-05-20 02:59:55 -04:00
2025-07-25 02:15:37 +08:00
(function () {
var $window = $(window);
var $toc = $('#TOCView');
var tocHeight = $toc.height();
function onResize() {
var windowAndMarginHeight = $window.height() - margin;
if(tocHeight >= windowAndMarginHeight) {
$toc.css("overflow-y", "scroll")
$toc.css("max-height", (windowAndMarginHeight + marginError) + "px")
} else {
$toc.css("overflow-y", "hidden")
$toc.css("max-height", "9999999px")
}
}
$window.on('resize', onResize);
$(document).ready(onResize);
})();
</script>
</div>
</div>
<div class="min-w-0 min-h-0 max-w-prose">
2025-08-05 13:24:21 +08:00
<!-- - [1. Video Presentation](#1-video-presentation)
- [2. Project Summary](#2-project-summary)
- [Device Description](#device-description)
- [Inspiration](#inspiration)
- [Device Functionality](#device-functionality)
- [Challenges](#challenges)
- [Prototype Learnings](#prototype-learnings)
- [Next Steps](#next-steps)
- [Takeaways from ESE5160](#takeaways-from-ese5160)
- [Project links](#project-links)
- [3. Hardware \& Software Requirements](#3-hardware--software-requirements)
- [Hardware Requirements](#hardware-requirements)
- [Software Requirements](#software-requirements)
- [4. Project Photos \& Screenshots](#4-project-photos--screenshots) -->
<h2 class="relative group">1. Project Photos &amp; Screenshots
<div id="1-project-photos--screenshots" class="anchor"></div>
2025-07-25 02:15:37 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
2025-08-05 13:24:21 +08:00
style="text-decoration-line: none !important;" href="#1-project-photos--screenshots" aria-label="Anchor">#</a>
2025-07-25 02:15:37 +08:00
</span>
</h2>
2025-08-05 13:24:21 +08:00
<p>The final project photo.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/finalproject_hu_937e68ac6a594371.jpg 330w,
/projects/embedded/pet_feeder/Pic/finalproject_hu_a3e222b22e286eac.jpg 660w,
/projects/embedded/pet_feeder/Pic/finalproject_hu_254b13c7e51aa40a.jpg 1024w,
/projects/embedded/pet_feeder/Pic/finalproject_hu_338f19bb7ab8e915.jpg 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/finalproject_hu_338f19bb7ab8e915.jpg"
src="/projects/embedded/pet_feeder/Pic/finalproject_hu_a3e222b22e286eac.jpg"
alt="final"
/>
</figure>
</p>
<p>The standalone PCBA, top.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/pcbtop_hu_48447a3c7c594866.jpg 330w,
/projects/embedded/pet_feeder/Pic/pcbtop_hu_9aa5e76f2126ffd8.jpg 660w,
/projects/embedded/pet_feeder/Pic/pcbtop_hu_5c0b8ba86c908081.jpg 1024w,
/projects/embedded/pet_feeder/Pic/pcbtop_hu_ba4dfdeb3bafe7a9.jpg 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/pcbtop_hu_ba4dfdeb3bafe7a9.jpg"
src="/projects/embedded/pet_feeder/Pic/pcbtop_hu_9aa5e76f2126ffd8.jpg"
alt="top"
/>
</figure>
</p>
<p>The standalone PCBA, bottom.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/pcbbottom_hu_5da23309705f67d8.jpg 330w,
/projects/embedded/pet_feeder/Pic/pcbbottom_hu_97a29e0e24a01eb4.jpg 660w,
/projects/embedded/pet_feeder/Pic/pcbbottom_hu_44c37ea3f03d53f8.jpg 1024w,
/projects/embedded/pet_feeder/Pic/pcbbottom_hu_39f3cb516562bade.jpg 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/pcbbottom_hu_39f3cb516562bade.jpg"
src="/projects/embedded/pet_feeder/Pic/pcbbottom_hu_97a29e0e24a01eb4.jpg"
alt="bottom"
/>
</figure>
</p>
<p>Thermal camera images while the board is running under load.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/thermal_hu_dd49210901077b78.jpg 330w,
/projects/embedded/pet_feeder/Pic/thermal_hu_5874c38595d29cb.jpg 660w,
/projects/embedded/pet_feeder/Pic/thermal_hu_619bb31eda73b131.jpg 1024w,
/projects/embedded/pet_feeder/Pic/thermal_hu_6805c0c8d1256a97.jpg 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/thermal_hu_6805c0c8d1256a97.jpg"
src="/projects/embedded/pet_feeder/Pic/thermal_hu_5874c38595d29cb.jpg"
alt="thermal"
/>
</figure>
</p>
<p>The Altium Board design in 2D view.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/board2D_hu_1d2eb0797bdbf5bd.png 330w,
/projects/embedded/pet_feeder/Pic/board2D_hu_5571679c43e58c50.png 660w,
/projects/embedded/pet_feeder/Pic/board2D_hu_ee36071afe644178.png 1024w,
/projects/embedded/pet_feeder/Pic/board2D_hu_a572028726c99440.png 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/board2D_hu_a572028726c99440.png"
src="/projects/embedded/pet_feeder/Pic/board2D_hu_5571679c43e58c50.png"
alt="2D"
/>
</figure>
</p>
<p>The Altium Board design in 3D view.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/board3D_hu_961c539fb5ea7667.png 330w,
/projects/embedded/pet_feeder/Pic/board3D_hu_da1912d06eb738fb.png 660w,
/projects/embedded/pet_feeder/Pic/board3D_hu_c729be25e9955c8c.png 1024w,
/projects/embedded/pet_feeder/Pic/board3D_hu_2eaf5e39c4ae9b91.png 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/board3D_hu_2eaf5e39c4ae9b91.png"
src="/projects/embedded/pet_feeder/Pic/board3D_hu_da1912d06eb738fb.png"
alt="3D"
/>
</figure>
</p>
<p>Node-RED dashboard
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/dashboard_hu_c22f7ef76cb0e20a.png 330w,
/projects/embedded/pet_feeder/Pic/dashboard_hu_4c338f9b1b5e7047.png 660w,
/projects/embedded/pet_feeder/Pic/dashboard_hu_a962133b726ebc75.png 1024w,
/projects/embedded/pet_feeder/Pic/dashboard_hu_76d1e34820fef302.png 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/dashboard_hu_76d1e34820fef302.png"
src="/projects/embedded/pet_feeder/Pic/dashboard_hu_4c338f9b1b5e7047.png"
alt="dashboard"
/>
</figure>
</p>
<p>Node-RED backend
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/backend_hu_79f04fa526671c5e.png 330w,
/projects/embedded/pet_feeder/Pic/backend_hu_d24a0819af354a47.png 660w,
/projects/embedded/pet_feeder/Pic/backend_hu_5831f8327d9cab79.png 1024w,
/projects/embedded/pet_feeder/Pic/backend_hu_57dd65dd067dc4c.png 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/backend_hu_57dd65dd067dc4c.png"
src="/projects/embedded/pet_feeder/Pic/backend_hu_d24a0819af354a47.png"
alt="backend"
/>
</figure>
</p>
<p>Block diagram of the system.
<figure>
<img
class="my-0 rounded-md"
loading="lazy"
srcset="
/projects/embedded/pet_feeder/Pic/blockdiagram_hu_8d28b727f3194105.png 330w,
/projects/embedded/pet_feeder/Pic/blockdiagram_hu_5b69ff1becf17508.png 660w,
/projects/embedded/pet_feeder/Pic/blockdiagram_hu_ea464e74371058b2.png 1024w,
/projects/embedded/pet_feeder/Pic/blockdiagram_hu_e79b4fa6be4a64aa.png 2x"
data-zoom-src="/projects/embedded/pet_feeder/Pic/blockdiagram_hu_e79b4fa6be4a64aa.png"
src="/projects/embedded/pet_feeder/Pic/blockdiagram_hu_5b69ff1becf17508.png"
alt="block"
/>
</figure>
</p>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h2 class="relative group">2. Project Summary
<div id="2-project-summary" class="anchor"></div>
2025-07-25 02:15:37 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
2025-08-05 13:24:21 +08:00
style="text-decoration-line: none !important;" href="#2-project-summary" aria-label="Anchor">#</a>
2025-07-25 02:15:37 +08:00
</span>
</h2>
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Device Description
<div id="device-description" class="anchor"></div>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#device-description" aria-label="Anchor">#</a>
</span>
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
</h3>
<ol>
<li>
<p>SG90 Servo Motor<br>
The servo motor is used to turn on and off the food storage. It is much more complicated than we expected when we implemented the drivers by ourselves. Since the rotation of the servo angle is controlled by the PWM signals which are generated by the TCC/TC timer counter, not all MCU pins are attached to this function. Fortunately, the pin PA11 we assigned has the TCC1 counter. After the successful generation of the PWM signal, the next problem is how to verify the duty cycle after the system initialization. Once we change the <code>compare_match</code> in the <code>tcc_configure</code> process, the whole system will get stuck and cashed. We solved it by using the <code>tcc_set_compare_value</code> function, where we can change the PWM length by calculating the required timer counter ticks based on the datasheet parameters.</p>
</li>
<li>
<p>Load Cell with NAU7802 ADC<br>
The load cell is used to measure the weight data and the ADC is used to convert the raw data to the real value, which is communicated with the MCU through the I2C protocol. The problem with this device is that there are numerous registers in the datasheet, which is necessary to find out how to assign them correctly. This is the essential part of the ADC chip working because the wrong initialization of the registers will lead to the unsuccessful value read. After figuring out the correct presetting of the ADC, the calibration and handling of raw data is also a huge problem. In the end, though the real weight converting is still not so accurate, we at least can measure the load cell value with the correct tendency.</p>
</li>
<li>
<p>ST7735 LCD TFT Screen<br>
The LCD screen is used to display the weight data measured from the load cell, which is connected to the SAMW25 chip by SPI communication. Although we learned the basic initialization and LCD function in the ESE5190 class last semester, we still met unexpected problems in SPI configuration. The SCK and MOSI pins must be under the same SERCOM, and need to be defined with the <code>CONF_MASTER_PINMUX_PAD</code>.</p>
</li>
<li>
<p>Internet Augment<br>
Enable users to control and monitor the device remotely through a web or mobile application. This could involve turning devices on/off(SG90 motor), adjusting settings, or receiving real-time data updates from sensors(load cell). Utilize cloud services to store data collected by the device. This data can then be analyzed to provide insights, trends, or predictive maintenance alerts. Cloud platforms like AWS, Google Cloud, or Microsoft Azure(used in this project) offer various tools for data storage, processing, and analysis. Implement FOTA capabilities to remotely update device firmware. This ensures that devices can receive bug fixes, security patches, or new features without requiring physical access or manual intervention.</p>
</li>
</ol>
<h3 class="relative group">Inspiration
<div id="inspiration" class="anchor"></div>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#inspiration" aria-label="Anchor">#</a>
</span>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
</h3>
<p>The project is inspired by my friend who has a cute but hungry cat. We need to feed it two or three times per day, but we are very busy studying on campus. Therefore, we want to design a pet feeder that can provide food for the cat at home while we are studying in school.</p>
<ol>
<li>Remote Feeding: Create a system that allows pet owners to feed their pets remotely using a mobile app or web interface. This could be particularly useful for pet owners who are away from home for extended periods.</li>
<li>Scheduled Feeding: Implement scheduling functionality that enables pet owners to set specific times for automatic feeding. This ensures that pets receive their meals on time, even when their owners are busy or away.</li>
<li>Portion Control: Incorporate portion control features that allow pet owners to dispense precise amounts of food for each feeding. This helps prevent overfeeding or underfeeding and ensures that pets receive the appropriate amount of nutrition.</li>
<li>Customizable Diet Plans: Provide pet owners with the ability to create customized diet plans tailored to their pets&rsquo; specific dietary needs and preferences. This could involve setting different portion sizes or types of food for each meal.</li>
<li>Food Monitoring: Integrate sensors or cameras to monitor food levels in the feeder and send alerts when it&rsquo;s time to refill. This helps ensure that pets always have access to food and prevents them from going hungry.</li>
</ol>
<h3 class="relative group">Device Functionality
<div id="device-functionality" class="anchor"></div>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#device-functionality" aria-label="Anchor">#</a>
</span>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
</h3>
<p>The device operation logic is described as follows: The user can press the servo button on the website to control the on/off food storage. Once the food is dropped, the load cell will measure the weight data and upload it to the cloud and process, which is visible on the website. Also, the weight information will be sent to the LCD screen to show the total weight of the food.</p>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Challenges
<div id="challenges" class="anchor"></div>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#challenges" aria-label="Anchor">#</a>
</span>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
</h3>
<p>We encountered a lot of unexpected problems on this project both in hardware and software.</p>
<ol>
<li>We want to use the TCC timer counter to generate the PWM signal, but we met the problem that once the timer counter compare match value is set in system initialization, it is hard to modify later to change the rotation angle of the motor. We solved it by using the <code>tcc_set_compare_value</code> function.</li>
<li>Initially, we prepared to use an ultrasonic distance sensor HC-SR04 to detect the location of the pets. We previously thought that this sensor simply needs two GPIO to control, but it needs the trig and echo pin applied with the PWM signals. Unfortunately, the pins we assigned for the trig and echo pins have no TCC counter attached, which cannot support the PWM signal generation. So we cancel this sensor in the end.</li>
<li>We met the design problem of connecting the I2C pins <code>SCL</code> and <code>SDA</code> in the wrong direction, and I attached the <code>SCL</code> signal to the PA08 and the <code>SDA</code> signal to the PA09. I first wanted to change the codes to solve this problem, but we found that it was hard to achieve since all the pin functions are set as the starter project. Finally, it was solved by disconnecting the I2C jumpers and resoldering the correct connections to make the I2C device work.</li>
</ol>
2025-07-25 02:15:37 +08:00
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Prototype Learnings
<div id="prototype-learnings" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#prototype-learnings" aria-label="Anchor">#</a>
</span>
</h3>
<ol>
<li>We gained extensive knowledge about testing methodologies, testing from the specific region to the entire system. We first tested the function of two power regulators, first testing the boost converter, and then the buck converter. After making sure both the converters are outputting the correct voltage, we tested the whole power module is working. We implemented lots of 0Ohm resistors as jump wires, which proved instrumental in facilitating the measurement of various system components&rsquo; performance, particularly those that had not been previously explored. Our exposure to standardized testing methodologies has furnished us with invaluable insights and skills that will prove beneficial in our future endeavors.</li>
<li>If given the chance to redesign, we might opt to swap out the 0805 packages with the 0603 as it offers better accessibility for measurement purposes. Alternatively, we could incorporate additional test points into the design. Additionally, we aspire to refine the board&rsquo;s layout to make it more compact and increase its density.</li>
</ol>
2025-05-20 02:59:55 -04:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Next Steps
<div id="next-steps" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#next-steps" aria-label="Anchor">#</a>
</span>
</h3>
<ol>
<li>We can add more useful functions to the project, such as including a motor driver(DRV8801/DRV8803) to control the water pump, which can provide the pet with not only food but also water to drink.</li>
<li>We can implement the feedback control algorithm to add another feeding mode that always fills the food with the fixed value, which will provide the pet the enough food to eat.</li>
</ol>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Takeaways from ESE5160
<div id="takeaways-from-ese5160" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#takeaways-from-ese5160" aria-label="Anchor">#</a>
</span>
</h3>
<p>We acquired a wealth of invaluable knowledge throughout our project journey. From the intricacies of PCBA design to the intricacies of programming and firmware uploading, each step presented its own set of challenges and learning opportunities. Notably, we gained significant insights into PCB design and the utilization of FreeRTOS. Additionally, we deepened our understanding of I2C and SPI protocols, which honed our skills in unit testing and debug-thinking, further enriching our learning experience.</p>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Project links
<div id="project-links" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#project-links" aria-label="Anchor">#</a>
</span>
</h3>
<p>The Node-RED instance link:<br>
http://68.154.49.115:1880/ui/#!/0?socketid=DRc2CLKWRofETc06AAAW<br>
The code repository link:<br>
<a href="https://github.com/ese5160/a12g-firmware-drivers-t19-pet-feeder/tree/main/Final_submission" target="_blank">https://github.com/ese5160/a12g-firmware-drivers-t19-pet-feeder/tree/main/Final_submission</a><br>
The Altium 365 link:<br>
<a href="https://upenn-eselabs.365.altium.com/designs/EA1CCED6-8C54-4405-B127-DA898DF3EFB7#design" target="_blank">https://upenn-eselabs.365.altium.com/designs/EA1CCED6-8C54-4405-B127-DA898DF3EFB7#design</a></p>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h2 class="relative group">3. Hardware &amp; Software Requirements
<div id="3-hardware--software-requirements" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#3-hardware--software-requirements" aria-label="Anchor">#</a>
</span>
</h2>
2025-07-25 02:15:37 +08:00
2025-08-05 13:24:21 +08:00
<h3 class="relative group">Hardware Requirements
<div id="hardware-requirements" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#hardware-requirements" aria-label="Anchor">#</a>
</span>
</h3>
<ol>
<li>Overview of Hardware Components:<br>
The hardware aspect of the project comprised several components including the SAMW25 MCU, load cells, ultrasonic distance sensor, servo motor, and LCD display.</li>
<li>Description of Components:<br>
Each component was carefully selected and described in detail, specifying its functionality, datasheet references, and purpose within the project.
The load cells were intended to measure food weight, while the ultrasonic distance sensor aimed to detect the pet&rsquo;s position. The servo motor controlled the food release mechanism, and the LCD display provided real-time information.</li>
<li>Functionality:<br>
Most hardware components, such as the load cells, servo motor, and LCD display, operated as intended and aligned with the project&rsquo;s specifications.
However, the distance sensor encountered issues, failing to accurately measure distance or provide reliable data regarding pet position.</li>
<li>Potential Causes of Sensor Failure:
The failure of the distance sensor was attributed to hardware malfunction: incorrect wiring with compatibility issues with the MCU.</li>
<li>Mitigation Steps Taken:
Throughout the semester, efforts were made to troubleshoot and resolve the issue with the distance sensor, including checking connections, reconfiguring setups, and reviewing software implementations.</li>
<li>Outcome:
Despite troubleshooting attempts, the distance sensor remained non-functional by the end of the semester, posing a notable challenge to the project&rsquo;s completeness.</li>
</ol>
<h3 class="relative group">Software Requirements
<div id="software-requirements" class="anchor"></div>
<span
class="absolute top-0 w-6 transition-opacity opacity-0 ltr:-left-6 rtl:-right-6 not-prose group-hover:opacity-100">
<a class="group-hover:text-primary-300 dark:group-hover:text-neutral-700"
style="text-decoration-line: none !important;" href="#software-requirements" aria-label="Anchor">#</a>
</span>
</h3>
<ol>
<li>Overview of Software Architecture:<br>
The software aspect of the project operated in two parts: one on the MCU for data processing and actuation, and the other on the cloud or MCU acting as a web server for user interaction.
MQTT facilitated communication between these two parts.</li>
<li>Functionality:<br>
The software fulfilled specified functionalities outlined in the Software Requirements Specification (SRS), including bootloader initialization, main loop operation, sensor data handling, actuator control, LCD display, MQTT configuration, and web app features.</li>
<li>User Interface:<br>
The web app provided a user-friendly interface accessible via phone or laptop, displaying machine/environment status and offering buttons for sending instructions.</li>
<li>Integration with Hardware:<br>
The software successfully integrated with hardware components, collecting data from sensors, operating actuators based on certain conditions, and receiving messages through MQTT.</li>
<li>Testing and Validation:<br>
Throughout development, rigorous testing and validation procedures were implemented to ensure software functionalities operated as intended and aligned with project requirements.</li>
<li>Outcome:<br>
Despite challenges with the distance sensor, the software aspect of the project functioned effectively, meeting user needs and providing a seamless interaction experience.</li>
</ol>
<p>In conclusion, while the hardware aspect faced challenges with the distance sensor, the software aspect operated successfully, fulfilling specified requirements and ensuring the project&rsquo;s overall functionality and usability.</p>
2025-07-25 02:15:37 +08:00
</div>
2025-08-05 13:24:21 +08:00
</section>
<section class="mt-10 prose dark:prose-invert">
<p class="py-8 border-t">
<em>There are no articles to list here yet.</em>
</p>
</section>
2025-07-25 02:15:37 +08:00
<div id="top-scroller" class="pointer-events-none absolute top-[110vh] bottom-0 w-12 ltr:right-0 rtl:left-0">
<a href="#the-top"
class="pointer-events-auto sticky top-[calc(100vh-5.5rem)] flex h-12 w-12 mb-16 items-center justify-center rounded-full bg-neutral/50 text-xl text-neutral-700 hover:text-primary-600 dark:bg-neutral-800/50 dark:text-neutral dark:hover:text-primary-400"
aria-label="Scroll to top" title="Scroll to top">
&uarr;
</a>
</div>
2025-05-20 02:59:55 -04:00
</main><footer id="site-footer" class="py-10 print:hidden">
<nav class="flex flex-row pb-4 text-base font-medium text-neutral-500 dark:text-neutral-400">
<ul class="flex flex-col list-none sm:flex-row">
<li class="flex mb-1 ltr:text-right rtl:text-left sm:mb-0 ltr:sm:mr-7 ltr:sm:last:mr-0 rtl:sm:ml-7 rtl:sm:last:ml-0">
2025-07-25 02:15:37 +08:00
<a class="decoration-primary-500 hover:underline hover:decoration-2 hover:underline-offset-2 flex items-center" href="/tags/"
title="Tags">
2025-05-20 02:59:55 -04:00
Tags
</a>
</li>
</ul>
</nav>
<div class="flex items-center justify-between">
<p class="text-sm text-neutral-500 dark:text-neutral-400">
&copy;
2025
2025-07-25 02:15:37 +08:00
SWang
</p>
<p class="text-sm text-neutral-500 dark:text-neutral-400">
<a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">
苏ICP备2024145451号
</a>
2025-05-20 02:59:55 -04:00
</p>
<p class="text-xs text-neutral-500 dark:text-neutral-400">
2025-07-25 02:15:37 +08:00
Powered by <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500"
2025-05-20 02:59:55 -04:00
href="https://gohugo.io/" target="_blank" rel="noopener noreferrer">Hugo</a> &amp; <a class="hover:underline hover:decoration-primary-400 hover:text-primary-500"
href="https://blowfish.page/" target="_blank" rel="noopener noreferrer">Blowfish</a>
</p>
</div>
<script>
mediumZoom(document.querySelectorAll("img:not(.nozoom)"), {
margin: 24,
background: 'rgba(0,0,0,0.5)',
scrollOffset: 0,
})
</script>
<script type="text/javascript" src="/js/process.min.ee03488f19c93c2efb199e2e3014ea5f3cb2ce7d45154adb3399a158cac27ca52831db249ede5bb602700ef87eb02434139de0858af1818ab0fb4182472204a4.js" integrity="sha512-7gNIjxnJPC77GZ4uMBTqXzyyzn1FFUrbM5mhWMrCfKUoMdsknt5btgJwDvh&#43;sCQ0E53ghYrxgYqw&#43;0GCRyIEpA=="></script>
</footer>
<div
id="search-wrapper"
class="invisible fixed inset-0 flex h-screen w-screen cursor-default flex-col bg-neutral-500/50 p-4 backdrop-blur-sm dark:bg-neutral-900/50 sm:p-6 md:p-[10vh] lg:p-[12vh]"
2025-07-25 02:15:37 +08:00
data-url="http://localhost:1313/"
2025-05-20 02:59:55 -04:00
style="z-index:500"
>
<div
id="search-modal"
class="flex flex-col w-full max-w-3xl min-h-0 mx-auto border rounded-md shadow-lg top-20 border-neutral-200 bg-neutral dark:border-neutral-700 dark:bg-neutral-800"
>
<header class="relative z-10 flex items-center justify-between flex-none px-2">
<form class="flex items-center flex-auto min-w-0">
<div class="flex items-center justify-center w-8 h-8 text-neutral-400">
<span class="relative block icon">
<svg aria-hidden="true" focusable="false" data-prefix="fas" data-icon="search" class="svg-inline--fa fa-search fa-w-16" role="img" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path fill="currentColor" d="M505 442.7L405.3 343c-4.5-4.5-10.6-7-17-7H372c27.6-35.3 44-79.7 44-128C416 93.1 322.9 0 208 0S0 93.1 0 208s93.1 208 208 208c48.3 0 92.7-16.4 128-44v16.3c0 6.4 2.5 12.5 7 17l99.7 99.7c9.4 9.4 24.6 9.4 33.9 0l28.3-28.3c9.4-9.4 9.4-24.6.1-34zM208 336c-70.7 0-128-57.2-128-128 0-70.7 57.2-128 128-128 70.7 0 128 57.2 128 128 0 70.7-57.2 128-128 128z"/></svg>
</span>
</div>
<input
type="search"
id="search-query"
class="flex flex-auto h-12 mx-1 bg-transparent appearance-none focus:outline-dotted focus:outline-2 focus:outline-transparent"
2025-07-25 02:15:37 +08:00
placeholder="Search"
2025-05-20 02:59:55 -04:00
tabindex="0"
/>
</form>
<button
id="close-search-button"
class="flex items-center justify-center w-8 h-8 text-neutral-700 hover:text-primary-600 dark:text-neutral dark:hover:text-primary-400"
2025-07-25 02:15:37 +08:00
title="Close (Esc)"
2025-05-20 02:59:55 -04:00
>
<span class="relative block icon">
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><path fill="currentColor" d="M310.6 361.4c12.5 12.5 12.5 32.75 0 45.25C304.4 412.9 296.2 416 288 416s-16.38-3.125-22.62-9.375L160 301.3L54.63 406.6C48.38 412.9 40.19 416 32 416S15.63 412.9 9.375 406.6c-12.5-12.5-12.5-32.75 0-45.25l105.4-105.4L9.375 150.6c-12.5-12.5-12.5-32.75 0-45.25s32.75-12.5 45.25 0L160 210.8l105.4-105.4c12.5-12.5 32.75-12.5 45.25 0s12.5 32.75 0 45.25l-105.4 105.4L310.6 361.4z"/></svg>
</span>
</button>
</header>
<section class="flex-auto px-2 overflow-auto">
<ul id="search-results">
</ul>
</section>
</div>
</div>
</div>
</body>
</html>