Reviving Retro Tech: Building a Daily News Printer with a Dot Matrix

For many, the day begins in the digital realm, unlocking smartphones and diving into a stream of news and social media updates. While staying informed is crucial, this constant screen engagement can take a toll on mental well-being. Seeking a healthier balance, I decided to explore a more tangible approach to daily news consumption.

This led me to eBay and the purchase of a dot matrix printer. My vision? To create a custom “front page” printed each morning, offering a curated snapshot of the day’s information. This project became a fascinating blend of retro technology and modern information, resulting in a unique daily ritual.

Hear the nostalgic sounds of the printer in action:

[Printer ASMR noises in the video below 👇]

This article will guide you through the journey of building this project, detailing the hardware used, the setup process, and the PHP script that powers this daily printed news experience.

Eager to see the code behind it? Explore the complete source code on the GitHub repo!

Gathering the Essential Hardware for Your Dot Matrix Printer Project

The components required for this project are straightforward. Beyond the dot matrix printer itself, most items are readily available from online retailers like Amazon.

  • Dot Matrix Printer: The heart of the project.
  • Raspberry Pi Zero W: [link]: The mini-computer to drive the printer.
  • Serial to USB Adapter: [link]: For connecting the Raspberry Pi to the printer’s serial interface.
  • Power Supply: To power the Raspberry Pi.

For the dot matrix printer, I opted for a Star NP-10, a model seemingly from the 1980s. While my specific model is a Star NP-10, the good news is that any dot matrix printer equipped with a serial port should be compatible for this project. Prices can vary, typically ranging from $80 to $120 USD, but persistence can pay off – I managed to acquire mine for about half price, listed as “untested”.

Upon arrival, a little cleaning and attention to the ink ribbon cartridge (a delightful throwback to typewriter technology!) were needed. However, after these minor adjustments, it sprang to life, successfully printing a test page.

Connecting the hardware was the next step. The Raspberry Pi, connected to my WiFi network, interfaced with the printer’s serial port via the USB adapter. After powering on the printer and accessing the Raspberry Pi via ssh, verification confirmed the printer’s availability at /dev/usb/lp0.

Now, the pivotal question: How do you command this dot matrix printer to print?

Decoding the Dot Matrix Printer Language

With the printer recognized at lp0, my initial thought was to directly send raw text to it using the echo command. I attempted:

<div><span>echo</span><span>"</span><span>Hello, world!</span><span>"</span><span>></span><span>/dev/usb/lp0</span></div>

However, this resulted in a “permission denied” error. A quick fix using chmod resolved this:

<div><span>sudo</span><span>chmod</span><span>666</span><span>/dev/usb/lp0</span></div>

While there might be more refined permission management methods, this allowed the echo command to proceed, and “Hello, world!” appeared on the dot matrix printer’s output! Success – direct data transmission to the printer was possible. The next challenge was to develop a more sophisticated approach.

PHP, my preferred programming language, became the natural choice. I created a basic script to interact with the printer file using fopen() and began sending text. Experimenting with sentences, spacing, and even some unicode art quickly revealed limitations in the printer’s character support. It wasn’t as versatile as modern systems in terms of character encoding.

Alt text: Garbled output from dot matrix printer showing encoding errors due to incompatible character set.

Realizing a deeper understanding was needed, I embarked on a digital archeological dig for information on this vintage hardware. Fortunately, thanks to dedicated internet archivists, I unearthed a complete manual for the printer – scanned and available as a PDF.

The manual unveiled that, whether due to its age or design choices, this dot matrix printer operates with a very specific character set. Loosely based on the IBM PC’s Code Page 437, it primarily includes standard alphanumeric characters, along with a limited selection of special symbols, lines, and box-drawing characters. This discovery was key to controlling the printer effectively.

Sending these supported characters became straightforward. PHP’s ability to output hexadecimal values allowed direct command of the printer’s character set:

<div><span>$</span><span>horizontalDouble </span><span>=</span><span>"</span><span>xCD</span><span>"</span><span>;</span></div><div><span>$</span><span>deg </span><span>=</span><span>"</span><span>xF8</span><span>"</span><span>;</span></div><div> </div><div><span>echo</span><span>str_repeat</span><span>($</span><span>horizontalDouble</span><span>,</span><span>24</span><span>);</span></div><div><span>echo</span><span>'</span><span>78</span><span>'</span><span>.</span><span>$</span><span>deg </span><span>.</span><span>'</span><span>F</span><span>'</span><span>.</span><span> PHP_EOL</span><span>;</span></div>

With the ability to reliably print text and special characters, the next step was to define the content for my daily front page.

Curating Data Feeds for a Personalized Dot Matrix News

My vision for the printed front page encompassed four key sections, mirroring my typical morning digital checks: weather, stock market updates, major news headlines, and top Reddit posts. The aim was to replicate the information I usually access on my phone, but in a physical, limited format.

Keeping the project budget-conscious, I prioritized free data sources. The GitHub repo, a treasure trove of free and public APIs, proved invaluable. I explored this repository to identify APIs suitable for each section of my front page.

