Gerrit Niezen

Maker of open-source software and hardware.

Feature image

There has been a noticeable trend from people reading blogs towards reading e-mail newsletters instead. I use Feedly to subscribe to blogs[1], but if you don't use a blog reader I guess e-mail makes more sense. Here are a few newsletters that make it into my inbox, even if I prefer blogs.

  • Offscreen Dispatch is a once-a-week newsletter with an assortment of products and articles on design and the web by Kai Brach, maker of Offscreen magazine. Coincidentally Offscreen is also my favourite magazine at the moment.
  • The Prepared is a manufacturing newsletter targeted at engineers and entrepreneurs by Spencer Wright, who also hosts The Prepared podcast.
  • Sunday Dispatches is a little bit of everything by Paul Jarvis. He usually writes about freelancing and small businesses.

  1. Hint: You can subscribe to this blog by clicking the Subscribe link at the top of the page. ↩︎

#Reading

Comment on this post

I discovered a customizable design for a door stop on Thingiverse, where you can resize it to fit the door holes in your house. I measured the holes, modified and 3D-printed the design, and it turned out to work much better than expected.

I then needed a way to keep our wardrobe door closed. I couldn't find anything on Amazon or any existing designs on Thingiverse that would work. So I started creating some baby-proofing designs of my own.

I noticed that there is a small gap at the top of the wardrobe door, with a knob just behind it. So I thought “why not make something that clips to that knob that prevents the door from opening”? Ladies and gentlemen, I present to you the wardrobe door holder :

wardrobeDoorHolder

It should work with any IKEA PAX hinged wardrobe doors. I posted the wardrobe door holder on Thingiverse if you just want to download the STL file to print it yourself. Here is the OpenSCAD code to make or modify your own wardrobe door holder:

$fn=50;

difference () {
  cylinder(5, d=16);
  translate([0, 0, -1]) {
      cylinder(7, d=11.9);
  }
}

translate([-4,6,3]) {
  cube([51,10,2]);
  translate([0,0,-3])
      cube([7,10,3]);
  translate([41,0,-10])
      cube([10,10,10]);
}

I also made a simple hook that clips over two IKEA PAX door handles:

handleHolder

And here is the OpenSCAD code, which is easy enough to modify by changing the variables for width, thickness and height:

width = 82;
thickness = 5;
height = 25;

cube([width+thickness,thickness*2,thickness]);
cube([thickness,thickness*2,height]);

translate([width+thickness,0,0]) {
  cube([thickness,thickness*2,height]);
}

Comment on this post

Feature image

I've been looking for a way to very easily write and publish posts. I've tried static page generators like Hugo and and Jekyll on GitHub Pages in the past, but there are just enough steps to create too much friction.

First you have to write your markdown files in a text editor. Then you have to compile it and publish it using a computer. I was looking for a quick way to write posts, even on my phone or iPad (with a Bluetooth keyboard). SimpleNote came close to what I needed, except that each post exists completely separate to other posts.

Enter Ghost. I spun up a Digital Ocean instance and followed the tutorial for setting up the one-click application. Easy peasy.

Now I am self-hosting my own content and I can type away on any device that can load Ghost's web-based Markdown editor. Adding header images is super easy thanks to built-in Unsplash integration, and then publishing a post is one click away.

In future I hope that decentralized solutions like Beaker browser and the Dat project will make it much easier to publish blogs in a decentralized fashion, but until then running my own Ghost instance seems to make the most sense.

Comment on this post

Feature image

I've been adding updates to the wireless temperature sensor code I posted last week, mainly adding timestamps to the sensor readings.

canvas

I first tried using an array of objects of the form { time: <timestamp>, temp: <temperature>}, but for some reason the ESP8266 would reboot every couple of hours. My guess is that it was some kind of memory or buffer overrun issue, so I used two separate array (one for time, one for temperature) instead.

Getting accurate time from microcontrollers is notoriously difficult. At Tidepool we have an entire guide dedicated to working with timestamps coming from diabetes devices, and we use a pretty complex algorithm to convert local timestamps to UTC time.

