summaryrefslogtreecommitdiffstats
path: root/_site
diff options
context:
space:
mode:
authorSadeep Madurange <sadeep@asciimx.com>2025-12-15 22:37:40 +0800
committerSadeep Madurange <sadeep@asciimx.com>2025-12-15 22:37:40 +0800
commit0759546e7de6a96fda6a9a004e3f37fe2ddcb75a (patch)
tree6e998985123ae21b516d04858ae96eb5e7ff9283 /_site
parent73324b887ac675af744d2b187cdf52a9d68bd8cc (diff)
downloadwww-0759546e7de6a96fda6a9a004e3f37fe2ddcb75a.tar.gz
Etlas write-up.term
Diffstat (limited to '_site')
-rw-r--r--_site/feed.xml2
-rw-r--r--_site/posts.xml2
-rw-r--r--_site/projects/etlas/index.html78
-rw-r--r--_site/robots.txt2
-rw-r--r--_site/sitemap.xml30
5 files changed, 74 insertions, 40 deletions
diff --git a/_site/feed.xml b/_site/feed.xml
index 58ef809..00889b5 100644
--- a/_site/feed.xml
+++ b/_site/feed.xml
@@ -1 +1 @@
-<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/feed.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-14T22:02:29+08:00</updated><id>/feed.xml</id><title type="html">ASCIIMX | Blog</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">How I manage Suckless software installations</title><link href="/blog/suckless-software/" rel="alternate" type="text/html" title="How I manage Suckless software installations" /><published>2025-11-30T00:00:00+08:00</published><updated>2025-11-30T00:00:00+08:00</updated><id>/blog/suckless-software</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Since suckless software requires users to modify the source code and recompile to customize, I need a way to maintain patches over the long term while retaining the ability to upgrade the software as new versions are released.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="/blog/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2025-09-14T00:00:00+08:00</published><updated>2025-09-14T00:00:00+08:00</updated><id>/blog/neo4j-a-star-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Back in 2018, we used Neo4J graph database to track the movement of marine vessels. We were interested in the shortest path a ship could take through a network of about 13,000 route points. Algorithms based on graph theory, such as A* search, provide optimal solutions to such problems. In other words, the set of route points lends itself well to a model based on graphs.]]></summary></entry><entry><title type="html">MOSFETs as electronic switches</title><link href="/blog/mosfet-switches/" rel="alternate" type="text/html" title="MOSFETs as electronic switches" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>/blog/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Recently, I needed a low-power circuit for one of my battery-operated projects. Much of the system’s power savings depended on its ability to electronically switch off components, such as servos, that draw high levels of quiescent currents. My search for a solution led me to MOSFETs, transistors capable of controlling circuits operating at voltages far above their own.]]></summary></entry><entry><title type="html">How to configure ATmega328P microcontrollers to run at 3.3V and 5V</title><link href="/blog/arduino-uno/" rel="alternate" type="text/html" title="How to configure ATmega328P microcontrollers to run at 3.3V and 5V" /><published>2025-04-10T00:00:00+08:00</published><updated>2025-04-10T00:00:00+08:00</updated><id>/blog/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This is a quick reference for wiring up ATmega328P ICs to run at 5V and 3.3V. While the 5V configuration is common, the 3.3V configuration can be useful in low-power applications and when interfacing with parts that themselves run at 3.3V. In this guide, the 5V setup is configured with a 16MHz crystal oscillator, while the 3.3V configuration makes use of an 8MHz crystal oscillator.]]></summary></entry><entry><title type="html">How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title><link href="/blog/arduino-due/" rel="alternate" type="text/html" title="How to set up ATSAM3X8E microcontrollers for bare-metal programming in C" /><published>2024-10-05T00:00:00+08:00</published><updated>2024-10-05T00:00:00+08:00</updated><id>/blog/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This article is a step-by-step guide for programming bare-metal ATSAM3X8E chips found on Arduino Due boards. It also includes notes on the chip’s memory layout relevant for writing linker scripts. The steps described in this article were tested on an OpenBSD workstation.]]></summary></entry></feed> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="http://localhost:4000/feed.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2025-12-15T22:35:43+08:00</updated><id>http://localhost:4000/feed.xml</id><title type="html">ASCIIMX | Blog</title><author><name>W. D. Sadeep Madurange</name></author><entry><title type="html">How I manage Suckless software installations</title><link href="http://localhost:4000/blog/suckless-software/" rel="alternate" type="text/html" title="How I manage Suckless software installations" /><published>2025-11-30T00:00:00+08:00</published><updated>2025-11-30T00:00:00+08:00</updated><id>http://localhost:4000/blog/suckless-software</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Since suckless software requires users to modify the source code and recompile to customize, I need a way to maintain patches over the long term while retaining the ability to upgrade the software as new versions are released.]]></summary></entry><entry><title type="html">Neo4J A* search</title><link href="http://localhost:4000/blog/neo4j-a-star-search/" rel="alternate" type="text/html" title="Neo4J A* search" /><published>2025-09-14T00:00:00+08:00</published><updated>2025-09-14T00:00:00+08:00</updated><id>http://localhost:4000/blog/neo4j-a-star-search</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Back in 2018, we used Neo4J graph database to track the movement of marine vessels. We were interested in the shortest path a ship could take through a network of about 13,000 route points. Algorithms based on graph theory, such as A* search, provide optimal solutions to such problems. In other words, the set of route points lends itself well to a model based on graphs.]]></summary></entry><entry><title type="html">MOSFETs as electronic switches</title><link href="http://localhost:4000/blog/mosfet-switches/" rel="alternate" type="text/html" title="MOSFETs as electronic switches" /><published>2025-06-22T00:00:00+08:00</published><updated>2025-06-22T00:00:00+08:00</updated><id>http://localhost:4000/blog/mosfet-switches</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[Recently, I needed a low-power circuit for one of my battery-operated projects. Much of the system’s power savings depended on its ability to electronically switch off components, such as servos, that draw high levels of quiescent currents. My search for a solution led me to MOSFETs, transistors capable of controlling circuits operating at voltages far above their own.]]></summary></entry><entry><title type="html">How to configure ATmega328P microcontrollers to run at 3.3V and 5V</title><link href="http://localhost:4000/blog/arduino-uno/" rel="alternate" type="text/html" title="How to configure ATmega328P microcontrollers to run at 3.3V and 5V" /><published>2025-04-10T00:00:00+08:00</published><updated>2025-04-10T00:00:00+08:00</updated><id>http://localhost:4000/blog/arduino-uno</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This is a quick reference for wiring up ATmega328P ICs to run at 5V and 3.3V. While the 5V configuration is common, the 3.3V configuration can be useful in low-power applications and when interfacing with parts that themselves run at 3.3V. In this guide, the 5V setup is configured with a 16MHz crystal oscillator, while the 3.3V configuration makes use of an 8MHz crystal oscillator.]]></summary></entry><entry><title type="html">How to set up ATSAM3X8E microcontrollers for bare-metal programming in C</title><link href="http://localhost:4000/blog/arduino-due/" rel="alternate" type="text/html" title="How to set up ATSAM3X8E microcontrollers for bare-metal programming in C" /><published>2024-10-05T00:00:00+08:00</published><updated>2024-10-05T00:00:00+08:00</updated><id>http://localhost:4000/blog/arduino-due</id><author><name>W. D. Sadeep Madurange</name></author><summary type="html"><![CDATA[This article is a step-by-step guide for programming bare-metal ATSAM3X8E chips found on Arduino Due boards. It also includes notes on the chip’s memory layout relevant for writing linker scripts. The steps described in this article were tested on an OpenBSD workstation.]]></summary></entry></feed> \ No newline at end of file
diff --git a/_site/posts.xml b/_site/posts.xml
index 386871a..4a92130 100644
--- a/_site/posts.xml
+++ b/_site/posts.xml
@@ -1 +1 @@
-<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="/posts.xml" rel="self" type="application/atom+xml" /><link href="/" rel="alternate" type="text/html" /><updated>2025-12-14T22:02:29+08:00</updated><id>/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed> \ No newline at end of file
+<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="4.4.1">Jekyll</generator><link href="http://localhost:4000/posts.xml" rel="self" type="application/atom+xml" /><link href="http://localhost:4000/" rel="alternate" type="text/html" /><updated>2025-12-15T22:35:43+08:00</updated><id>http://localhost:4000/posts.xml</id><title type="html">ASCIIMX</title><author><name>W. D. Sadeep Madurange</name></author></feed> \ No newline at end of file
diff --git a/_site/projects/etlas/index.html b/_site/projects/etlas/index.html
index f8f539f..6b2906b 100644
--- a/_site/projects/etlas/index.html
+++ b/_site/projects/etlas/index.html
@@ -44,9 +44,7 @@
<h2 class="center" id="title">ETLAS: E-PAPER DASHBOARD</h2>
<h6 class="center">05 SEPTEMBER 2024</h5>
<br>
- <div class="twocol justify"><p>Etlas is a news, stock market, and weather tracker powered by an ESP32 NodeMCU
-D1, featuring a 7.5-inch <a href="https://www.waveshare.com/" class="external" target="_blank" rel="noopener noreferrer">Waveshare</a> e-paper display and a
-DHT22 sensor module.</p>
+ <div class="twocol justify"><p>Etlas is a weather, news, and stock price tracking system.</p>
<table style="border: none;">
<tr style="border: none;">
@@ -55,34 +53,70 @@ DHT22 sensor module.</p>
</tr>
</table>
-<p>The top left panel displays the end-of-day stock prices from the <a href="https://polygon.io/" class="external" target="_blank" rel="noopener noreferrer">Polygon.io</a> API, relayed through my own
-FastCGI-wrapped Flask app hosted on a VPS. The stock symbols can be configured
-through the Flask app’s application settings. The server.fcgi script enclosed
-in the tarball at the end of the page contains the Flask app.</p>
+<h2 id="acknowledgements">Acknowledgements</h2>
-<p>The following diagram outlines this system architecture.</p>
+<p>The e-paper display driver in the epd.c file of the project is derived from <a href="https://github.com/waveshareteam/e-Paper" class="external" target="_blank" rel="noopener noreferrer">Waveshare examples</a> for Arduino
+and STM32 platforms.</p>
-<p><img src="etlas_arch.png" alt="architecture" /></p>
+<p>The exceptionally elegant algorithm in the file dht.c, which reads DHT22 sensor
+data by comparing consecutive pulses, I ported directly from <a href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external" target="_blank" rel="noopener noreferrer">this</a> implementation for ESP8266
+modules to my ESP32. All credit for the algorithm belongs to them.</p>
+
+<h2 id="overview">Overview</h2>
-<p>Unlike my <a href="/projects/e-reader">e-reader</a>, which worked with raster images,
-Etlas downloads time series data as CSV and computes the price curves on the
-ESP32.</p>
+<p>Etlas comprises an embedded system featuring an ESP32 NodeMCU D1
+microcontroller, a 7.5″ <a href="https://www.waveshare.com/" class="external" target="_blank" rel="noopener noreferrer">Waveshare</a> e-paper display, a
+DHT22 weather sensor, and a server backend consisting of a FastCGI-wrapped
+Flask app. The following diagram outlines this system architecture.</p>
+
+<p><img src="etlas_arch.png" alt="architecture" /></p>
-<p>The more prominent panel on the right of the e-paper display shows local
-(Singapore) and world news from the <a href="https://www.channelnewsasia.com/" class="external" target="_blank" rel="noopener noreferrer">Channel News Asia</a>
-RSS feed. The MCU downloads and parses XML data from the RSS feed directly
-before rendering it to the display. Although I did it this way to avoid writing
-server code, it limits the feeds from which Etlas can receive data. In a future
-version, I will relay the RSS feed through a server (like the stock prices) to
-make it more flexible.</p>
+<p>The embedded application, written in C with the help of the ESP-IDF v5.2.1,
+connects to a (2.4GHz) WiFi network at startup and obtains time from an NTP
+server. It then composites and updates an internal pixel buffer using data
+acquired from various data sources and renders to the screen by writing to its
+Serial Peripheral Interface.</p>
+
+<h2 id="price-curves">Price curves</h2>
+
+<p>On the e-paper display, the top-left panel displays end-of-day price curves
+over two weeks from the <a href="https://polygon.io/" class="external" target="_blank" rel="noopener noreferrer">Polygon.io</a> API. The
+microcontroller’s 512KB SRAM limits the price curves to two weeks. Instead of
+using raster images for complex graphics—like e-paper projects often do—Etlas
+computes the price curves from CSV data on the fly using the ESP32’s 160MHz
+microprocessor. To avoid the overhead of floating-point arithmetic, all
+computations are performed on integers. The <code class="language-plaintext highlighter-rouge">gui_plot_stocks()</code> function in the
+gui.c file contains the rendering logic.</p>
+
+<p>Proxying the price feeds through the Flask app permits me to configure the
+tickers I’m interested in via its application settings. The Flask app cycles
+through the tickers in its configuration file as it receives requests from the
+embedded software. The Flask app is secured with basic authentication
+implemented using htpasswd and OpenBSD’s httpd web server. This FastCGI-wrapped
+architecture dramatically reduces the complexity of the server code and
+increases system reliability.</p>
+
+<h2 id="news-feed">News feed</h2>
+
+<p>The more prominent panel on the right displays news from <a href="https://www.channelnewsasia.com/" class="external" target="_blank" rel="noopener noreferrer">Channel News Asia</a>. The embedded program downloads
+and parses the RSS feed before rendering it to the display. The character
+glyphs used for rendering news are stored in header files in the sprites
+directory as bitmaps. I created the glyphs manually by saving them as images in
+GIMP and rasterizing them with ImageMagick.</p>
+
+<p>I connected the embedded system directly to the RSS feed to write less server
+code (the focus of this project was the embedded system). In hindsight,
+however, it limits the feeds from which Etlas can receive data. In a future
+version, I will relay the RSS feed through the backend (like the stock prices)
+to make it more flexible.</p>
+
+<h2 id="weather-data">Weather data</h2>
<p>The bottom panels (middle and right) display the temperature and relative
humidity from a DHT22 sensor. The DHT22 driver, arguably the most interesting
part of the software, reads real-time sensor data by comparing relative pulse
widths. The pulses themselves are too quick for the ESP32 to reliably measure
-directly. I ported <a href="https://github.com/Fonger/ESP8266-RTOS-DHT" class="external" target="_blank" rel="noopener noreferrer">this</a>
-implementation for ESP8266 modules to my ESP32. All credit for the algorithm
-belongs to them.</p>
+directly.</p>
<p>Much of the heavy lifting of acquiring, interpreting, and rendering data from
different data sources is performed on the microcontroller using less than 512
diff --git a/_site/robots.txt b/_site/robots.txt
index e087884..d297064 100644
--- a/_site/robots.txt
+++ b/_site/robots.txt
@@ -1 +1 @@
-Sitemap: /sitemap.xml
+Sitemap: http://localhost:4000/sitemap.xml
diff --git a/_site/sitemap.xml b/_site/sitemap.xml
index 1b23cd3..5130d9f 100644
--- a/_site/sitemap.xml
+++ b/_site/sitemap.xml
@@ -1,59 +1,59 @@
<?xml version="1.0" encoding="UTF-8"?>
<urlset xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.sitemaps.org/schemas/sitemap/0.9 http://www.sitemaps.org/schemas/sitemap/0.9/sitemap.xsd" xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<url>
-<loc>/blog/arduino-due/</loc>
+<loc>http://localhost:4000/blog/arduino-due/</loc>
<lastmod>2024-10-05T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/blog/arduino-uno/</loc>
+<loc>http://localhost:4000/blog/arduino-uno/</loc>
<lastmod>2025-04-10T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/blog/mosfet-switches/</loc>
+<loc>http://localhost:4000/blog/mosfet-switches/</loc>
<lastmod>2025-06-22T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/blog/neo4j-a-star-search/</loc>
+<loc>http://localhost:4000/blog/neo4j-a-star-search/</loc>
<lastmod>2025-09-14T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/blog/suckless-software/</loc>
+<loc>http://localhost:4000/blog/suckless-software/</loc>
<lastmod>2025-11-30T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/e-reader/</loc>
+<loc>http://localhost:4000/projects/e-reader/</loc>
<lastmod>2023-10-24T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/matrix-digital-rain/</loc>
+<loc>http://localhost:4000/projects/matrix-digital-rain/</loc>
<lastmod>2024-01-12T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/etlas/</loc>
+<loc>http://localhost:4000/projects/etlas/</loc>
<lastmod>2024-09-05T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/bumblebee/</loc>
+<loc>http://localhost:4000/projects/bumblebee/</loc>
<lastmod>2025-04-02T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/my-first-pcb/</loc>
+<loc>http://localhost:4000/projects/my-first-pcb/</loc>
<lastmod>2025-07-14T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/projects/fpm-door-lock/</loc>
+<loc>http://localhost:4000/projects/fpm-door-lock/</loc>
<lastmod>2025-10-03T00:00:00+08:00</lastmod>
</url>
<url>
-<loc>/about/</loc>
+<loc>http://localhost:4000/about/</loc>
</url>
<url>
-<loc>/blog/</loc>
+<loc>http://localhost:4000/blog/</loc>
</url>
<url>
-<loc>/</loc>
+<loc>http://localhost:4000/</loc>
</url>
<url>
-<loc>/projects/</loc>
+<loc>http://localhost:4000/projects/</loc>
</url>
</urlset>