Posts

Featured

Haskell gravity simulation

Image
This was my joint-first place winning entry to the annual Haskell coding competition at my university. The briefing was to "make something that looks nice" using Haskell. It's a 2D gravity simulation I wrote using the package Gloss. While I enjoyed working with Haskell, I had some sanity-breaking type errors with most of the calculations as the language is extremely particular about data types. It would have been much more straightforward to code this in Python, but I appreciate the advantages of such a language. Source code on GitHub.

Writing a MicroPython Pi-hole for the ESP8266

Image
Pi-hole is a self-hosted, domain-blocking DNS resolver, which I've been running as my home network's primary DNS server for a while (using Docker). It's excellent software, and can run on very low-power hardware -- even a Raspberry Pi Zero! However, I wanted to take things a step further. I had a few ESP8266-based NodeMCU V3 boards loaded with MicroPython lying around, so I set out to replicate (some) of the Pi-hole featureset on a platform with 128 kilobytes of RAM. NodeMCU V3 board I found this incredibly useful blog post written by James Routley detailing a bit-level breakdown of DNS queries and responses with some sample Python code, which I used to help me write the packet parsing/creation functions. I quickly ran into my first problem -- MicroPython omits a lot of default Python3 modules, like binascii, for the sake of saving space. So, I ended up only importing the modules socket (to send/recieve data), gc (MicroPython garbage collection, so I could manuall...

Making a Docker application

Image
In keeping with the self-hosted/homelab theme of the last post, I decided to try my hand at creating a service to run in a Docker container, namely a local network 'radio station' organiser with a web interface. The program is written in Python (no surprises there) with the network streaming handled by VLC, the downloading of audio files (playlists) carried out by YouTube-DL, Python module Bottle fulfilling webserver duties and SQLite3 storing information about downloaded playlists and created streams. The bash commands that are used to start the VLC streams and to download a YouTube playlist are quite specific. VLC streams are launched in the background, with a never-ending, randomly selected order of file playback to be transcoded to mp3 and streamed via http. nohup cvlc -vvv ~/Music/$playlist --random --loop --sout "#gather,transcode{vcodec=none,acodec=mp3,ab=128,channels=2,samplerate=44100,scodec=none}:http{mux=mp3,dst=:$port/}" --sout-keep & Down...

Mini server update

It's been a while since I first introduced my mini Linux server on this site, and a lot has changed in the meantime. I switched to running my services in Docker containers a few months after the original post, then to LXC (Linux Containers) running on the hypervisor OS Proxmox from summer onwards, and more recently back to Docker with Arch as the host system. I settled on Arch as I wanted a rolling release distribution that could be run headless, had low system requirements and strong community support. For production environments, a distribution with an emphasis on stability would make more sense, like Debian or OpenSUSE, but I've had no issues yet when upgrading packages and I find it more fun to be on the bleeding edge anyway since this server doesn't need to have flawless uptime. Despite Arch's reputation, it was easy to install thanks to the excellent documentation available in the wiki. Once booted, I was impressed with the low memory usage even compared to Ub...

Coding shadows

Image
Here's a small project I wrote in a few hours. It's a Python3 program that calculates and displays shadows based on information read from a JSON file. Firstly, the user is presented with a list of files ending in .json in the current directory. They must enter a valid filename to proceed. The JSON file is parsed. It contains the resolution of the image, the location of the light in the scene and the location and radius of the circles (which cast shadows) in the image. Each light and shape in the scene instantiate a new object from an appropriate class, with the afforementioned data stored in the object's attributes. These objects are appended to an array. The program then iterates through each light in the lights array and each pixel in the x and y axis (from 0 to the total width and height of the image). It determines if the path from the light source to the pixel in question is obstructed by a shape. To accomplish this, the program determines the equation of the s...

The Casio F-91W

Image
A digital classic When I was first starting this blog, I had begun to write a post detailing the history and engineering behind the Vostok Amphibia, a Russian automatic dive watch. Unfortunately, that post didn’t see the light of day as I felt that it didn’t suit the theme of the blog. However, in this post I’ll be returning back to that theme. It seems fitting, then, that the watch in question is one as ubiquitous and iconic as the legendary Casio F-91W. Launched in 1991, its simplicity and durability, coupled with its extremely low price, has allowed it to prevail as a best-seller. I was drawn to its iconic status and low price, and decided to buy my own F-91W recently. The watch’s case is refreshingly slim compared to my Vostok (only 8.5mm), and is very comfortable on the wrist. The three button control is intuitive, with each press reinforced by a short beep of a piezoelectric buzzer. Turning it over reveals a stainless steel caseback held in place by four Phillips he...

Setbacks and problems: Building an autonomous truck from scratch Part 3

Image
It’s been a while since my previous post covering the autonomous truck I have been building, but I’m far from stopping work on it! So far, I have been able to get the GPS and ultrasonic sensor working in Python, on the Pi. Both of those were not easy to get going. The magnetometer is where I now face the greatest issue. The compass I was originally intending to use was the HMC5883l, a small 3 axis magnetometer which connects over I2C. The problems first began to make themselves apparent before I had even plugged it in. The GPS unit I was using (Adafruit Ultimate GPS Featherwing) was supposed to be hooked up the Raspberry Pi via a USB to TTL adapter. However, the adapter would not show up as a recognised device in the Pi, even after I manually loaded the kernel module for the specific chipset inside the adapter into Raspbian’s kernel. So, I decided to simply connect the GPS module via I2C instead, which, after some hours of tinkering, was able to submit its location to the Pi. QMC5...