Any microcontroller timer is susceptible to clock drift, so it was nice to discover that Espruino has a feature where it auto-updates the time on the device every time you push new code to it. While this is not necessarily going to work that well in real-world environments where you're not frequently pushing code changes, it works great for my prototype where I'm pushing new updates all the time.

Currently the prototype is sitting in our nursery, measuring the room temperature overnight to see if the baby is getting too hot, as Swansea is currently experiencing a very unusual spell of warm weather. I still can't get over how cool it is to program the ESP8266 over WiFi in another room two floors up.

So, how did I go about getting those timestamps? The first step is to set your timezone on the device, offset from UTC, so for the UK it would be 1 for UTC+1:

E.setTimeZone(1); // UTC + 1

Also remember to check the box next to “When sending code, set Espruino's clock to the current time” in the Espruino Web IDE. Getting the current time is then just regular JavaScript code:

var dt = new Date(Date.now());
var time = dt.getHours() + ':' + dt.getMinutes().toString().padStart(2,'0');
console.log(time, temp);

Note that on the ESP8266 I had to use the padStart polyfill as Espruino does not yet support ES8/ECMAScript 2017. Here is the entire script, taking sensor readings every 10 minutes and printing the timestamp and value every 5 readings:

var wifi = require('Wifi');
var http = require('http');

var led = Pin(NodeMCU.D4);
var toggle=1;
var ow = new OneWire(NodeMCU.D3);
var sensor = require("DS18B20").connect(ow);
var history = new Float32Array(60);
var timeArr = new Array(60);

function updateLed(){
  digitalWrite(led, toggle);
  toggle=!toggle;
}

// https://github.com/uxitten/polyfill/blob/master/string.polyfill.js
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/padStart
if (!String.prototype.padStart) {
    String.prototype.padStart = function padStart(targetLength,padString) {
        targetLength = targetLength>>0; //truncate if number or convert non-number to 0;
        padString = String((typeof padString !== 'undefined' ? padString : ' '));
        if (this.length > targetLength) {
            return String(this);
        }
        else {
            targetLength = targetLength-this.length;
            if (targetLength > padString.length) {
                padString += padString.repeat(targetLength/padString.length); //append to original to ensure we are longer than needed
            }
            return padString.slice(0,targetLength) + String(this);
        }
    };
}


setInterval(function() {
  updateLed();

  var temp = sensor.getTemp();
  var dt = new Date(Date.now());
  var time = dt.getHours() + ':' + dt.getMinutes().toString().padStart(2,'0');
  console.log(time, temp);
  // move history back
  for (var i = 1; i < history.length; i++) {
    history[i-1] = history[i];
    timeArr[i-1] = timeArr[i];
  }
  // insert new history at end
  history[history.length-1] = temp;
  timeArr[timeArr.length-1] = time;
}, 600000); // every 10 minutes

function onPageRequest(req, res) {
  res.writeHead(200, {'Content-Type': 'text/html'});
  res.write('<html><head><meta charset="utf-8"/><meta http-equiv="refresh" content="600"></head>'+
            '<body><canvas id="canvas" width="400" height="200" style="border:1px solid #888;"></canvas><script>');
  res.write('var d='+JSON.stringify(history)+';'+
            'var t='+JSON.stringify(timeArr)+';'+
'var c=document.getElementById("canvas").getContext("2d");'+
'c.moveTo(0,100 - (d[0]-d[d.length-1])*10);'+
'for (i in d) {'+
'var x = i*400/(d.length-1); var y = 100 - (d[i]-d[d.length-1])*10;'+
'c.lineTo(x, y);'+
'if (i % 5 === 0) {'+
'c.fillText(Number.parseFloat(d[i]).toFixed(1),x,y - 5);'+
'c.fillText(t[i],x,y + 20);}}'+
'c.stroke()'+
'</script>');
  res.end('</body></html>');
}

function onInit() {
  wifi.restore();
  http.createServer(onPageRequest).listen(80);
  console.log("Server created at " + wifi.getIP().ip);
  E.setTimeZone(1); // UTC+1, remember to select "set current time" in IDE
}

onInit();

Update: Using NTP

Justin from Swansea Hackspace pointed out that I could use NTP to get the time:

