EtherCrab 0.5: Not Much In A Name
I've just released EtherCrab 0.5.0 (lib.rs), the pure Rust EtherCAT MainDevice. This is a smaller release than usual, with added support for FreeBSD/NetBSD and a bunch of renamed items in the public API. The full changelog can be found here.
Continue ReadingRust: Running a TLC5940 with an ESP32 using the RMT peripheral
The TLC5940 is a "16-channel LED driver w/EEprom dot correction & grayscale PWM control" IC, used for driving up to 16 constant current outputs (typically LEDs) using a number of control lines. It's more complex to drive than the TLC5947 which uses a simple I2C interface, but leaves more control to the application developer by letting them set the LED PWM frequency, among other things.
The TLC5940 uses SPI to transfer brightness data, but also requires an external PWM clock, as well as a periodic pulse on the BLANK pin to ensure the outputs remain enabled. This is annoying to do in software, but by abusing the RMT peripheral in an ESP32, we can let the microcontroller hardware do all of the heavy lifting for us.
Continue ReadingEtherCrab 0.4: Distributed Clocks, io_uring
, Derives, Oh My
EtherCrab 0.4.0
(lib.rs), the pure Rust EtherCAT MainDevice is out! I've added a
lot of features and fixes to this release, including Distributed Clocks support, an io_uring
-based
network driver for better performance, and a brand new set of derive-able traits to make getting
data into and out of your EtherCAT network easier than ever! The full changelog including breaking
changes can be found here, but
for the rest of this article let's dig a little deeper into some of the headline features.
Controlling an Electriq iQool AC with ESPHome and Home Assistant
I recently got a pretty neat all-in-one air conditioner to heat my frigid Scottish garage in the
winter. CNC machines don't like the cold, and neither do I! My unit is an "electriQ iQool 12000 BTU
Wall Mounted Air Conditioner with Heating Function", product code IQOOL-SMART15HP
. I quite like
it, but when I got it I really wanted to be able to shout at Siri to turn the garage heat on so
it'd be warmer by the time I went out. And I succeeded in this mission! By flashing ESPHome to the
integrated Tuya TYJW2S-5V-YA module, I can now control this AC perfectly from Home Assistant and, by
extension, Apple's Home app.
Building a LinuxCNC 2.9 simulator on Linux Mint 21.3
An update on my previous guide for LM 19.3 on how to set up a LinuxCNC simulator on Linux Mint 21.3 Virginia. The LinuxCNC simulator is useful for testing/debugging drivers, gcode parsing and other non-realtime features without having to crawl around under your machine's actual control.
Continue ReadingA study of Rust micro-optimisations
In working on ethercrab I found myself down the rabbit hole of trying to reduce binary size, in this case for the thumbv7m-none-eabi architecture used in embedded. This post is a collection of examples of attempted code size reductions by refactoring sometimes the most tiny of fu…
Continue ReadingAnnouncing EtherCrab: The 100% Rust EtherCAT controller
The EtherCrab story started with my dream of writing a motion controller in Rust to provide a modern
alternative to the venerable LinuxCNC project. But motion
controllers are hard, even with the right books, so I did what any good programmer would do:
procrastinate by implementing an entire industrial fieldbus protocol instead! Say hello to
EtherCrab - a pure Rust EtherCAT controller that supports
Linux, macOS, Windows and even no_std
.
Heads up! EtherCrab 0.4.0 was released in March 2024 with some breaking changes. Why not head over to the announcement post to see what's new?
Continue ReadingReducing fan noise on the Morefine S500+
I got a Ryzen 5625U Morefine S500+ Mini PC from Aliexpress for EtherCrab development recently. It's a lovely little machine for the price and about 7x faster than my previous dev box. There's one very annoying issue though: the noisy little fan installed on the CPU heatsink. Let's fix that.
Continue ReadingA const builder pattern in Rust
During the creation of EtherCrab, a pure-Rust EtherCAT master, one of the core structs in the crate started growing quite a few const generic parameters. Here's a reduced example of what I'm talking about:
Continue Reading
Weird high frequency behaviour on your STM32 pins? Change the mode!
A quick PSA in case you're at a loss as to why you're seeing strange behaviour from your STM32 MCU pins when running higher frequencies through them like I was.
After successfully getting MCO (Microcontroller Clock Output) working on the only STM32L031 I could find in the universe, I was seeing some strange behaviour when attempting to push the output frequency above 2MHz.
Continue ReadingClockwise Triangles Performance: Addendum
A quick update on my previous article.
Nicholas Wilcox (@redbluemonkey) on Twitter made a very good point:
Continue ReadingOptimising Rust: Clockwise Triangles
Welcome to another pointless tangent into the exciting world of line joints in
embedded-graphics! embedded-graphics
is an integer
only, iterator based no-std graphics library for environments with low resource availability. This
time, we'll be looking at some not-so-great optimisations made to a point sorting function.
Update: A kind Twitter user pointed out a more optimised solution for triangles which you can find here.
Continue ReadingInteger Graphics: Line Intersection
Graphics can be a tricky topic, particularly when attempting to find anything on the internet these
days that provides solution in terms of integer-only maths.
embedded-graphics is a (mostly) integer-only library,
so in pursuing a solution to good line joints for the Polyline
and Polygon
shape
implementations, a bit of interweb detective work was required.
Setting up an MPG Jog Pendant in LinuxCNC
CNC jog pendants are super useful devices for quick setup and configuration of CNC machines. A quick search for CNC jog pendant on AliExpress turns up a bunch of results. For this post, I'll cover connecting a wired jog pendant with ESTOP to a Mesa 5i25 FPGA card to control a 3 axis CNC mill.
Continue ReadingAnnouncing linuxcnc-hal: write LinuxCNC HAL components in Rust
I'd like to announce two crates I've been working to integrate Rust components into LinuxCNC. You can find them at linuxcnc-hal (high-level interface) and linuxcnc-hal-sys (low-level interface). The rest of this post is a getting started tutorial, so follow along if you have a cool idea for a custom bit of CNC hardware and an itch to write the interface in Rust!
Continue ReadingBuilding a LinuxCNC 2.8 simulator on Linux Mint 19.3
This guide has been upated for Linux Mint 21.3. Check it out here.
A quick guide on how to set up a LinuxCNC simulator on Linux Mint. The LinuxCNC simulator is useful for testing/debugging drivers, gcode parsing and other non-realtime features without having to crawl around under your machine's actual control.
Continue ReadingEmbedded graphics 0.5.0
Version 0.5.0 is released! This is a pretty big one, focussed around ergonomics. There are new
macros to make drawing and positioning primitives and text much less noisy, as well as changes to
the Drawing
trait to remove the explicit .into_iter()
call when passing objects to it.
Persistent state with Tower Web
We're building a new product at work, for which we've decided to use Rust and tower-web for the backend. There don't seem to be any Tower examples using state in request handlers, so this is a quick copypasta showing how to add Diesel so request handlers can do database operations.
Continue ReadingXML sitemaps in React with Typescript
I maintain the Repositive website which uses React for the frontend and a server that supports server side rendering for the speed and SEO benefits of SSR. I'm currently in the process of porting it over to Typescript which is kickass, but the type checker kept borking on the XML tags used in the sitemap component. What follows is a quick "note to self" on how to fix that error. There might be much better solutions out there, but this is the one that worked for me.
Continue ReadingEmbedded Graphics 0.4.7 and TinyBMP 0.1.0
Embedded graphics 0.4.7 has been released, along with a new sister crate, tinybmp! TinyBMP aims to parse BMP-format image data using no dynamic allocations. It targets embedded environments but can be used in any place a small BMP parser is required. Thanks to TinyBMP, Embedded Graphics now supports loading this simple image format. The header photo was made using Embedded Graphics and the SSD1331 driver in pure Rust. In this post, I'll talk through how the BMP file is parsed in no_std environments with nom and how to get BMP images working with embedded_graphics.
Continue ReadingCross compiling Rust from Linux to macOS
I've recently been working on a Rust project at work which requires compiling for Linux (GNU), Linux (musl - for Alpine Linux) and macOS. I use Linux Mint nearly all the time, so building for macOS targets has required asking very nicely to borrow a spare Macbook Air. This is naturally a bit crap, so I set out to find a Linux-only solution to cross compile for macOS using osxcross. A weekend of pain later, and I have the following post. Hopefully it spares you a weekend of your own pain.
Continue ReadingAnnouncing the SH1106 OLED display driver
Similar to the SSD1306 covered previously, the
SH1106 OLED display is a small, self contained module perfect for hacking into a project or
prototype. It's available on AliExpress and eBay for peanuts, but is lacking a Rust driver. Until
now with the sh1106
crate!
Optimising out calls to new()
Rust (and LLVM) are really good at optimising things.
I have a struct, TrajectoryStep
, that I pass to some methods in my program. I don't want to use
positional arguments as it's impossible to tell what some_func(f32, f32, f32)
might actually
require. It looks like this:
Default arguments for cooler testing
In my other post about
creating properly typechecked helper functions in Typescript, I missed something out from the
examples that's present in the real code: default parameters! There's a function, createEvent
,
that returns an object with a dynamically generated UUID value in it. It also includes the current
timestamp. This is great from the programmer's point of view as there's no need to wire up these
values manually, but it sucks for unit tests because the values always change! The solution is to
use
default parameters
to keep the ergonomics of a clean public API, but still support unit testing and special cases
gracefully.
Typechecking builder functions in Typescript
I've been working on toasting a lot of our tech debt at Repositive
recently. We use an event driven microservice architecture which has various benefits, but some
drawbacks concerning what data is sent where due in part to the liberal use of any
in our
Typescript codebases. During my refactoring rampage, I encountered some places where event objects
were missing fields or otherwise weren't being generated properly. To this end, I set out to create
a type-checked solution to this problem.
Office 365 in Linux Mint 19: Calendar, Email, Notifications
Announcing the SSD1306 OLED display driver
As part of the weekly driver initiative, myself (@jamwaffles), @therealprof and @scowcron have been working on a Rust driver for the common as mud SSD1306-based OLED display modules. This little chip is found in the majority of inexpensive OLED display modules found on Ebay and AliExpress. It supports either an SPI or I2C interface, both of which the driver supports.
Continue ReadingSetting the GDB safe-path cross platform
I've been developing an embedded Rust app (yay!) on Windows (blegh) recently. The Rust team have put
incredible effort into making Rust itself work great in Windows environments, but the tooling around
it can be difficult to get working correctly. My current problem was making GDB load a .gdbinit
file from the current projecting when doing xargo run
. Here's how I fixed it in .cargo/config
:
Elm: counting groups of items in a list
So. Elm. It's been an interesting experience for me, coming from a procedural language (JS) background. The learning curve is steep, but the functional nature of Elm, along with its compile time type safety really pays off. One of the (few!) problems I've found as a newcomer however, is that the documentation can be really frustrating sometimes. In this post, I hope to remedy that slightly by providing a newcomer's perspective on a little bit of data processing in Elm.
Continue ReadingCloning private Github repos in Rust
Cloning a private Github repo using SSH auth in Rust has proved to be a pretty gnarly problem (for my anyway), so I thought I'd share this quick tutorial to help anyone else out that might be struggling with the same issue. I'm using git2-rs which has good interface documentation, but very few pieces of example code, so I set out to fix that somewhat with this post.
Continue ReadingLogging analytics events in a testable way with React and Redux
One of my main responsibilites at TotallyMoney was to take care of the in-house analytics/event logging framework. Like lots of companies, understanding what users do and how they interact with a product is to get good insight on. In this regard, people reinvent the logging wheel with various krimskrams attached, me being no exception. What I want to show in this post is how to integrate an event logging framework into a React/Redux application in a way that's scaleable and testable. Unit testable logging is important when the rest of the business relies heavily on the events and the data in them like many companies do.
Continue ReadingScraping without a scraper
In between watching the rain and emptying all the shmoo out of my air compressor (long overdue), I decided to try my hand at some impromptu scraping this weekend. Matters were complicated somewhat due to me not owning a scraping tool, but I worked with what I have to make what I think are some satisfctory results. This post will be a short log of what went down and will hopefully demonstrate that one can achieve reasonably good (i.e. flat) results without having a real scraper.
Continue ReadingA white (and red and green) Christmas
Here's a quick one; I'm making a Christmas display out of a bunch of serially controllable APA106
RGB LEDs, but how do I turn a value of 0 – 255
into a glorious RGW (Red Green White) struct with
the correct colour, and the correct wrapping rules?
Parsing Logentries output safely using Rust
I'm fascinated by Rust for it's safety and speed, but also because it's simple to write low level code in what feels like a high level language. To that end, I've been working on a small Rust project at TotallyMoney.com (where I work) for the last week or so to see if it's viable for production use. It's a simple service that polls a Logentries endpoint for JSON, parses it and saves some values in a Postgres database. It's not a very complicated task, but I saw this as a good opportunity to try Rust in a production-ish role.
Continue ReadingG&G P90 hicap mag feeding fix(ish)
Disclaimer: This is an article for an airsoft gun only. None of this pertains to real firearms.
I have a G&G P90 (in tan, in case you were wondering) and like many others suffer from the hicap mags failing to feed. Half filling them kind of works, but the feed mechanism always seems to jam. I've got a half solution here in this article. It doesn't completely fix the problem, but my hicaps feed a lot more reliably now, particularly in semi-auto, than they did before.
Continue ReadingFaster, smoother, better, stronger (at high speeds): bipolar parallel stepper wiring
Quick tip: if you're looking for higher maximum speeds with your bipolar stepper motors, try wiring the windings in parallel instead of series. According to a short National Instruments article, it can increase torque at higher speeds, reducing the chance that the motor will stall during fast rapids.
Continue ReadingSpindle speed control using LinuxCNC 2.7 with a Huanyang inverter
Huanyang branded VFD drives are ubiquitous on eBay and other sites like AliExpress. I bought one
some time ago with a 1.5KW spindle and have been controlling the speed manually with the difficult
to use control panel on the front. It is, however, possible to control the VFD from within LinuxCNC
using the M3
and M5
commands
(I haven't been able to get M4
, reverse rotation, working yet). What's also neat is we can get the
machine to wait for the spindle to come up to speed before moving to the next line of GCode.