Files
www.aklabs.net/2026/06/18/Devlog-20260618/index.html

812 lines
26 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta
name="viewport"
content="width=device-width, initial-scale=1.0, minimum-scale=1.0">
<meta
http-equiv="X-UA-Compatible"
content="ie=edge">
<meta
name="theme-color"
content="#fff"
id="theme-color">
<meta
name="description"
content="AKLabs">
<link
rel="icon"
href="/">
<title>Devlog Entry - 18 June 2026</title>
<meta
property="og:title"
content="Devlog Entry - 18 June 2026">
<meta
property="og:url"
content="https://aklabs.net/2026/06/18/Devlog-20260618/index.html">
<meta
property="og:img"
content="/images/akesterson.webp">
<meta
property="og:type"
content="article">
<meta
property="og:article:published_time"
content="2026-06-18">
<meta
property="og:article:modified_time"
content="2026-06-27">
<meta
property="og:article:author"
content="Andrew Kesterson">
<link rel="preload" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css" as="style" >
<link rel="preload" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css" as="style" >
<link rel="preload" href="/css/main.css" as="style" >
<link rel="modulepreload" href="//instant.page/5.1.0">
<link rel="stylesheet" href="/css/main.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1946621_i1kgafibvw.css">
<link rel="stylesheet" href="//at.alicdn.com/t/font_1952792_89b4ac4k4up.css">
<link rel="stylesheet" href="/js/lib/lightbox/baguetteBox.min.css">
<script>
function loadScript(url, cb) {
var script = document.createElement('script');
script.src = url;
if (cb) script.onload = cb;
script.async = true;
document.body.appendChild(script);
}
function loadCSS(href, data, attr) {
var sheet = document.createElement('link');
sheet.ref = 'stylesheet';
sheet.href = href;
sheet.dataset[data] = attr;
document.head.appendChild(sheet);
}
function changeCSS(cssFile, data, attr) {
var oldlink = document.querySelector(data);
var newlink = document.createElement("link");
newlink.setAttribute("rel", "stylesheet");
newlink.setAttribute("href", cssFile);
newlink.dataset.prism = attr;
document.head.replaceChild(newlink, oldlink);
}
</script>
<script>
function prismThemeChange() {
if(document.getElementById('theme-color').dataset.mode === 'dark') {
if(document.querySelector('[data-prism]')) {
changeCSS('/js/lib/prism/prism-tomorrow.min.css', '[data-prism]', 'prism-tomorrow');
} else {
loadCSS('/js/lib/prism/prism-tomorrow.min.css', 'prism', 'prism-tomorrow');
}
} else {
if(document.querySelector('[data-prism]')) {
changeCSS('/js/lib/prism/prism-defauult.min.css', '[data-prism]', 'prism-defauult');
} else {
loadCSS('/js/lib/prism/prism-defauult.min.css', 'prism', 'prism-defauult');
}
}
}
prismThemeChange()
</script>
<link rel="stylesheet" href="/js/lib/prism/prism-line-numbers.min.css">
<script>
// control reverse button
var reverseDarkList = {
dark: 'light',
light: 'dark'
};
var themeColor = {
dark: '#1c1c1e',
light: '#fff'
}
// get the data of css prefers-color-scheme
var getCssMediaQuery = function() {
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
};
// reverse current darkmode setting function
var reverseDarkModeSetting = function() {
var setting = localStorage.getItem('user-color-scheme');
if(reverseDarkList[setting]) {
setting = reverseDarkList[setting];
} else if(setting === null) {
setting = reverseDarkList[getCssMediaQuery()];
} else {
return;
}
localStorage.setItem('user-color-scheme', setting);
return setting;
};
// apply current darkmode setting
</script>
<script>
var setDarkmode = function(mode) {
var setting = mode || localStorage.getItem('user-color-scheme');
if(setting === getCssMediaQuery()) {
document.documentElement.removeAttribute('data-user-color-scheme');
localStorage.removeItem('user-color-scheme');
document.getElementById('theme-color').content = themeColor[setting];
document.getElementById('theme-color').dataset.mode = setting;
prismThemeChange();
} else if(reverseDarkList[setting]) {
document.documentElement.setAttribute('data-user-color-scheme', setting);
document.getElementById('theme-color').content = themeColor[setting];
document.getElementById('theme-color').dataset.mode = setting;
prismThemeChange();
} else {
document.documentElement.removeAttribute('data-user-color-scheme');
localStorage.removeItem('user-color-scheme');
document.getElementById('theme-color').content = themeColor[getCssMediaQuery()];
document.getElementById('theme-color').dataset.mode = getCssMediaQuery();
prismThemeChange();
}
};
setDarkmode();
</script>
<link rel="preload" href="/js/lib/lightbox/baguetteBox.min.js" as="script">
<link rel="preload" href="/js/lib/lightbox/baguetteBox.min.css" as="style" >
<link rel="preload" href="/js/lib/lozad.min.js" as="script">
<meta name="generator" content="Hexo 6.0.0"><link rel="alternate" href="/atom.xml" title="AKLabs" type="application/atom+xml">
</head>
<body>
<div class="wrapper">
<nav class="navbar">
<div class="navbar-logo">
<a class="navbar-logo-main" href="/">
<span class="navbar-logo-dsc">AKLabs</span>
</a>
</div>
<div class="navbar-menu">
<a
href="/now"
class="navbar-menu-item">
~/.plan
</a>
<a
href="/archives"
class="navbar-menu-item">
Archive
</a>
<a
href="/categories"
class="navbar-menu-item">
Categories
</a>
<a
href="/about"
class="navbar-menu-item">
About
</a>
<a
href="/contact"
class="navbar-menu-item">
Contact
</a>
<button
class="navbar-menu-item darknavbar navbar-menu-btn"
aria-label="Toggle dark mode"
id="dark">
<i class="iconfont icon-weather"></i>
</button>
<button
class="navbar-menu-item searchnavbar navbar-menu-btn"
aria-label="Toggle search"
id="search">
<!-- <i
class="iconfont icon-search"
style="font-size: 1.2rem; font-weight: 400;">
</i> -->
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img"
class="iconify iconify--ion" width="28" height="28" preserveAspectRatio="xMidYMid meet" viewBox="0 0 512 512">
<path fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="28"
d="M256 80a176 176 0 1 0 176 176A176 176 0 0 0 256 80Z"></path>
<path fill="none" stroke="currentColor" stroke-miterlimit="10" stroke-width="28"
d="M232 160a72 72 0 1 0 72 72a72 72 0 0 0-72-72Z"></path>
<path fill="none" stroke="currentColor" stroke-linecap="round" stroke-miterlimit="10" stroke-width="28"
d="M283.64 283.64L336 336"></path>
</svg>
</button>
</div>
</nav>
<div
id="local-search"
style="display: none">
<input
class="navbar-menu-item"
id="search-input"
placeholder="请输入搜索内容..." />
<div id="search-content"></div>
</div>
<div class="section-wrap">
<div class="container">
<div class="columns">
<aside class="left-column">
<div class="card card-author">
<img
src="/images/akesterson.webp"
class="author-img"
width="88"
height="88"
alt="author avatar">
<p class="author-name">Andrew Kesterson</p>
<p class="author-description"><center><i>"Love God. Live Righteously. Die Well."</i> <br/> <br/> <a target="_blank" rel="noopener" href="https://source.starfort.tech/andrew">Source Code</a> || <a target="_blank" rel="noopener" href="https://www.linkedin.com/in/andrewkesterson/">LinkedIn</a> <br/> </center></p>
<div class="author-message">
<a
class="author-posts-count"
href="/archives">
<span>35</span>
<span>Posts</span>
</a>
<a
class="author-categories-count"
href="/categories">
<span>9</span>
<span>Categories</span>
</a>
<a
class="author-tags-count"
href="/tags">
<span>0</span>
<span>Tags</span>
</a>
</div>
</div>
<div class="sticky-tablet">
<article class="display-when-two-columns spacer">
<div class="card card-content toc-card">
<div class="toc-header">
<i
class="iconfont icon-menu"
style="padding-right: 2px;">
</i>TOC
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-bit-Flash-ADC-using-LM339N-comparators"><span class="toc-text">3-bit Flash ADC using LM339N comparators</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Snake-Game-on-an-8x8-LED-Matrix"><span class="toc-text">Snake Game on an 8x8 LED Matrix</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Closing-Thoughts"><span class="toc-text">Closing Thoughts</span></a></li></ol>
</div>
</article>
<article class="card card-content categories-widget">
<div class="categories-card">
<div class="categories-header">
<i
class="iconfont icon-fenlei"
style="padding-right: 2px;">
</i>Categories
</div>
<div class="categories-list">
<a href="/categories/Books/">
<div class="categories-list-item">
Books
<span class="categories-list-item-badge">14</span>
</div>
</a>
<a href="/categories/Faith/">
<div class="categories-list-item">
Faith
<span class="categories-list-item-badge">7</span>
</div>
</a>
<a href="/categories/Technology/">
<div class="categories-list-item">
Technology
<span class="categories-list-item-badge">16</span>
</div>
</a>
<a href="/categories/Outdoors/">
<div class="categories-list-item">
Outdoors
<span class="categories-list-item-badge">1</span>
</div>
</a>
<a href="/categories/Philosophy/">
<div class="categories-list-item">
Philosophy
<span class="categories-list-item-badge">7</span>
</div>
</a>
<a href="/categories/Current-Events/">
<div class="categories-list-item">
Current-Events
<span class="categories-list-item-badge">6</span>
</div>
</a>
<a href="/categories/Leadership/">
<div class="categories-list-item">
Leadership
<span class="categories-list-item-badge">8</span>
</div>
</a>
<a href="/categories/History/">
<div class="categories-list-item">
History
<span class="categories-list-item-badge">1</span>
</div>
</a>
<a href="/categories/Liberal-Education/">
<div class="categories-list-item">
Liberal-Education
<span class="categories-list-item-badge">1</span>
</div>
</a>
</div>
</div>
</article>
<article class="card card-content tags-widget">
<div class="tags-card">
<div class="tags-header">
<i
class="iconfont icon-biaoqian"
style="padding-right: 2px;">
</i>hot tags
</div>
<div class="tags-list">
</div>
</div>
</article>
</div>
</aside>
<main class="main-column">
<article class="card card-content">
<header>
<h1 class="post-title">
Devlog Entry - 18 June 2026
</h1>
</header>
<div class="post-meta post-show-meta">
<time datetime="2026-06-18T16:47:16.000Z">
<i
class="iconfont icon-calendar"
style="margin-right: 2px;">
</i>
<span>2026-06-18</span>
</time>
<span class="dot"></span>
<a
href="/categories/Technology/"
class="post-meta-link">
Technology
</a>
<span class="dot"></span>
<span>562 words</span>
</div>
</header>
<div
id="section"
class="post-content">
<p>Ive spent all my spare (technology) time learning more about the ESP32, the Arduino HAL, and using some additional integrated circuits.</p>
<h2 id="3-bit-Flash-ADC-using-LM339N-comparators"><a href="#3-bit-Flash-ADC-using-LM339N-comparators" class="headerlink" title="3-bit Flash ADC using LM339N comparators"></a>3-bit Flash ADC using LM339N comparators</h2><blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">Put together a 3 bit flash ADC while waiting on some other tasks to finish. I had meant to do this last week but I didnt have time. I did learn some new things here, as usual. <a target="_blank" rel="noopener" href="https://t.co/AAU8mq8pWy">pic.twitter.com/AAU8mq8pWy</a></p>&mdash; Andrew Kesterson (@AKLabsDotNet) <a target="_blank" rel="noopener" href="https://x.com/AKLabsDotNet/status/2064431239013048425?ref_src=twsrc%5Etfw">June 9, 2026</a></blockquote> <script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
<p>This project uses an LM339N comparator chip, a voltage ladder, a potentiometer and 4 LEDs to create a Flash Analog to Digital Converter.</p>
<p>Its worth pointing out that this ADC outputs thermometer code (unary code), not binary. I would have needed to use an additional priority encoder to get it converted down to binary. I didnt have a priority encoder on hand (though I couldve built one with quite a few other chips I did have on hand), so I just left it at unary output.</p>
<p>Lessons learned from this project:</p>
<ul>
<li>What is a voltage ladder</li>
<li>How pull up and pull down resistors work</li>
<li>Breadboards are small finnicky things</li>
<li>How USB power delivery dummies work</li>
</ul>
<p>There is a more detailed writeup about this project <a target="_blank" rel="noopener" href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/07-LM339N-ADC/README.md">in my source repository</a>.</p>
<h2 id="Snake-Game-on-an-8x8-LED-Matrix"><a href="#Snake-Game-on-an-8x8-LED-Matrix" class="headerlink" title="Snake Game on an 8x8 LED Matrix"></a>Snake Game on an 8x8 LED Matrix</h2><blockquote class="twitter-tweet" data-media-max-width="560"><p lang="en" dir="ltr">It works! Snake on an ESP32 with a 7 segment scoreboard and adjustable difficulty using an 8x8 LED matrix as a display <a target="_blank" rel="noopener" href="https://t.co/RZPqkQRxEZ">pic.twitter.com/RZPqkQRxEZ</a></p>&mdash; Andrew Kesterson (@AKLabsDotNet) <a target="_blank" rel="noopener" href="https://x.com/AKLabsDotNet/status/2067645849258103188?ref_src=twsrc%5Etfw">June 18, 2026</a></blockquote> <script async src="https://platform.x.com/widgets.js" charset="utf-8"></script>
<p>This project uses 3 74HC595 serial to parallel shift registers, a 7-segment display multi unit, an 8x8 LED matrix, an active buzzer, an NPN transistor, a joystick (later replaced with 4 buttons), a handful of resistors and a potentiometer to make a playable Snake game.</p>
<p>This was easily the most challenging project so far, taking me almost two weeks to get it working right. I wound up having to break the project out across 4 separate breadboards. The breadboards look as gross in real life as it does in Fritzing.</p>
<p>Lessons Learned</p>
<ul>
<li>C has admitted design flaws</li>
<li>Hardware debouncing is definitely the way to go</li>
<li>The Arduino IDE debugger really sucks</li>
<li>Its been a long time since I had to think this hard about what my code was doing to the hardware</li>
<li>Compiling, uploading, and debugging Arduino code from the CLI</li>
<li>Breadboards probably introduce just as many bugs as I do</li>
<li>How to drive a 7-segment display and an 8x8 LED matrix using shift registers</li>
<li>Embedded platforms have undocumented limits that may surprise you</li>
<li>You dont need lots of pixels, or even colors, to make it fun</li>
</ul>
<p>There is a more detailed writeup about this project <a target="_blank" rel="noopener" href="https://source.starfort.tech/andrew/esp32-learning/src/branch/main/08-74HC595-Snake/README.md">in my source repository</a>.</p>
<h2 id="Closing-Thoughts"><a href="#Closing-Thoughts" class="headerlink" title="Closing Thoughts"></a>Closing Thoughts</h2><p>That 8x8 LED Matrix Snake game left me taxed. Im probably going to lay off the embedded stuff for a week or so while I work out some stuff in libakgl related to partitioning the game world for actor collisions and some physics engine bits. Then Im on vacation until July 6, so I may or may not have a devlog in the first week of July at all.</p>
<p>Also, getting into embedded development is like getting into Warhammer. When a new chip costs pennies, a new MCU costs a dollar, an entire dev board costs 5 or 10 bucks, and a new Pi is less than $50…</p>
<center><img src="/ srcset="data:image/svg+xml,%3Csvg%20xmlns='http://www.w3.org/2000/svg'%20viewBox='0%200%20300%20300'%3E%3C/svg%3E" data-src="/images/posts/devlog-20260618/embeddedexpensivebutfun.gif" class="lozad post-image"images/posts/devlog-20260618/embeddedexpensivebutfun.gif"/><center>
<!--
-- tags
INFO Validating config
INFO Start processing
Name Posts Path
No tags.
---------------
-- categories
INFO Validating config
INFO Start processing
Name Posts
Books 14
Current Events 5
Current Events 0
Faith 7
History 1
Leadership 8
Liberal Education 1
Outdoors 1
Philosophy 6
Philosophy 0
Technology 13
technology 0
--!>
</div>
<div>
</div>
</article>
<div class="nav">
<div class="nav-item-prev">
<a
href="/2026/06/23/News-2026-Week-26/"
class="nav-link">
<i class="iconfont icon-left nav-prev-icon"></i>
<div>
<div class="nav-label">Prev</div>
<div class="nav-title">News - 2026 - Week - 26 </div>
</div>
</a>
</div>
<div class="nav-item-next">
<a
href="/2026/06/08/Carrying-That-Weight/"
class="nav-link">
<div>
<div class="nav-label">Next</div>
<div class="nav-title">Carrying That Weight </div>
</div>
<i class="iconfont icon-right nav-next-icon"></i>
</a>
</div>
</div>
<div
class="card card-content toc-card"
id="mobiletoc">
<div class="toc-header">
<i
class="iconfont icon-menu"
style="padding-right: 2px;">
</i>TOC
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-bit-Flash-ADC-using-LM339N-comparators"><span class="toc-text">3-bit Flash ADC using LM339N comparators</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Snake-Game-on-an-8x8-LED-Matrix"><span class="toc-text">Snake Game on an 8x8 LED Matrix</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Closing-Thoughts"><span class="toc-text">Closing Thoughts</span></a></li></ol>
</div>
</main>
<aside class="right-column">
<div class="sticky-widescreen">
<article class="card card-content toc-card">
<div class="toc-header">
<i
class="iconfont icon-menu"
style="padding-right: 2px;">
</i>TOC
</div>
<ol class="toc"><li class="toc-item toc-level-2"><a class="toc-link" href="#3-bit-Flash-ADC-using-LM339N-comparators"><span class="toc-text">3-bit Flash ADC using LM339N comparators</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Snake-Game-on-an-8x8-LED-Matrix"><span class="toc-text">Snake Game on an 8x8 LED Matrix</span></a></li><li class="toc-item toc-level-2"><a class="toc-link" href="#Closing-Thoughts"><span class="toc-text">Closing Thoughts</span></a></li></ol>
</article>
<article class="card card-content">
<div class="recent-posts-card">
<div class="recent-posts-header">
<i
class="iconfont icon-wenzhang_huaban"
style="padding-right: 2px;">
</i>Recent Posts
</div>
<div class="recent-posts-list">
<div class="recent-posts-item">
<div class="recent-posts-item-title">2026-06-27</div>
<a href="/2026/06/27/News-2026-Week-2/"><div class="recent-posts-item-content">News-2026-Week-2</div></a>
</div>
<div class="recent-posts-item">
<div class="recent-posts-item-title">2026-06-27</div>
<a href="/2026/06/27/Devlog-20260627/"><div class="recent-posts-item-content">Devlog Entry - 27 June 2026</div></a>
</div>
<div class="recent-posts-item">
<div class="recent-posts-item-title">2026-06-23</div>
<a href="/2026/06/23/News-2026-Week-26/"><div class="recent-posts-item-content">News - 2026 - Week - 26</div></a>
</div>
<div class="recent-posts-item">
<div class="recent-posts-item-title">2026-06-18</div>
<a href="/2026/06/18/Devlog-20260618/"><div class="recent-posts-item-content">Devlog Entry - 18 June 2026</div></a>
</div>
</div>
</div>
</article>
</div>
</aside>
</div>
</div>
</div>
</div>
<footer class="footer">
<div class="footer-container">
<div>
<div class="footer-dsc">
<span>
Copyright ©
-
2026
</span>
&nbsp;
<a
href="mailto:andrew@aklabs.net"
class="footer-link">
Andrew Kesterson
</a>
<br/>
</div>
</div>
<div class="footer-dsc">
Powered by
<a
href="https://hexo.io/"
class="footer-link"
target="_blank"
rel="nofollow noopener noreferrer">
&nbsp;Hexo
</a>
<span>&nbsp;|&nbsp;</span>
Theme -
<a
href="https://github.com/theme-kaze"
class="footer-link"
target="_blank"
rel="nofollow noopener noreferrer">
&nbsp;Kaze
</a>
</div>
</footer>
<a
role="button"
id="scrollbutton"
class="basebutton"
aria-label="回到顶部">
<i class="iconfont icon-arrowleft button-icon"></i>
</a>
<a
role="button"
id="menubutton"
aria-label="menu button"
class="basebutton">
<i class="iconfont icon-menu button-icon"></i>
</a>
<a
role="button"
id="popbutton"
class="basebutton"
aria-label="控制中心">
<i class="iconfont icon-expand button-icon"></i>
</a>
<a
role="button"
id="darkbutton"
class="basebutton darkwidget"
aria-label="夜色模式">
<i class="iconfont icon-weather button-icon"></i>
</a>
<a
role="button"
id="searchbutton"
class="basebutton searchwidget"
aria-label="搜索">
<i class="iconfont icon-search button-icon"></i>
</a>
<script>
var addImgLayout = function () {
var img = document.querySelectorAll('.post-content img')
var i
for (i = 0; i < img.length; i++) {
var wrapper = document.createElement('a')
wrapper.setAttribute('href', img[i].getAttribute('data-src'))
wrapper.setAttribute('aria-label', 'illustration')
wrapper.style.cssText =
'width: 100%; display: flex; justify-content: center;'
if (img[i].alt) wrapper.dataset.caption = img[i].alt
wrapper.dataset.nolink = true
img[i].before(wrapper)
wrapper.append(img[i])
var divWrap = document.createElement('div')
divWrap.classList.add('gallery')
wrapper.before(divWrap)
divWrap.append(wrapper)
}
baguetteBox.run('.gallery')
}
</script>
<script>
loadScript(
"/js/lib/lightbox/baguetteBox.min.js",
addImgLayout
)
</script>
<script src="/js/main.js"></script>
<script>
var addLazyload = function () {
var observer = lozad('.lozad', {
load: function (el) {
el.srcset = el.getAttribute('data-src')
},
loaded: function (el) {
el.classList.add('loaded')
},
})
observer.observe()
}
</script>
<script>
loadScript('/js/lib/lozad.min.js', addLazyload)
</script>
<script src="//instant.page/5.1.0" type="module"
integrity="sha384-by67kQnR+pyfy8yWP4kPO12fHKRLHZPfEsiSXR8u2IKcTdxD805MGUXBzVPnkLHw"></script>
<script>
var googleAnalytics = function () {
window.dataLayer = window.dataLayer || []
function gtag() {
dataLayer.push(arguments)
}
gtag('js', new Date())
gtag('config', 'G-S3YLF516N6')
}
</script>
<script>
loadScript(
'https://www.googletagmanager.com/gtag/js?id=' +
'G-S3YLF516N6',
googleAnalytics
)
</script>
</body>
</html>