I assume this is an internet enable device, so why not just use NTP? For arduino based code the standard Time library has an example of an NTP SyncProvider callback

— Justin Mitchell (@popemadmitch) June 11, 2018

I looked it up in the Espruino docs, and low and behold, it's as easy as wifi.setSNTP('uk.pool.ntp.org', 1); (for UTC+1).

#Electronics

Comment on this post

Feature image

While drinking my Sunday morning coffee I read an article in the Guardian with the title Underpaid and exhausted: the human cost of your Kindle.

One thing that struck me is that the while the richest man in the world, Jeff Bezos, is worth an estimated £102 billion, there are people making Amazon products for £1.69 an hour. Why are poor people being exploited both directly (workers in Amazon warehouses and delivery drivers) and indirectly (people working for companies like Foxconn)? Is it fair to blame Jeff Bezos? Or maybe it is really just a symptom of late stage capitalism.

It reminds me of a paragraph in Jay Rayner's book “A Greedy Man in a Hungry World” that has been bothering me for a while, because I disagree with it but couldn't exactly say why:

China does one thing really well: making stuff. America does a different thing really well: growing corn and soya beans. So they trade. This is called utilizing comparative advantage.

If China's comparative advantage is just being able to pay people peanuts and companies getting away with not following labour laws, does it really make them better at making stuff?

What would it look like if e-book readers were made in an open source, decentralized fashion instead of in one factory in China? What would it look like if voice assistants were made in the same town were they are being used, sold directly instead of paying the Amazon tax?

Comment on this post

Feature image

Now that I've made it a week with blogging every day, I should probably explain why. I was re-reading a post by Austin Kleon on daily blogging. There's this one bit I found quite inspiring:

I had forgotten how wonderful blogging is as a mode of thinking. Blogging is, for me, more about discovering what I have to say, and tweeting more about having a thought, then saying it the right way. It’s also great to be able to go as long or as short as you want to go.

Writing more should help me communicate with others more effectively. Most of my communication is done via chat as I work remotely, and being able to write clear and unambiguously will be very helpful.

Austin's blog post also lead me to this nugget that summarizes Seth Godin's thoughts on daily blogging. He should know, he's been blogging daily since 2002:

Everyone should write a blog, every day, even if no one reads it. There’s countless reasons why it’s a good idea and I can’t think of one reason it’s a bad idea.

I don't need anyone's permission. I don't need to go out and promote it. I don't use any analytics. I don't have comments. It's just: this is what I noticed today and I thought I'd share it with you.

Let's see how long I can keep this going.

Comment on this post

Feature image

Have you seen the Remote Only manifesto written by Gitlab that has been doing the rounds on the internets lately? This is basically how we work at Tidepool.

We currently have a team of 14 people based in the US, Canada, Australia and the UK. We used to have a main office in San Francisco, but now that our team is not mainly concentrated in the Bay Area anymore, we are now truly remote only.

Slack works well for us in terms of asynchronous communication. When I start work in the morning, I can quickly reply to questions people in other timezones left me overnight. For group video calls we still use the old Google Hangouts, as the new Google Hangouts Meet is very much a downgrade at the moment. For one-on-one meetings Slack's video call feature works quite well – I especially like the feature to draw on the other person's screen during screen sharing.

We use Trello for tracking tasks and prioritizing work, falling back to Google Docs if something needs more than a card to describe it. GitHub has been invaluable for remote collaboration, which is why I consider their acquisition by Microsoft earlier this week to be a cause for concern.

Having a fast, reliable internet connection is essential for remote-only. A good microphone helps too. And having a separate room that you use for your office helps to separate work and family life.

We try to get together at least twice a year in the same location (usually Santa Cruz), as it's true that remote work is not a substitute for human interaction. These offsites are usually reserved for prioritising tasks and overall company strategy. I also try to work from a co-working space in town at least once a week, to stave off loneliness and interact with people working on other software-related projects.

From my experience working remote for almost three years now, the benefits outweigh the disadvantages by far. If you have the opportunity to work for a remote-only company, or if you can transition your existing organisation to a remote-only one, I would highly recommend it.