For each data category, I developed basic PHP code to fetch data from the chosen API endpoints. The scripts extracted relevant information and compiled it into a unified data array. To ensure data integrity, the scripts were designed to halt early if any section failed to retrieve data, prompting a restart at a later time. This robustness was important for daily automated operation.

The following code snippet illustrates the process of fetching news headlines:

<div><span>// Get news headlines data</span></div><div><span>echo</span><span>"</span><span>Fetching news headlines data...</span><span>"</span><span>.</span><span> PHP_EOL</span><span>;</span></div><div><span>$</span><span>newsUrl </span><span>=</span><span> NEWS </span><span>.</span><span>"</span><span>?api-key=</span><span>"</span><span>.</span><span> NEWSKEY</span><span>;</span></div><div><span>$</span><span>newsData </span><span>=</span><span>[];</span></div><div><span>$</span><span>newsAmount </span><span>=</span><span>0</span><span>;</span></div><div> </div><div><span>$</span><span>data </span><span>=</span><span>json_decode</span><span>(</span><span>file_get_contents</span><span>($</span><span>newsUrl</span><span>),</span><span>true);</span></div><div> </div><div><span>if</span><span>(!</span><span>isset</span><span>($</span><span>data</span><span>[</span><span>'</span><span>results</span><span>'</span><span>]))</span><span>{</span></div><div><span>die</span><span>(</span><span>"</span><span>Unable to retrieve news data</span><span>"</span><span>);</span></div><div><span>}</span></div><div> </div><div><span>foreach</span><span>($</span><span>data</span><span>[</span><span>'</span><span>results</span><span>'</span><span>]</span><span>as</span><span>$</span><span>article</span><span>)</span><span>{</span></div><div><span>if</span><span>(</span></div><div><span>($</span><span>article</span><span>[</span><span>'</span><span>type</span><span>'</span><span>]</span><span>===</span><span>'</span><span>Article</span><span>'</span><span>)</span><span>&&</span></div><div><span>(</span><span>in_array</span><span>($</span><span>article</span><span>[</span><span>'</span><span>section</span><span>'</span><span>],</span><span>[</span><span>'</span><span>U.S.</span><span>'</span><span>,</span><span>'</span><span>World</span><span>'</span><span>,</span><span>'</span><span>Weather</span><span>'</span><span>,</span><span>'</span><span>Arts</span><span>'</span><span>]))</span><span>&&</span></div><div><span>($</span><span>newsAmount </span><span><span> MAXNEWS</span><span>)</span></span></div><div><span>)</span><span>{</span></div><div><span>$</span><span>newsData</span><span>[]</span><span>=</span><span>$</span><span>article</span><span>;</span></div><div><span>$</span><span>newsAmount</span><span>++;</span></div><div><span>}</span></div><div><span>}</span></div>

Variables like NEWS, NEWSKEY, and MAXNEWS, defined as constants at the script’s beginning, offer easy customization.

Executing these data-gathering scripts compiles all the necessary information. The final challenge was formatting this data for the dot matrix printer and sending the raw print commands.

Formatting and Printing the Daily Front Page on Dot Matrix

While simply printing section headings was an option, I aimed for a more visually appealing output. To add some “flair,” I decided to enclose the date, day of the week, and the front page title within a bordered box at the top of the printout.

Achieving this required some careful calculations, leveraging the hexadecimal character codes for box-drawing, the str_repeat function in PHP, and the knowledge that the dot matrix printer’s page width is 80 characters. This combination allowed precise control over text placement and visual elements.

For each section, I printed a concise heading:

<div><span>str_repeat</span><span>($</span><span>horizontalSingle</span><span>,</span><span>3</span><span>)</span><span>.</span><span>"</span><span> WEATHER </span><span>"</span><span>.</span><span>str_repeat</span><span>($</span><span>horizontalSingle</span><span>,</span><span>(</span><span>PAGEWIDTH </span><span>-</span><span>9</span><span>))</span><span>.</span><span>"</span><span>n</span><span>"</span><span>;</span></div>

Followed by the relevant data for that section:

<div><span>"</span><span>"</span><span>.</span><span>round</span><span>(($</span><span>weatherData</span><span>[</span><span>'</span><span>daily</span><span>'</span><span>][</span><span>'</span><span>daylight_duration</span><span>'</span><span>][</span><span>0</span><span>]</span><span>/</span><span>3600</span><span>),</span><span>2</span><span>)</span><span>.</span><span>"</span><span>h of Sunlight - Sunrise: </span><span>"</span><span>.</span><span>date</span><span>(</span><span>'</span><span>g:ia</span><span>'</span><span>,</span><span>strtotime</span><span>($</span><span>weatherData</span><span>[</span><span>'</span><span>daily</span><span>'</span><span>][</span><span>'</span><span>sunrise</span><span>'</span><span>][</span><span>0</span><span>]))</span><span>.</span><span>"</span><span> - Sunset: </span><span>"</span><span>.</span><span>date</span><span>(</span><span>'</span><span>g:ia</span><span>'</span><span>,</span><span>strtotime</span><span>($</span><span>weatherData</span><span>[</span><span>'</span><span>daily</span><span>'</span><span>][</span><span>'</span><span>sunset</span><span>'</span><span>][</span><span>0</span><span>]))</span><span>.</span><span>"</span><span>n</span><span>"</span><span>;</span></div>