#Tidepool

Comment on this post

Feature image

We had an allotment[1] for a couple of years here in Swansea. It took us a year and a half[2] to get hold of one, as the waiting lists tend to be very long everywhere in the UK. We enjoyed the grow-your-own part of it very much, but it was just too far away to make economic or environmental sense.

It usually took anywhere from 20 to 40 minutes to get there based on the traffic. It's partly this quote from Jay Rayner's “A Greedy Man in a Hungry World” that made me think twice:

if you are renting an allotment a mile or two from your house, which you have to drive to, so as to carry tools there and produce back, you will quickly bestow upon your food a carbon footprint of the size that would embarrass a multinational oil company.

I disagree with a lot of what he says in that book, but he's got a point about the carbon footprint of an allotment that's not within walking distance. We gave up the allotment at the beginning of this year.

Given the super short summer and lots of rain here in Wales, you have a pretty limited growing season if you're not using a greenhouse. It's also easy for pests to quickly wipe out an entire crop. We had lovely tomato plants that were destroyed in less than a week by blight.

I was also a bit surprised by how expensive it can be, for example to provide nutrients like compost if you don't already have your own compost heap. And I found weeding to be very time-consuming, but my wife tends to enjoy it. Overall what I found most disappointing was the yield when conditions weren't perfect.

But what if:

  • we can grow all year round
  • we can eliminate weeds and pests
  • minimize the amount of nutrients required
  • do it anywhere, even on an airship or a boat
  • maximize yield

That's the promise of hydroponics, which is why I want to give it a try. I found a tutorial on Instructables that I'm going to give a go, and will post the progress here when I get started.


  1. also known as a community garden in the US ↩︎

  2. registered with the city council in November 2014, got the allotment in May 2016 ↩︎

#Hydroponics

Comment on this post

Feature image

I use Goodreads to keep track of the books I've read. You may notice on my Goodreads profile that I joined their 2018 Reading Challenge. This is the second year that I've done it, as it gives that extra bit of motivation to continue my reading habit:

Just by building a tiny habit of reading at least 30 minutes per day I have already read 21 books this year ✊ https://t.co/Fuw2wc56MZ

— Gerrit Niezen (@gendor) October 5, 2017

I prefer to get my books from the library, but sometimes being able to immediately start reading a book I just found is great on Kindle. I also use the highlight function on Kindle, and receive a daily digest of recent highlights in my inbox, courtesy of Readwise.io. And of course, when I finish a book on Kindle, it automatically gets marked as read on Goodreads! That said, nothing beats holding a physical book in your hands.

#Reading

Comment on this post

Feature image

During my afternoon run I was listening to The Amp Hour podcast interviewing Jeri Ellsworth who co-founded CastAR, and thinking to myself that doing a VC-funded startup if you're an engineer sounds like a really bad idea.

Jeri and her co-founder Rick Johnson were working on Augmented Reality (AR) glasses at Valve, and started CastAR to commercialise the technology on their own after Valve shut down the project. They did a Kickstarter, but returned all the money to their backers when they raised their first round of VC funding. CastAR shut down in 2017 after they ran out of money, but to hear the reasons why from Jeri herself was illuminating.

Basically, as soon as her investors decided to scale and brought in a new CEO that was aligned with investor interests, she lost control of the company. The number of middle-management employees ballooned, they spent hundreds of thousands of dollars just on renaming the product, and the new upper management were taking multiples of her founder's salary in compensation.

That made me think that an open-source hardware project like Gordon Willam's Espruino is really at the other end of the scale. Each new product is funded through Kickstarter, and then sold through his e-shop and other distribution partners. I noticed that he is also getting donations through Patreon, as a lot of people (me included, see yesterday's post) use the Espruino software with ESP8266 and this provides another channel to fund his work.

While this second route seems hard and doesn't promise massive returns, I think it's less risky than the VC-funded route and a lot more fulfilling. I realise Espruino and CastAR are completely different projects, but I do wonder what a successfully bootstrapped open-source hardware project making consumer hardware would look like.

#Bootstrapping

Comment on this post

Enter your email to subscribe to updates.