For weather and stock data, single-line printing was sufficient. However, news headlines and Reddit post titles often exceeded the page width. While the printer could wrap lines automatically, I wanted to prevent words from being split mid-word across lines.

To handle this, I implemented a function to manage line breaks, ensuring words remained intact and lines were within the 80-character limit. The splitString function achieves this:

<div><span>function</span><span>splitString</span><span>($</span><span>string</span><span>,</span><span>$</span><span>maxLength </span><span>=</span><span> PAGEWIDTH</span><span>)</span><span>{</span></div><div><span>$</span><span>result </span><span>=</span><span>[];</span></div><div><span>$</span><span>words </span><span>=</span><span>explode</span><span>(</span><span>'</span><span>'</span><span>,</span><span>$</span><span>string</span><span>);</span></div><div><span>$</span><span>currentLine </span><span>=</span><span>''</span><span>;</span></div><div> </div><div><span>foreach</span><span>($</span><span>words </span><span>as</span><span>$</span><span>word</span><span>)</span><span>{</span></div><div><span>if</span><span>(</span><span>strlen</span><span>($</span><span>currentLine </span><span>.</span><span>$</span><span>word</span><span>)</span><span><span>$</span><span>maxLength</span><span>)</span><span>{</span></span></div><div><span>$</span><span>currentLine </span><span>.=</span><span>($</span><span>currentLine </span><span>?</span><span>'</span><span>'</span><span>:</span><span>''</span><span>)</span><span>.</span><span>$</span><span>word</span><span>;</span></div><div><span>}</span><span>else</span><span>{</span></div><div><span>if</span><span>($</span><span>currentLine</span><span>)</span><span>{</span></div><div><span>$</span><span>result</span><span>[]</span><span>=</span><span>$</span><span>currentLine</span><span>;</span></div><div><span>$</span><span>currentLine </span><span>=</span><span>$</span><span>word</span><span>;</span></div><div><span>}</span><span>else</span><span>{</span></div><div><span>// If a single word is longer than maxLength, split it</span></div><div><span>$</span><span>result</span><span>[]</span><span>=</span><span>substr</span><span>($</span><span>word</span><span>,</span><span>0</span><span>,</span><span>$</span><span>maxLength</span><span>);</span></div><div><span>$</span><span>currentLine </span><span>=</span><span>substr</span><span>($</span><span>word</span><span>,</span><span>$</span><span>maxLength</span><span>);</span></div><div><span>}</span></div><div><span>}</span></div><div><span>}</span></div><div> </div><div><span>if</span><span>($</span><span>currentLine</span><span>)</span><span>{</span></div><div><span>$</span><span>result</span><span>[]</span><span>=</span><span>$</span><span>currentLine</span><span>;</span></div><div><span>}</span></div><div> </div><div><span>return</span><span>$</span><span>result</span><span>;</span></div><div><span>}</span></div>

This function is then used when printing headlines and Reddit posts:

<div><span>foreach</span><span>(</span><span>splitString</span><span>($</span><span>redditPost</span><span>)</span><span>as</span><span>$</span><span>line</span><span>)</span><span>{</span></div><div><span>fwrite</span><span>($</span><span>printer</span><span>,</span><span>$</span><span>line</span><span>)</span><span>.</span><span>"</span><span>n</span><span>"</span><span>;</span></div><div><span>}</span></div>

With all components in place, running the script brings the dot matrix daily news printer to life.

Daily Usage and Project Reflections on Dot Matrix Printing

While manual script execution via php print.php is possible, I opted for automation using a cron job. Set to run every morning around 8 am, the script automatically fetches data and prints my personalized front page. Each morning, I retrieve the freshly printed sheet, a tangible summary of the day’s information to accompany my morning coffee.

Alt text: Example daily news printout from dot matrix printer, showcasing weather, stocks, news headlines, and Reddit posts.

There’s a distinct satisfaction in receiving news in this finite, physical format. It encourages a more deliberate consumption of information, a welcome contrast to the endless scrolling of digital feeds. This project has become a small ritual that helps me start the day with a focused overview, rather than digital overload.

Beyond its practical aspect, this dot matrix printer project has been incredibly enjoyable. Working with physical hardware, especially vintage technology like this printer, is always a rewarding experience. Integrating it with modern technology and finding new uses for older devices reinforces the passion that drew me to programming in the first place.

What are your thoughts on this retro-tech project? If you have similar project ideas or any questions, I’d love to hear them! Connect with me on Twitter to discuss further.

Stay Updated with My Newsletter

Read sample

Subscribe using the form below to receive my newsletter approximately 1-2 times a month. It’s packed with helpful tips, updates on new packages, and interesting articles I’ve discovered related to PHP, JavaScript, Docker, and more.

Comments

No comments yet. Why don’t you start the discussion?

Leave a Reply

Your email address will not be published. Required fields are marked *