Compare commits

...

150 commits
v1.0 ... master

Author SHA1 Message Date
Michael Hope 9c4f388977 wiki: post about the Ampler protocol
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-12 15:47:54 +02:00
Michael Hope 45130cdc0b wiki: add discharge measurements
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-11 12:41:56 +02:00
Michael Hope 5aaaf3c9de wiki: detail the C6 setup and the use of deep sleep
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-11 12:28:11 +02:00
Michael Hope bf96817f9c wiki: lifire: post about the power budget
All checks were successful
continuous-integration/drone/push Build is passing
2024-05-11 11:58:50 +02:00
Michael Hope 78912b2c36 Add content/post/2024/esp32_sensor.md
All checks were successful
continuous-integration/drone Build is passing
2024-04-20 15:09:42 +02:00
Michael Hope d07cfb4f21 Add content/post/2024/tars.md 2024-03-24 17:49:30 +01:00
Michael Hope 4433f52bad wiki: try using the internal IP address
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-03 16:47:15 +01:00
Michael Hope 4a5f56890b wiki: try using the internal name
Some checks failed
continuous-integration/drone/push Build is failing
2024-03-03 16:45:06 +01:00
Michael Hope 6a779606b0 wiki: attempt to debug a push issue
Some checks failed
continuous-integration/drone/push Build is failing
2024-03-03 16:39:20 +01:00
Michael Hope d552722fb6 wiki: push the wiki to gw.juju.nz
Some checks failed
continuous-integration/drone/push Build is failing
2024-03-03 16:23:02 +01:00
Michael Hope 12a6f475be wiki: push the wiki to gw
Some checks failed
continuous-integration/drone/push Build is failing
2024-03-03 16:21:30 +01:00
Michael Hope 591c63bfd1 Add content/post/2024/wordclock.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-03-03 16:10:24 +01:00
Michael Hope b4fe8c050a wiki: move the old accidentally nested post directory
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-25 13:28:42 +01:00
Michael Hope 4990889060 Update content/post/2024/openwrt.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-01 20:37:39 +01:00
Michael Hope d4f49408c5 Update content/post/2024/openwrt.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-02-01 20:09:35 +01:00
Michael Hope 19310f2265 Add content/post/2024/openwrt.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-31 19:40:38 +01:00
Michael Hope 222b4e9e54 Add content/post/2024/orc8-1.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-21 20:26:23 +01:00
Michael Hope bcb94af6a0 Add content/post/2024/fpgablink.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-13 13:04:03 +01:00
Michael Hope b408ed94f3 Update content/post/2024/wireguard.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-02 17:12:55 +01:00
Michael Hope 952a9ffd26 Add content/post/2024/wireguard.md
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-02 17:10:20 +01:00
Michael Hope d59498d945 Merge branch 'master' of ssh://juju.nz:3022/michaelh/wiki
All checks were successful
continuous-integration/drone/push Build is passing
2024-01-01 14:59:45 +01:00
Michael Hope 454bbe5bae wiki: post about starting to learn about FPGAs 2024-01-01 14:59:21 +01:00
Michael Hope d1ffd3575a Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:48:50 +01:00
Michael Hope df14cecbd1 Merge the submodules and build steps for speed
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:46:43 +01:00
Michael Hope 68fc2b6b32 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:44:48 +01:00
Michael Hope 8f72610b7f Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:41:14 +01:00
Michael Hope ed3f58a260 Merge branch 'master' of ssh://juju.nz:3022/michaelh/wiki
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:38:35 +01:00
Michael Hope 39894e508a Put script in a block to fix the parsing rendering 2023-12-27 19:37:36 +01:00
Michael Hope e44dd61d08 Add the missing git cli
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-27 19:34:38 +01:00
Michael Hope 34d8a8bc7e Try pulling hugo from github
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-27 19:33:07 +01:00
Michael Hope de54364a0a Try building with bookworm
Some checks failed
continuous-integration/drone/push Build is failing
2023-12-27 19:12:06 +01:00
Michael Hope c193e721c4 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:08:32 +01:00
Michael Hope d2521252c6 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 19:04:22 +01:00
Michael Hope 1ea89b7222 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
2023-12-27 18:59:44 +01:00
Michael Hope 7917ffa204 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
2023-12-27 18:55:49 +01:00
Michael Hope d1a316b7ce Update content/post/2023/online.md
All checks were successful
continuous-integration/drone Build is passing
continuous-integration/drone/push Build is passing
2023-12-27 18:45:39 +01:00
Michael Hope 9d9ebcc393 Update content/post/2023/online.md
All checks were successful
continuous-integration/drone Build is passing
2023-12-27 18:40:22 +01:00
Michael Hope 7530bfd328 Add content/post/2023/online.md
All checks were successful
continuous-integration/drone Build is passing
2023-12-27 17:54:00 +01:00
Michael Hope 047b6b273e wiki: allow pandoc to run 2023-07-04 21:59:14 +02:00
Michael Hope 3b2c6e69b7 wiki: make the build quieter
All checks were successful
continuous-integration/drone/push Build is passing
continuous-integration/drone Build is passing
2023-06-04 20:27:57 +02:00
Michael Hope f302914622 wiki: switch to bullseye for the right hugo version
Some checks failed
continuous-integration/drone/push Build is failing
2023-06-04 20:21:10 +02:00
Michael Hope 670b5874e1 wiki: add the missing charger images
Some checks failed
continuous-integration/drone/push Build is failing
2023-06-04 20:18:05 +02:00
Michael Hope dba9fd8d36 wiki: try printing the hugo versions 2023-06-04 20:17:52 +02:00
Michael Hope aeedf32da3 wiki: switch to bullseye to get the right version of hugo
Some checks failed
continuous-integration/drone/push Build is failing
2023-06-04 20:11:09 +02:00
Michael Hope 509f4935ef wiki: stop using git-lfs
Some checks failed
continuous-integration/drone/push Build is failing
2023-06-04 20:06:43 +02:00
Michael Hope 1100eda1bc wiki: change the builder to use amd64
Some checks failed
continuous-integration/drone/push Build is failing
2023-06-04 20:04:10 +02:00
Michael Hope 8cf30aae75 wiki: post about the charger
Some checks are pending
continuous-integration/drone Build is pending
2023-06-04 18:08:08 +02:00
Michael Hope f87373c75f wiki: start posting about the CH32V003 2023-01-29 11:50:09 +01:00
Michael Hope a085a45e3d Post about GitJournal
All checks were successful
continuous-integration/drone/push Build is passing
2022-06-26 12:28:29 +02:00
Michael Hope b81763a6fa wiki: try adding git-lfs to the build #4
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-16 18:27:38 +01:00
Michael Hope 49795bfbe2 wiki: try adding git-lfs to the build #3
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-16 18:25:01 +01:00
Michael Hope c6c0c40940 wiki: try adding git-lfs to the build #2
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-16 18:23:57 +01:00
Michael Hope dc2e675094 wiki: try adding git-lfs to the build
Some checks failed
continuous-integration/drone/push Build is failing
2022-01-16 18:20:38 +01:00
Michael Hope 8e3599db0e wiki: video about nppilot doing laps
All checks were successful
continuous-integration/drone/push Build is passing
2022-01-16 18:11:16 +01:00
Michael Hope e0a7ea6a23 wiki: update my username
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-30 20:23:12 +01:00
Michael Hope 3f5103d0fe wiki: post about the ABRP integration
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-30 20:16:31 +01:00
Michael Hope 9640b53abd wiki: fix the image on the SolaX post
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-05 18:01:41 +01:00
Michael Hope bd22e5ccca wiki: reformat the SolaX post
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-05 17:58:23 +01:00
Michael Hope 471ef862a5 wiki: post about SolaX MQTT
All checks were successful
continuous-integration/drone/push Build is passing
2021-12-05 17:53:02 +01:00
Michael Hope 4c46c78a31 wiki: post about debugging the Duckiebot
All checks were successful
continuous-integration/drone/push Build is passing
2021-09-26 11:53:30 +02:00
Michael Hope 5a92418b26 wiki: posted about the zx0
All checks were successful
continuous-integration/drone/push Build is passing
2021-06-20 13:14:01 +02:00
Michael Hope 5e10bd18bb wiki: post about the TV load
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-26 16:01:46 +01:00
Michael Hope dbd5783e1e wiki: post about the AT-09
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-14 16:58:34 +01:00
Michael Hope 7add1bd406 wiki: add a submodule init
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-08 09:02:42 +01:00
Michael Hope d0867bf0ab wiki: add a submodule init
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-08 08:58:58 +01:00
Michael Hope 5991960f54 wiki: add a submodule init
Some checks failed
continuous-integration/drone/push Build is failing
2021-03-08 08:53:09 +01:00
Michael Hope 7ce4493514 wiki: also pull submodules and remove public/
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-08 08:44:36 +01:00
Michael Hope fc3442ac30 wiki: move to drone.io
All checks were successful
continuous-integration/drone/push Build is passing
2021-03-08 08:35:32 +01:00
Michael Hope 6cd2dafd1f wiki: post about solar panel cable loss limits 2021-03-06 12:44:45 +01:00
Michael Hope 098942ff52 wiki: post about cable losses 2021-03-02 17:53:29 +01:00
Michael Hope 7dab740083 wiki: enable minify saving a small amount of space 2021-02-28 18:21:57 +01:00
Michael Hope 2f218fc0ff wiki: post about pi-mqtt-gpio 2021-02-28 18:19:31 +01:00
Michael Hope ed0b126d31 wiki: remove the vendoring so highlighting will work 2021-02-28 18:17:53 +01:00
Michael Hope f95e254da8 wiki: update the build log 2021-02-24 13:58:59 +01:00
Michael Hope b1b1f5f826 wiki: update the solarch build log 2021-02-14 16:45:25 +01:00
Michael Hope 2b26d9b4aa wiki: post about the PC protocol 2021-02-07 21:34:33 +01:00
Michael Hope 644091f6aa wiki: post initial findings about HEYO 2021-02-07 12:12:31 +01:00
Michael Hope 43aa4cbe75 wiki: posted about brainslug 2021-01-30 17:43:08 +01:00
Michael Hope 2ecc22a18e wiki: use superscript for squared 2021-01-24 10:30:52 +01:00
Michael Hope 0559059a81 wiki: update the solar build log 2021-01-24 10:27:56 +01:00
Michael Hope b212f25def wiki: fix the PGGIS link 2021-01-10 13:08:55 +01:00
Michael Hope fa0b3bb809 wiki: post numbers on solar sizing 2021-01-10 13:03:28 +01:00
Michael Hope 9176425db2 wiki: post about the batteries and BMS 2021-01-10 11:54:57 +01:00
Michael Hope 72bd72e1f0 wiki: post about Ausdauer being assembled 2021-01-05 20:54:06 +01:00
Michael Hope 673eeac508 wiki: build log about the assembled ausdauer 2021-01-05 20:44:13 +01:00
Michael Hope bf5d7604dc wiki: fix a typo 2021-01-04 19:37:45 +01:00
Michael Hope 7a3f49eb96 wiki: post about the brace 2021-01-04 19:36:59 +01:00
Michael Hope 31e8d10d1c wiki: post about assembling ausdauer 2021-01-02 17:22:19 +01:00
Michael Hope a4c56b3ec5 wiki: post about the assembled ausdauer 2021-01-02 17:16:39 +01:00
Michael Hope a497be7098 wiki: post the build log for today 2021-01-01 20:04:36 +01:00
Michael Hope 271aba65e1 wiki: blog about the left hand assembly 2020-12-27 18:47:13 +01:00
Michael Hope 8dc7d1e5b7 wiki: update the ausdaur build log 2020-12-27 18:34:41 +01:00
Michael Hope a5dfe32c11 wiki: post about the rocker assembly 2020-12-23 20:46:07 +01:00
Michael Hope 0e521b6c51 ausdauer: post about the bed. 2020-12-22 21:01:53 +01:00
Michael Hope 269960be45 ausdauer: post on todays haul 2020-12-22 20:59:07 +01:00
Michael Hope ee90a997f1 wiki: update the ausdauer build log. 2020-12-20 20:02:00 +01:00
Michael Hope 23be61fd3e wiki: update the Ausdauer build log. 2020-12-18 13:15:41 +01:00
Michael Hope 5dc948c66d wiki: build log about Ausdauer 2020-12-12 12:17:41 +01:00
Michael Hope 79aba9050a wiki: update the tags and projects 2020-12-01 21:07:19 +01:00
Michael Hope c211e6cfe0 wiki: post about vedirect 2020-12-01 19:54:56 +01:00
Michael Hope cb8481beee wiki: rework the page locations and add features 2020-11-27 20:35:23 +01:00
Michael Hope 55bd08c4b8 wiki: tidy ups 2020-11-27 20:17:09 +01:00
Michael Hope 4e6d5cebd0 wiki: posted about nppilot 2020-11-27 17:33:28 +01:00
Michael Hope d193a78234 wiki: updated the old Z84 post 2020-11-27 11:37:23 +01:00
Michael Hope d6c872e871 wiki: update to academic v4.8.0 2020-11-27 11:06:22 +01:00
Michael Hope dbf2d9d7f5 wiki: fix a typo on the s/s 2020-11-26 21:27:12 +01:00
Michael Hope 4da09ecdb5 wiki: fix up the old solar table 2020-11-26 21:25:18 +01:00
Michael Hope 9a60f0b531 wiki: fix the intro text 2020-11-26 21:19:36 +01:00
Michael Hope 071f5bf0e1 wiki: post about the diskio 2020-11-26 21:17:58 +01:00
Michael Hope 10d13a2138 wiki: post about solarch 2020-11-19 08:57:21 +01:00
Michael Hope 87d416dbcc solarch: post about the generation per day 2020-11-10 19:53:04 +01:00
Michael Hope 7ff58358fd solarch: added a note of the power generated 2020-11-09 09:02:07 +01:00
Michael Hope a56bba3eb4 solarch: added a picture of the mounted panel 2020-11-08 13:42:32 +01:00
Michael Hope af869d5122 solarch: post about a first full day 2020-11-08 11:06:59 +01:00
Michael Hope 86e50e2220 solarch: note about the backups 2020-11-07 12:59:11 +01:00
Michael Hope e45de8e12d solarch: build log on less priviliges for powersel 2020-11-07 10:40:35 +01:00
Michael Hope 9ca1df4fc3 solarch: build log on the new powersel 2020-11-07 10:24:19 +01:00
Michael Hope 5a3142e7d8 solarch: posted about the power switch over 2020-11-03 21:57:35 +01:00
Michael Hope 2ff3820cc2 solarch: added a note on the mains switch over 2020-11-02 19:45:08 +01:00
Michael Hope bcd63a261d solarch: fix the images 2020-11-02 19:37:09 +01:00
Michael Hope 46324e4ba6 solarch: added images of the mounts 2020-11-02 19:35:16 +01:00
Michael Hope bd73e103ee solarch: build log on the exporter 2020-11-01 13:49:13 +01:00
Michael Hope 2b3e282ed6 solarch: documented todays generation 2020-10-27 20:41:25 +01:00
Michael Hope daa4488150 solarch: document the BlueSolar adapter. 2020-10-27 20:31:22 +01:00
Michael Hope 62d262b090 solarch: added the building altitude 2020-10-25 17:05:01 +01:00
Michael Hope 88db1d2876 deps: added pandoc 2020-10-25 16:55:17 +01:00
Michael Hope 217ff38090 solarch: started a build log 2020-10-25 16:21:33 +01:00
Michael Hope 0a6e09aa18 wiki: post on Vouch 2020-10-09 20:00:10 +02:00
Michael Hope 5a1744734d wiki: added the image 2020-09-04 16:56:48 +02:00
Michael Hope 4fa836fe4a wiki: post about propeller adapters 2020-09-04 15:37:56 +02:00
Michael Hope a79235d8c9 wiki: post about autobix 2020-08-29 11:27:03 +02:00
Michael Hope 20b0452195 wiki: posted about pudel 2020-05-23 20:37:17 +02:00
Michael Hope 4445963c6d wiki: added tags 2020-05-23 20:36:04 +02:00
Michael Hope 70b7a2ef92 wiki: remove the default bio 2020-05-23 20:34:13 +02:00
Michael Hope 52ea3ed55e wiki: added the missing solar icon 2020-05-23 17:40:32 +02:00
Michael Hope f1936575f5 wiki: add thumbnails and a link to Zephyr 2020-05-23 17:18:01 +02:00
Michael Hope 20798d4c39 wiki: update to academic v4.8.0 2020-05-23 17:01:43 +02:00
Michael Hope 6d249ed9fe wiki: update to academic v4.8.0 2020-05-23 16:56:31 +02:00
Michael Hope 678af16bbc wiki: use local versions of the CSS and JS 2020-05-23 16:52:58 +02:00
Michael Hope 36bbe942ae kiefer: posted about tracking using a camera 2020-04-19 20:20:36 +02:00
Michael Hope c832805ea5 Posted on Kiefer being self contained 2020-04-12 10:39:24 +02:00
Michael Hope 6db295a022 Posted on kieferbot 2020-03-22 17:10:28 +01:00
Michael Hope da595db43d Posted on kieferbot 2020-03-22 17:09:46 +01:00
Michael Hope 790c02fff8 wiki: added notes on JTAG 2020-02-09 17:21:57 +01:00
Michael Hope 1a57ed743a wiki: added a note on baremetal Pi Zero 2020-02-09 16:32:47 +01:00
Michael Hope f417fa7064 wiki: change the push directory 2020-02-02 19:47:43 +01:00
Michael Hope aefa276aed Post about ESPHome 2020-02-02 19:44:00 +01:00
Michael Hope 2033a13e11 wiki: add a push-after-build command. 2019-12-31 15:40:26 +01:00
Michael Hope 8f717ded3f wiki: update the push target 2019-12-31 15:17:38 +01:00
Michael Hope 9cf758df6d wiki: update the push target 2019-12-31 15:13:17 +01:00
146 changed files with 2870 additions and 703 deletions

39
.drone.yml Normal file
View file

@ -0,0 +1,39 @@
kind: pipeline
name: default
platform:
os: linux
arch: amd64
steps:
- name: build
image: debian:12-slim
commands:
- apt -qq update
- apt -qq install -y -q rsync pandoc wget git
- git submodule update --init --recursive
- wget -O /tmp/hugo.deb -nv https://github.com/gohugoio/hugo/releases/download/v0.121.1/hugo_extended_0.121.1_linux-amd64.deb
- dpkg --install /tmp/hugo.deb
- hugo version
- hugo --minify
- name: deploy
image: appleboy/drone-scp
settings:
host: 192.168.4.1
target: /opt/${DRONE_REPO_OWNER}/www
strip_components: 1
source: public/*
username: ${DRONE_REPO_OWNER}
key:
from_secret: ssh_key
passphrase:
from_secret: ssh_passphrase
environment:
PLUGIN_DEBUG: "true"
when:
branch:
- master
event:
exclude:
- pull_request

1
.gitignore vendored
View file

@ -1,2 +1,3 @@
public/
*~
resources/_gen

1
.gitmodules vendored
View file

@ -1,3 +1,4 @@
[submodule "themes/academic"]
path = themes/academic
url = https://github.com/gcushen/hugo-academic.git
branch = v4.8.0

View file

@ -1,40 +0,0 @@
IPNS_BASE = /ipns/juju.net.nz/michaelh/
TMPFILE := $(shell tempfile)
DESTDIR ?= dest
all: public
public:
hugo
ipfs:
hugo -b ${IPNS_BASE} -d $@
sed -i s#src=\"${IPNS_BASE}#href=\"./# $@/*.html
sed -i s#href=\"${IPNS_BASE}#href=\"./# $@/*.html
sed -i s#content=\"${IPNS_BASE}#href=\"./# $@/*.html
sed -i "s# url('${IPNS_BASE}# url('./#" $@/*.html
sed -i s#src=\"${IPNS_BASE}#href=\"../# $@/*/*.html
sed -i s#href=\"${IPNS_BASE}#href=\"../# $@/*/*.html
sed -i s#src=\"${IPNS_BASE}#href=\"../../# $@/*/*/*.html
sed -i s#href=\"${IPNS_BASE}#href=\"../../# $@/*/*/*.html
sed -i s#src=\"${IPNS_BASE}#href=\"../../../# $@/*/*/*/*.html
sed -i s#href=\"${IPNS_BASE}#href=\"../../../# $@/*/*/*/*.html
sed -i s#src=\"${IPNS_BASE}#href=\"../../../../# $@/*/*/*/*/*.html
sed -i s#href=\"${IPNS_BASE}#href=\"../../../../# $@/*/*/*/*/*.html
push: public ipfs
chmod -R go+r $^
find $^ -type d -exec chmod go+x {} \;
rsync -rlt public/ juju@www.juju.nz:michaelh/
rm -f $(TMPFILE)
install: all
mkdir -p $(DESTDIR)
tar czf $(DESTDIR)/michaelh-wiki+git$(shell git describe --always --tags).tar.gz public
deps:
sudo apt install -y -q hugo rsync
.PHONY: ipfs public
# Bump

View file

@ -1,197 +0,0 @@
baseurl = "https://juju.nz/michaelh/"
title = "Blue Duck Valley Rd"
copyright = "© 2017 Michael Hope"
theme = "academic"
enableEmoji = true
footnotereturnlinkcontents = "<sup>^</sup>"
# Enable comments by entering your Disqus shortname
disqusShortname = ""
# Enable analytics by entering your Google Analytics tracking ID
googleAnalytics = ""
# Default language to use (if you setup multilingual support)
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = false
[blackfriday]
hrefTargetBlank = true
[params]
name = "Michael Hope"
role = "Software Engineer, SRE"
organization = "Google"
organization_url = "https://landing.google.com/sre/"
avatar = "mugshot.png"
email = "michaelh@juju.nz"
address = "Switzerland"
# phone = "888 888 88 88"
# skype = "echo123"
# telegram = ""
# Enable Keybase in Contact section by entering your keybase.io username.
# keybase = "nzmichaelh"
# Date format (refer to Go's date format: http://flippinggodateformat.com )
# Examples: "Mon, Jan 2, 2006" or "2006-01-02"
date_format = "Mon, Jan 2, 2006"
# Enable global LaTeX math rendering?
# If false, you can enable it locally on a per page basis.
math = false
# Highlight.js options
# highlight
# Enable global source code highlighting? If false, you can
# override it for a particular page in that page's preamble.
#
# Example: highlight = true
#
# highlight_languages
# Add support for highlighting additional languages. Support for
# languages mentioned here will be included in all pages. You
# can also set this variable for a particular page in that
# page's preamble.
#
# Example: highlight_languages = ["go", "lisp", "ocaml"]
#
# highlight_style
# Choose a different CSS style for highlighting source
# code. Setting this option in a page's preamble has no
# effect.
#
# Example: highlight_style = "github-gist"
#
# highlight_version
# Choose the version of highlight.js you want. Setting this
# option in a page's preamble has no effect.
#
# Example: highlight_version = "9.9.0"
#
# For the list of supported languages, styles, and versions, see:
# https://cdnjs.com/libraries/highlight.js/
#
# For more info on the highlighting options, see:
# https://gcushen.github.io/hugo-academic-demo/post/writing-markdown-latex/#highlighting-options
highlight = true
highlight_languages = []
# highlight_style = "github"
# highlight_version = "9.9.0"
# Enable native social sharing buttons?
sharing = true
# Link custom CSS and JS assets
# (relative to /static/css and /static/js respectively)
custom_css = ["michaelh.css"]
custom_js = []
# Publication types.
# Used to categorize publications.
# The index of the publication type in the list is used as its unique numerical identifier.
# The numeric ID is used in a publication's frontmatter to categorize it.
# The language can be edited below.
# For multi-lingual sites, copy this block to each language section at the end of this file.
publication_types = [
'Uncategorized', # 0
'Conference proceedings', # 1
'Journal', # 2
'Work in progress', # 3
'Technical report', # 4
'Book', # 5
'Book chapter' # 6
]
# Social/Academic Networking
#
# Icon pack "fa" includes the following social network icons:
#
# twitter, weibo, linkedin, github, facebook, pinterest, google-plus,
# youtube, instagram, soundcloud
#
# For email icon, use "fa" icon pack, "envelope" icon, and
# "mailto:your@email.com" as the link.
#
# Full list: https://fortawesome.github.io/Font-Awesome/icons/
#
# Icon pack "ai" includes the following academic network icons:
#
# google-scholar, arxiv, orcid, researchgate, mendeley
#
# Full list: https://jpswalsh.github.io/academicons/
[[params.social]]
icon = "envelope"
icon_pack = "fa"
link = "mailto:michaelh@juju.nz"
[[params.social]]
icon = "code-fork"
icon_pack = "fa"
link = "//juju.nz/src/"
[[params.social]]
icon = "github"
icon_pack = "fa"
link = "//github.com/nzmichaelh"
[[params.social]]
icon = "google-plus"
icon_pack = "fa"
link = "//plus.google.com/+MichaelHopeX"
# Navigation Links
# To link a homepage widget, specify the URL as a hash `#` followed by the filename of the
# desired widget in your `content/home/` folder.
# The weight parameter defines the order that the links will appear in.
[[menu.main]]
name = "Home"
url = "#about"
weight = 1
[[menu.main]]
name = "Posts"
url = "#posts"
weight = 3
[[menu.main]]
name = "Projects"
url = "#projects"
weight = 4
[[menu.main]]
name = "Notes"
url = "#notes"
weight = 5
[[menu.main]]
name = "Contact"
url = "#contact"
weight = 6
# [[menu.main]]
# name = "Publications"
# url = "#publications_selected"
# weight = 2
# [[menu.main]]
# name = "Teaching"
# url = "#teaching"
# weight = 5
# Taxonomies.
[taxonomies]
tag = "tags"
category = "categories"
publication_type = "publication_types"
# Languages
# Create a [languages.X] block for each language you want, where X is the language ID.
# Configure the English version of the website.
[languages.en]
languageCode = "en-us"

View file

@ -0,0 +1,63 @@
# Configuration of Academic
# Documentation: https://sourcethemes.com/academic/
#
# This file is formatted using TOML syntax - learn more at https://learnxinyminutes.com/docs/toml/
# Each configuration section is defined by a name in square brackets (e.g. `[outputs]`).
title = "Blue Duck Valley Rd"
baseurl = "https://juju.nz/michaelh/"
copyright = "&copy; 2017 Michael Hope"
theme = "academic"
enableGitInfo = true
defaultContentLanguage = "en"
hasCJKLanguage = false # Set `true` for Chinese/Japanese/Korean languages.
defaultContentLanguageInSubdir = false
removePathAccents = true # Workaround for https://github.com/gohugoio/hugo/issues/5687
summaryLength = 30 # Listing summary length in words. Also, see `abstract_length` in `params.toml`.
paginate = 10 # Number of items per page in paginated lists.
enableEmoji = true
footnotereturnlinkcontents = "<sup>^</sup>"
ignoreFiles = ["\\.ipynb$", ".ipynb_checkpoints$", "\\.Rmd$", "\\.Rmarkdown$", "_files$", "_cache$"]
[outputs]
home = [ "HTML", "RSS", "JSON", "WebAppManifest" ]
section = [ "HTML", "RSS" ]
[mediaTypes."application/manifest+json"]
suffixes = ["webmanifest"]
[outputFormats.WebAppManifest]
mediaType = "application/manifest+json"
rel = "manifest"
[markup]
defaultMarkdownHandler = "goldmark"
[markup.goldmark]
[markup.goldmark.renderer]
unsafe = true # Enable user to embed HTML snippets in Markdown content.
[markup.highlight]
codeFences = false # Disable Hugo's code highlighter as it conflicts with Academic's highligher.
[markup.tableOfContents]
startLevel = 2
endLevel = 3
[imaging]
resampleFilter = "lanczos"
quality = 90
anchor = "smart" # Anchor for cropping. Options include Smart and Center.
# Taxonomies.
[taxonomies]
tag = "tags"
category = "categories"
publication_type = "publication_types"
author = "authors"
[security]
enableInlineShortcodes = false
[security.exec]
allow = ['^(dart-)?sass(-embedded)?$', '^go$', '^npx$', '^postcss$', '^pandoc$']
osEnv = ['(?i)^((HTTPS?|NO)_PROXY|PATH(EXT)?|APPDATA|TE?MP|TERM|GO\w+)$']

View file

@ -0,0 +1,2 @@
[en]
languageCode = "en-us"

View file

@ -0,0 +1,19 @@
# Navigation Links
# To link a homepage widget, specify the URL as a hash `#` followed by the filename of the
# desired widget in your `content/home/` folder.
# The weight parameter defines the order that the links will appear in.
[[main]]
name = "Posts"
url = "#posts"
weight = 20
[[main]]
name = "Projects"
url = "#projects"
weight = 30
[[main]]
name = "Notes"
url = "#notes"
weight = 40

110
config/_default/params.toml Normal file
View file

@ -0,0 +1,110 @@
# SITE SETUP
# Documentation: https://sourcethemes.com/academic/
############################
## Theme
############################
# Choose a theme.
# Latest themes (may require updating): https://sourcethemes.com/academic/themes/
# Browse built-in themes in `themes/academic/data/themes/`
# Browse user installed themes in `data/themes/`
theme = "minimal"
# Enable users to switch between day and night mode?
day_night = false
# Override the theme's font set (optional).
# Latest font sets (may require updating): https://sourcethemes.com/academic/themes/
# Browse built-in font sets in `themes/academic/data/fonts/`
# Browse user installed font sets in `data/fonts/`
font = "minimal"
# Choose a font size.
# Sizes: XS (extra small), S (small), M (medium), L (large - DEFAULT), XL (extra large)
font_size = "M"
############################
## Basic Info
############################
# Website type
# Improve how search engines understand your site.
# For personal sites, choose "Person".
# For organizations and projects, choose from https://schema.org/Organization#subtypes
# E.g. Person, Organization, LocalBusiness, Project, EducationalOrganization
site_type = "Person"
# Local business type (optional)
# If you entered "LocalBusiness" above, choose the type of business from https://schema.org/LocalBusiness#subtypes
local_business_type = ""
# Organization name (optional)
# Enter an organization or project name. Defaults to the site title from `config.toml`.
org_name = ""
# Description for social sharing and search engines. If undefined, superuser role is used in place.
description = ""
############################
## Site Features
############################
# Enable source code highlighting? true/false
# Documentation: https://sourcethemes.com/academic/docs/writing-markdown-latex/#highlighting-options
highlight = true
# Enable LaTeX math rendering? true/false
# If false, you can enable math on a per page basis as needed.
math = false
# Enable diagram rendering? true/false
# If false, you can enable diagrams on a per page basis as needed.
diagram = false
# Privacy pack
# Show a cookie consent message to visitors
# Anonymize IP in Google Analytics (if enabled)
privacy_pack = false
email = "michaelh@juju.nz"
# Address
# For country_code, use the 2-letter ISO code (see https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2 )
address = {city = "Zürich", country = "Switzerland", country_code = "CH"}
date_format = "Jan 2, 2006"
time_format = "15:04"
address_format = "en-us"
# Main menu alignment (l = left, c = center, r = right) and logo options.
main_menu = {align = "l", show_logo = true}
reading_time = false
sharing = false
link_authors = true
abstract_length = 135
netlify_cms = false
[avatar]
gravatar = false
shape = "circle"
[projects]
# Views for associated content.
# 1: List
# 2: Compact
# 3: Card
# 4: Citation (publications only)
post_view = 2
publication_view = 2
talk_view = 2
[comments]
engine = 0
commentable = {page = true, post = true, docs = true, project = true, publication = true, talk = true}
[search]
engine = 1
[address_formats]
en-us = {order = ['street', 'city', 'region', 'postcode'], delimiters = [', ', ', ', ' ', '']}

View file

@ -0,0 +1,44 @@
---
name: Michael Hope
authors:
- michaelh
superuser: true
role: Software Engineer
# Organizations/Affiliations
organizations:
- name: Google Zürich
url: "https://careers.google.com/locations/zurich/"
interests:
- Autonomus machines, especially drones
- Developer tools
- Languages, and their use in embedded
- Embedded software and electronics
education:
courses:
- course: Electrical and Electronic Enginnering
institution: University of Canterbury
- course: Mathematics
institution: University of Canterbury
social:
- icon: envelope
icon_pack: fas
link: 'mailto:michaelh@juju.nz'
- icon: code-branch
icon_pack: fas
link: https://juju.nz/src/
- icon: github
icon_pack: fab
link: https://github.com/nzmichaelh
# Enter email to display Gravatar (if Gravatar enabled in Config)
email: "michaelh@juju.nz"
---
I'm a software engineer from Christchurch, New Zealand now in Zürich, Switzerland.

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

View file

@ -0,0 +1,29 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Vedirect"
subtitle: ""
summary: ""
authors: []
tags: []
categories: []
date: 2020-12-01T19:44:14+01:00
lastmod: 2020-12-01T19:44:14+01:00
featured: false
draft: false
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
# Focal points: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight.
image:
caption: ""
focal_point: ""
preview_only: false
# Projects (optional).
# Associate this post with one or more of your projects.
# Simply enter your project's folder or file name without extension.
# E.g. `projects = ["internal-project"]` references `content/project/deep-learning/index.md`.
# Otherwise, set `projects = []`.
projects: []
---

View file

@ -0,0 +1,24 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Ausdauer: assembled"
subtitle: ""
summary: "I've almost completed the right hand side, and the left hand side is far enough along that I can assemble the whole rover!"
authors: ['michaelh']
tags: []
categories: []
date: 2021-01-02T17:17:27+01:00
lastmod: 2021-01-02T17:17:27+01:00
featured: false
draft: false
projects: ['ausdauer']
---
I've almost completed the right hand side, and the left hand side is far enough along that I can assemble the whole rover!
The remaining steps are:
1. Epoxy the steering wheel and differential inserts in. I didn't modify the print, and the 3D Jake insets are ~1 mm smaller in diameter.
2. Cut the grooves on the left hand side shafts.
3. Print the differential.

View file

@ -0,0 +1,29 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Ausdauer_assembled2"
subtitle: ""
summary: ""
authors: []
tags: []
categories: []
date: 2021-01-05T20:50:00+01:00
lastmod: 2021-01-05T20:50:00+01:00
featured: false
draft: false
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
# Focal points: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight.
image:
caption: ""
focal_point: ""
preview_only: false
# Projects (optional).
# Associate this post with one or more of your projects.
# Simply enter your project's folder or file name without extension.
# E.g. `projects = ["internal-project"]` references `content/project/deep-learning/index.md`.
# Otherwise, set `projects = []`.
projects: []
---

View file

@ -1,53 +1,10 @@
+++
# About/Biography widget.
# About widget.
widget = "about" # See https://sourcethemes.com/academic/docs/page-builder/
headless = true # This file represents a page section.
active = true # Activate this widget? true/false
weight = 20 # Order that this section will appear in.
date = "2016-04-20T00:00:00"
draft = false
widget = "about"
# Order that this section will appear in.
weight = 1
# List your academic interests.
[interests]
interests = [
"Autonomus machines, especially drones",
"Developer tools",
"Languages, and their use in embedded",
"Embedded software and electronics",
"People management",
]
# List your qualifications (such as academic degrees).
[[education.courses]]
course = "BE(Hons) Electrical and Electronic Enginnering"
institution = "University of Canterbury"
year = 1999
[[education.courses]]
course = "BSc Mathematics"
institution = "University of Canterbury"
year = 1999
title = "Biography"
author = "michaelh"
+++
# Biography
I'm a software engineer from Christchurch, New Zealand now in Zürich, Switzerland.
I'm currently a manager and ex-TPM in
[SRE](http://www.reddit.com/r/IAmA/comments/1w1y5m/) at
[Google in Zürich](//careers.google.com/locations/zurich/)
and before that led the
[Linaro](//www.linaro.org/)
[Toolchain Working Group](//wiki.linaro.org/WorkingGroups/ToolChain)
on [GCC](//gcc.gnu.org/), [GDB](//www.gnu.org/software/gdb/),
[QEMU](http://wiki.qemu.org), and everything else developer
related.
My company was [Seabright Technology](http://seabright.co.nz/)
and I'm up on [Linkedin](//nz.linkedin.com/pub/michael-hope/10/42/16b).
Some professional history is in my [[cv]]. There's even a
[blog](/michaelh/blog/) which is mirrored up on
[G+](//plus.google.com/+MichaelHopeX).

View file

@ -1,18 +0,0 @@
+++
# Contact widget.
date = "2016-04-20T00:00:00"
draft = false
title = "Contact"
subtitle = ""
widget = "contact"
# Order that this section will appear in.
weight = 70
# Automatically link email and phone?
autolink = true
+++

5
content/home/index.md Normal file
View file

@ -0,0 +1,5 @@
+++
# Homepage
type = "widget_page"
headless = true # Homepage is headless, other widget pages are not.
+++

View file

@ -1,45 +1,54 @@
+++
# Notes widget.
# Note: this widget will only display if `content/note/` contains notes.
date = "2016-04-20T00:00:00"
draft = false
widget = "portfolio" # See https://sourcethemes.com/academic/docs/page-builder/
headless = true # This file represents a page section.
active = true # Activate this widget? true/false
weight = 75 # Order that this section will appear.
title = "Notes"
subtitle = ""
widget = "notes"
# Order that this section will appear in.
weight = 55
[content]
# Page type to display. E.g. project.
page_type = "note"
# View.
# Customize how notes are displayed.
# Legend: 0 = list, 1 = cards.
view = 1
[design]
# Choose how many columns the section has. Valid values: 1 or 2.
columns = "2"
# Filter toolbar.
# Add or remove as many filters (`[[filter]]` instances) as you like.
# Use "*" tag to show all notes or an existing tag prefixed with "." to filter by specific tag.
# To remove toolbar, delete/comment all instances of `[[filter]]` below.
[[filter]]
name = "All"
tag = "*"
[[filter]]
name = "Machines"
tag = ".machines"
# Toggle between the various page layout types.
# 1 = List
# 2 = Compact
# 3 = Card
# 5 = Showcase
view = 3
[[filter]]
name = "Embedded"
tag = ".embedded"
# For Showcase view, flip alternate rows?
flip_alt_rows = false
[[filter]]
name = "Dev tools"
tag = ".devtools"
[design.background]
# Apply a background color, gradient, or image.
# Uncomment (by removing `#`) an option to apply it.
# Choose a light or dark text color by setting `text_color_light`.
# Any HTML color name or Hex value is valid.
[[filter]]
name = "People"
tag = ".people"
# Background color.
# color = "navy"
# Background gradient.
# gradient_start = "DeepSkyBlue"
# gradient_end = "SkyBlue"
# Background image.
# image = "background.jpg" # Name of image in `static/img/`.
# image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
# Text color (true=light or false=dark).
# text_color_light = true
[advanced]
# Custom CSS.
css_style = ""
# CSS class.
css_class = ""
+++

View file

@ -1,22 +1,68 @@
+++
# Recent Posts widget.
# Note: this widget will only display if `content/post/` contains posts.
# A Recent Blog Posts section created with the Pages widget.
# This section displays recent blog posts from `content/post/`.
date = "2016-04-20T00:00:00"
draft = false
widget = "pages" # See https://sourcethemes.com/academic/docs/page-builder/
headless = true # This file represents a page section.
active = true # Activate this widget? true/false
weight = 60 # Order that this section will appear.
title = "Recent Posts"
subtitle = ""
widget = "posts"
# Order that this section will appear in.
weight = 40
[content]
# Page type to display. E.g. post, talk, or publication.
page_type = "post"
# Show posts that contain the following tags. Default to any tags.
tags = []
# Choose how much pages you would like to display (0 = all pages)
count = 5
# Number of posts to list.
count = 5
# Choose how many pages you would like to offset by
offset = 0
# Page order. Descending (desc) or ascending (asc) date.
order = "desc"
# Filter posts by a taxonomy term.
[content.filters]
tag = ""
category = ""
publication_type = ""
author = ""
exclude_featured = false
[design]
# Toggle between the various page layout types.
# 1 = List
# 2 = Compact
# 3 = Card
# 4 = Citation (publication only)
view = 2
[design.background]
# Apply a background color, gradient, or image.
# Uncomment (by removing `#`) an option to apply it.
# Choose a light or dark text color by setting `text_color_light`.
# Any HTML color name or Hex value is valid.
# Background color.
# color = "navy"
# Background gradient.
# gradient_start = "DeepSkyBlue"
# gradient_end = "SkyBlue"
# Background image.
# image = "background.jpg" # Name of image in `static/img/`.
# image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
# Text color (true=light or false=dark).
# text_color_light = true
[advanced]
# Custom CSS.
css_style = ""
# CSS class.
css_class = ""
+++

View file

@ -1,45 +1,55 @@
+++
# Projects widget.
# Note: this widget will only display if `content/project/` contains projects.
date = "2016-04-20T00:00:00"
draft = false
# A Projects section created with the Portfolio widget.
widget = "portfolio" # See https://sourcethemes.com/academic/docs/page-builder/
headless = true # This file represents a page section.
active = true # Activate this widget? true/false
weight = 65 # Order that this section will appear.
title = "Projects"
subtitle = ""
widget = "projects"
# Order that this section will appear in.
weight = 50
[content]
# Page type to display. E.g. project.
page_type = "project"
# View.
# Customize how projects are displayed.
# Legend: 0 = list, 1 = cards.
view = 1
[design]
# Choose how many columns the section has. Valid values: 1 or 2.
columns = "2"
# Filter toolbar.
# Add or remove as many filters (`[[filter]]` instances) as you like.
# Use "*" tag to show all projects or an existing tag prefixed with "." to filter by specific tag.
# To remove toolbar, delete/comment all instances of `[[filter]]` below.
[[filter]]
name = "All"
tag = "*"
[[filter]]
name = "Machines"
tag = ".machines"
# Toggle between the various page layout types.
# 1 = List
# 2 = Compact
# 3 = Card
# 5 = Showcase
view = 3
[[filter]]
name = "Embedded"
tag = ".embedded"
# For Showcase view, flip alternate rows?
flip_alt_rows = false
[[filter]]
name = "Dev tools"
tag = ".devtools"
[design.background]
# Apply a background color, gradient, or image.
# Uncomment (by removing `#`) an option to apply it.
# Choose a light or dark text color by setting `text_color_light`.
# Any HTML color name or Hex value is valid.
[[filter]]
name = "People"
tag = ".people"
# Background color.
# color = "navy"
# Background gradient.
# gradient_start = "DeepSkyBlue"
# gradient_end = "SkyBlue"
# Background image.
# image = "background.jpg" # Name of image in `static/img/`.
# image_darken = 0.6 # Darken the image? Range 0-1 where 0 is transparent and 1 is opaque.
# Text color (true=light or false=dark).
# text_color_light = true
[advanced]
# Custom CSS.
css_style = ""
# CSS class.
css_class = ""
+++

View file

@ -1,22 +0,0 @@
+++
# Recent Publications widget.
# Note: this widget will only display if `content/publication/` contains publications.
date = "2016-04-20T00:00:00"
draft = true
title = "Recent Publications"
subtitle = ""
widget = "publications"
# Order that this section will appear in.
weight = 20
# Number of publications to list.
count = 10
# Show publication details (such as abstract)? (true/false)
detailed_list = false
+++

View file

@ -1,20 +0,0 @@
+++
# Selected Publications widget.
# Note: this widget will only display if `content/publication/` contains publications
# with `selected = true` in their `+++` preamble.
date = "2016-04-20T00:00:00"
draft = true
title = "Selected Publications"
subtitle = ""
widget = "publications_selected"
# Order that this section will appear in.
weight = 10
# Show publication details (such as abstract)? (true/false)
detailed_list = true
+++

View file

@ -1,21 +0,0 @@
+++
# Recent and Upcoming Talks widget.
date = "2016-04-20T00:00:00"
draft = true
title = "Recent & Upcoming Talks"
subtitle = ""
widget = "talks"
# Order that this section will appear in.
weight = 30
# Number of talks to list.
count = 10
# Show talk details (such as abstract)? (true/false)
detailed_list = false
+++

View file

@ -1,27 +0,0 @@
+++
# An example of using the custom widget to create your own homepage section.
# To create more sections, duplicate this file and edit the values below as desired.
date = "2016-04-20T00:00:00"
draft = true
title = "Teaching"
subtitle = ""
widget = "custom"
# Order that this section will appear in.
weight = 60
+++
This is an example of using the *custom* widget to create your own homepage section.
I am a teaching instructor for the following courses at University X:
- CS101: An intro to computer science
- CS102: An intro to computer science
- CS103: An intro to computer science
- CS104: An intro to computer science
- CS105: An intro to computer science
- CS106: An intro to computer science
- CS107: An intro to computer science

View file

@ -10,7 +10,7 @@ categories:
---
A certain website had a few vuneribilities including XSS and leaking passwords.  The fixes were:
* The <script> tag was turned on for pending users.  Configure off.  All other users get their tags filtered against a safe list
* The `<script>` tag was turned on for pending users.  Configure off.  All other users get their tags filtered against a safe list
* The superuser always skips the filter and sees all tags.  I can&#8217;t fix this, but I&#8217;ve changed the cookie so that its not useful to a cookie catcher
* The &#8216;password&#8217; in the cookie was just a hash of the password.  It is now a hash of the password, the IP address of the client, and a secret.  A leaked password should only be usable from the same IP
* The &#8216;password&#8217; field has been removed from all forms and replaced with cookie based authentication
* The &#8216;password&#8217; field has been removed from all forms and replaced with cookie based authentication

View file

@ -3,14 +3,14 @@ title: Z-84 flying wing
author: michaelh
type: post
date: 2015-10-03T15:49:55+00:00
url: /2015/10/z-84-flying-wing/
#url: /2015/10/z-84-flying-wing/
categories:
- Flying
---
Hobbyking had a free shipping promotion recently, so I picked up a [Wing Wing Z-84 flying wing][1] like [all the cool kids have][2].
[<img src="https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/10/IMG_20151003_171416.jpg" alt="Z-84 flying wing" width="2448" height="2506" class="aligncenter size-full wp-image-284" />][3]
![Z-84 flying wing](IMG_20151003_171416.jpg)
It&#8217;s quite fun if a bit noisy. The 1500 mAh 2S batter lasts 15 minutes, which is crazy long, and it&#8217;s quite interesting how a pusher propeller changes climbs and loops &#8211; you need momentum as there&#8217;s no propeller to caster under.
@ -18,4 +18,3 @@ Next step is to change the motor controller for the one that the PX4 team recomm
[1]: http://www.hobbyking.com/hobbyking/store/__25664__Wing_Wing_Z_84_EPO_845mm_PNF_.html
[2]: https://pixhawk.org/platforms/planes/z-84_wing_wing
[3]: https://juju.net.nz/michaelh/blog/wp-content/uploads/2015/10/IMG_20151003_171416.jpg

Binary file not shown.

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 45 KiB

View file

@ -0,0 +1 @@
adapter.png

View file

@ -0,0 +1,18 @@
+++
date = "2020-09-04T00:02:42+02:00"
title = "Propeller adapter"
highlight = true
draft = false
+++
A nice thing about having a 3D printer is quick fixes to small
things. The 8x4 propeller that came with my [Bixler 3][bixler3] was
loose on the motor shaft, so I 3D printed an adapter:
![Propeller adapter](./adapter.png)
It took 5 minutes to print and three tries to get the tolerances
right, but the propeller is now a good fit, much quieter, and seems
more powerful. Yay!
[bixler3]: https://hobbyking.com/en_us/h-king-bixler-3-glider-1550-pnf.html

Binary file not shown.

After

Width:  |  Height:  |  Size: 114 KiB

View file

@ -0,0 +1,15 @@
---
title: "Ausdauer: left rocker/bogie assembly"
subtitle: ""
summary: "Progress update showing the new left hand assembly"
authors: ["michaelh"]
categories: []
date: 2020-12-27T18:35:54+01:00
lastmod: 2020-12-27T18:35:54+01:00
draft: false
projects: ["ausdauer"]
---
I'm working on a build of the [Sawppy rover](https://github.com/Roger-random/Sawppy_Rover). Today was a major milestone, as I finished assembling the left hand rocker/bogie assembly. This covers all of the major parts and techniques needed to build the rover, so the remaining work is to crank the handle and get the right side and box done.
There's more information at the [build log](https://juju.nz/michaelh/project/ausdauer/).

Binary file not shown.

After

Width:  |  Height:  |  Size: 431 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 371 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 74 KiB

View file

@ -0,0 +1 @@
20200824_171653.jpg

View file

@ -0,0 +1,45 @@
+++
date = "2020-08-29T00:02:42+02:00"
title = "Bixler 3 Drone"
highlight = true
draft = false
+++
I recently purchased a HobbyKing [Bixler 3][bixler3] to use as a autopilot
platform and am pretty happy with how it turned out. Both the under
wing area and nose area have plenty of room and could easily fit a
[Pixhawk 4 Mini][p4m] with GPS and telemetry.
I prefer the Pixhawk 4 Mini over the older [Pixfalcon][pixfalcon] for
a few reasons:
- the servo connectors are built-in to the module
- the safety switch is built-in to the GPS
- two of the four sides are connector free, making it easier to route
I ended up putting the power distribution board in the under wing area
and 3D printing a hatch to hold everything else:
![Hatch](./ap.png)
The hatch is held on by the front tongue and 2x magnets. The
autopilot, telemetry, and RX are on the bottom of the hatch and the
GPS on top:
![Cropped to autopliot](./20200824_171653.jpg)
The plane flew just fine in stabilised and hold mode with the default
PX4 aircraft turnings. I was a bit surprised by how PX4 handles a
strong headwind - if the plane can't make progress in hold mode at the
cruise throttle then it gives up and switches back to stabilised
mode.
![Overall](./20200824_171641.jpg)
Once the weather clears up I hope to do some waypoint tests. I'd also
like to find a quieter propeller. The stock is fine, but it's
slightly unbalanced and could be much quieter.
[bixler3]: https://hobbyking.com/en_us/h-king-bixler-3-glider-1550-pnf.html
[p4m]: https://shop.holybro.com/pixhawk4-mini_p1120.html
[pixfalcon]: https://docs.px4.io/v1.9.0/en/flight_controller/pixfalcon.html

View file

@ -0,0 +1 @@
iosecs.png

View file

@ -0,0 +1,68 @@
---
date: "2020-11-26T00:02:42+02:00"
title: "Reducing disk IO"
highlight: true
draft: false
projects: ["solarch"]
---
I'm using a Raspberry Pi 4 with a USB3 based SSD to host this website
and other services, and as a side effect the lounge looks like a disco
due to all the flashing activity LEDs.
The machine should be fairly idle so I went looking for where the disk
activity was coming from.
Running `iotop -a` and looking at the writes shows that mysql (aka
MariaDB) is by far the heaviest writer.
Looking at the metrics recorded by the Prometheus
[mysqld\_exporter](https://github.com/prometheus/mysqld_exporter):
```
delta(mysql_global_status_commands_total[1h])
```
gives:
![MariaDB commands per hour](mysql.png)
which is dominated by inserts.
Dropping to the mysql command line and running:
```
SELECT table_name, table_rows from
INFORMATION_SCHEMA.TABLES ORDER BY table_rows DESC LIMIT 20;
```
gives:
| table_name | table\_rows |
|------------------------------------------------|------------|
| events | 1731748 |
| states | 1577498 |
| oc\_filecache | 26239 |
| notice | 23483 |
The `events` and `states` tables are part of my
[HomeAssistant](https://www.home-assistant.io/) installation. Reading
the docs shows that the `recorder` commits every second and changing this
to 5m using:
```
recorder:
db_url: mysql+pymysql://hass:....@db/hass?charset=utf8
commit_interval: 300
```
fixes the problem. This reduces the write rate from 680 KiB/s to
~95 KiB/s:
![Bytes written per 10 minutes](writes.png)
and cuts the I/O seconds per second:
![I/O seconds per second](iosecs.png)
and makes the lounge much less blinky, yay!

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -0,0 +1,40 @@
+++
date = "2020-02-01T00:02:42+02:00"
title = "ESPHome as a Ruuvi bridge"
highlight = true
draft = false
+++
[ESPHome](https://esphome.io/) is a framework for building custom home
automation that runs on an ESP8266 or
[ESP32][esp32]. It's pretty cool - you
select and configure components by writing a [YAML
file][cfg], which
then drives host side [Python
snippets][snip]
to configure and bind the device side code, which is then built and
pushed using [PlatformIO](https://platformio.org/).
[esp32]: https://en.wikipedia.org/wiki/ESP32
[cfg]: https://esphome.io/cookbook/display_time_temp_oled.html
[snip]: https://github.com/esphome/esphome/blob/dev/esphome/components/ruuvitag/sensor.py
Some nice touches:
- It integrates with [Home Assistant](https://home-assistant.io/)
and has automatic discovery
- It can drive displays, including [rendering TTF files][ttf]
host side to give nice fonts device side
- It looks reasonably composable so, for example, you can have
multiple Bluetooth broadcast parsers
[ttf]: https://esphome.io/cookbook/display_time_temp_oled.html#define-the-fonts
I used this to bridge between [Ruuvi tags](https://ruuvi.com/) and my
Home Assistant instance. Home Assistant then re-exports everything to
[Prometheus](https://prometheus.io/).
It also gave me a reason to break out the 3D printer and make a case
for the ESP-WROOM-32 based
[Lolin32](https://wiki.wemos.cc/products:lolin32:lolin32):
![Case](./case.jpg)

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View file

@ -0,0 +1,55 @@
+++
date = "2020-04-11T00:00:00+02:00"
title = "Self-contained and smoke"
highlight = true
draft = false
tags = ["kieferbot"]
+++
A day of highs and lows. Here's Kieferbot still in [teleop][teleop]
mode but now self contained:
<video controls src="self.m4v"></video>
The [PinePhone][pinephone] is taking commands from a PS4 DualShock
over Bluetooth using `ds4drv` and sending them to the IO board over
serial. I experimented with a few transports:
- UDP over Wifi was fine, but the default ESP32 Wifi power mode added
random latency of up to 100 ms. Switching to 'always on' mode by
modifying MicroPython fixed this.
- Bluetooth Low Energy worked for one-way communication to the IO
board, but there was lots of packet loss when using Bluetooth for
both the joystick and IO.
Inspired by [Firmata][firmata], I settled on MIDI over serial. I
quite like the MIDI format for short messages. A frame starts with
the command followed by a command specific payload. The command has
the MSB set so it's simple to frame.
I also compiled [ROS Kinetic][kinetic] for Debian Buster and created an IO node
that takes left and right velocity commands. There seems to be an
ordering issue with either the ESP32 PWM chip or the FIT0441
controller, where going from forward to reverse and vice-versa is
fine but the motor won't start sometimes when going from zero.
So plenty of highs, but the low was [releasing the smoke][smoke] - I'm
using a LiPo battery for the supply and something short-circuited when
unplugging the battery. It seems to have taken out the regulator and
the ESP32 flash.
Next step is to re-make the IO board using an [ItsyBitsy M4][m4]. It
also runs MicroPython so the IO software was easy to port. I've
ordered some Seeed [XIAO][xiao] boards - $5 gives you a MicroPython
compatible SAMD21 with 9 pins of IO which is enough for this project.
This time I'll secure the battery socket better and 3D print a
shield.
[pinephone]: https://wiki.pine64.org/index.php/PinePhone
[teleop]: https://en.wikipedia.org/wiki/Teleoperation
[firmata]: https://github.com/firmata/protocol
[xiao]: https://www.seeedstudio.com/Seeeduino-XIAO-Arduino-Microcontroller-SAMD21-Cortex-M0+-p-4426.html
[kinetic]: http://wiki.ros.org/kinetic
[smoke]: https://en.wikipedia.org/wiki/Magic_smoke
[m4]: https://www.adafruit.com/product/3800

Binary file not shown.

View file

@ -0,0 +1,26 @@
+++
date = "2020-03-22T00:00:00+02:00"
title = "Teleop"
highlight = true
draft = false
tags = ["kieferbot"]
+++
As a winter project, I'm turning my
[PinePhone](https://wiki.pine64.org/index.php/PinePhone) into an
indoor robot. The Pinephone has everything needed for a decent
stand-alone robot: plenty of CPU, a camera,
gyro/accelerometor/compass, display, and it can run Debian.
Below is a video of the hardware in [teleop](https://en.wikipedia.org/wiki/Teleoperation) mode. A
[Lolin32](https://wiki.wemos.cc/products:lolin32:lolin32)
[ESP32](https://www.espressif.com/en/products/hardware/esp32/overview)
running [MicroPython](https://micropython) takes commands over
Bluetooth LE and sends PWM and direction signals to the
[FIT0441](https://wiki.dfrobot.com/FIT0441_Brushless_DC_Motor_with_Encoder_12V_159RPM)
motors. The frame is 3D printed.
<video controls src="teleop.m4v"></video>
Currently the phone is just a passenger. The next step is to get the
phone to communicate with the IO board.

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 220 KiB

View file

@ -0,0 +1 @@
above.jpg

View file

@ -0,0 +1,27 @@
---
title: "nppilot"
subtitle: "My never complete, often restarted rover"
summary: ""
date: 2020-11-27T17:23:01+01:00
lastmod: 2020-11-27T17:23:01+01:00
featured: true
draft: false
projects: ["nppilot"]
---
I realized I haven't posted about the current generation of `nppilot`,
my never complete, often restarted rover project.
The current version is a modified Traxxas E-Revo 1/16:
Under the hood this is:
* A Revo controller running ROSflight for control and sensors.
* A Raspberry Pi 3 running ROS for command and telemetry.
The frame is laser cut MDF with 3D printed mounts and
risers.
It works well, but winter came before I made much progress on the
control. The goal is for the Pi to do the planning using the GPS and a
map of the local area, and to see how fast it can complete the course.

View file

@ -0,0 +1,59 @@
+++
date = "2020-05-23T00:00:00+02:00"
title = "Pan/tilt mount for a cell phone"
highlight = true
draft = false
tags = ["pudel", "ros"]
+++
I think it's important to also post about the projects that didn't
turn out. Pudel was a project to automatically track and video a
model plane using a cell phone camera.
![mount](mount.jpg)
The pan and tilt components were modeled in
[OpenSCAD](https://openscad.org/) and 3D printed. The pan unit had a
standard [1/4-20 tripod mount][tri] and the tilt unit had a Samsung
A40 mount that I've used on a few other projects.
[tri]: https://www.matrix-vision.com/manuals/mvBlueFOX/mvBF_page_tech.html
![close](closeup.jpg)
Both were driven by standard [HS-422][hs422] servos with a [Trinket M0][m0]
for I/O and a 2S LiPo through a [6V BEC][bec] for power.
The I/O board ran [CircuitPython][cp] with custom firmware that takes
MIDI-like messages as servo commands. It implemented an
acceleration limiter and velocity limiter to limit the
[jerk][jerk], as the servos are capable of 60 deg/0.2 s which is much
faster than the plane would move.
The host side was going to be similar to Kieferbot and use ROS with an
IO specific node, OpenCV based detection, and a PID controller to keep
the plane centered in the frame.
So why did it fail?
- The servos aren't intended for precise, slow movement and hence had
mild jerk.
- There was too much slack in the mechanics, and the phone was mildly
heavy, so mild jerk caused the phone to move about too much.
- The plane is too small to resolve on a wide angle lens, so tracking
was unlikely to work.
If I wanted to take it further, I can imagine some improvements:
- Take the load off the pan servo. The tilt unit sits directly on top
of the pan servo shaft and there's not much material to sit on which
increased the shake. Perhaps add a turntable style plates that most
of the downwards force could go through.
- Decrease the arm length out to the phone. It's 30 mm and reducing
to 20 mm would reduce the load on the tilt servo.
- Try a phone with optical stabilization.
[bec]: https://hobbyking.com/en_us/turnigy-3a-ubec-w-noise-reduction.html?___store=en_us
[cp]: https://circuitpython.org/
[hs422]: https://hitecrcd.com/products/servos/sport-servos/analog-sport-servos/hs-422/product
[jerk]: https://en.wikipedia.org/wiki/Jerk_(physics)
[m0]: https://www.adafruit.com/product/3500

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

View file

@ -0,0 +1,101 @@
+++
date = "2020-02-09T00:02:42+02:00"
title = "Bare metal Raspberry Pi Zero"
highlight = true
draft = false
+++
These are short notes on loading baremetal software on the Raspberry
Pi Zero. I started down this path due to wanting to learn Rust, which
lead to [Tock](https://www.tockos.org/) which is an embedded operating
system in Rust. Rather than buy yet another piece of hardware I
though I'd use one of my 5 (!) Raspberry Pi Zeros as a development
board instead. It's just another microcontroller, just one that runs
at 1 GHz and has a ton of RAM...
# Console
See https://pinout.xyz/pinout/uart for the UART pins. Note that on
Linux you need to add `enable_uart=1` to `boot/config.txt`.
Connect to a USB --> Serial adapter and launch a console at 11500
baud.
# Examples
See [dwelch][dwelch]'s bare metal examples. Note that every Pi model
has different things on different pins so use the examples from
`boards/pizero`.
[dwelch]: https://github.com/dwelch67/raspberrypi
# Loading
The Pi Zero can boot over USB from a host machine without needing a SD
card. This greatly reduces the build/debug cycle. To do this:
- Fetch `bootcode.bin` and `start.elf` from the [firmware][firmware]
repo.
- Fetch the [usbboot][usbboot] repo and build.
- Copy the `.bin` file to `kernel.img`
- Run `sudo rpiboot -d .`
- Unplug / plug the board
A fully worked example is:
```sh
$ git clone --depth 1 https://github.com/raspberrypi/firmware
Cloning into 'firmware'...
$ mkdir boot
$ cp firmware/boot/bootcode.bin firmware/boot/start.elf boot/
$ git clone https://github.com/raspberrypi/usbboot.git
Cloning into 'usbboot'...
$ make -C usbboot/
$ git clone https://github.com/dwelch67/raspberrypi.git
$ make -C raspberrypi/boards/pizero/uart02/
$ cp raspberrypi/boards/pizero/uart02/uart02.bin boot/kernel.img
$ sudo ./usbboot/rpiboot -d boot
Waiting for BCM2835/6/7/2711...
Sending bootcode.bin
Successful read 4 bytes
Waiting for BCM2835/6/7/2711...
Second stage boot server
File read: start.elf
File read: kernel.img
Second stage boot server done
```
[firmware]: https://github.com/raspberrypi/firmware/tree/master/boot
[usbboot]: https://github.com/raspberrypi/usbboot
# JTAG
- Add `enable_jtag_gpio=1` to `boot/config.txt`
- Wire up using
https://github.com/raspberrypi/linux/issues/1749#issuecomment-265404857
- Use the `raspberry.cfg` from
https://sysprogs.com/VisualKernel/tutorials/raspberry/jtagsetup/
- Run openocd using `openocd -f interface/jlink.cfg -f ./raspberry.cfg`
- Run gdb-multiarch against the corresponding ELF file
giving:
```sh
$ sudo openocd -f interface/jlink.cfg -f ./raspberry.cfg
Open On-Chip Debugger 0.10.0
Licensed under GNU GPL v2
For bug reports, read
http://openocd.org/doc/doxygen/bugs.html
adapter speed: 100 kHz
adapter_nsrst_delay: 400
none separate
Info : auto-selecting first available session transport "jtag". To override use 'transport select <transport>'.
Info : No device selected, using first device.
Info : J-Link ARM V8 compiled Nov 28 2014 13:44:46
Info : Hardware version: 8.00
Info : VTarget = 3.287 V
Info : clock speed 100 kHz
Info : JTAG tap: rspi.arm tap/device found: 0x07b7617f (mfg: 0x0bf (Broadcom), part: 0x7b76, ver: 0x0)
Info : found ARM1176
Info : rspi.arm: hardware has 6 breakpoints, 2 watchpoints
```
Note that the ARM CPU needs to be running some code for the JTAG to connect.

View file

@ -0,0 +1 @@
mounted.jpg

View file

@ -0,0 +1,27 @@
---
date: "2020-11-19T00:00:00+02:00"
title: "Solar at home"
highlight: true
draft: false
projects: ["solarch"]
---
For the last month or so I've been working on making my home server
(which also hosts this blog!) solar powered. It's pointless but
entertaining, and this is a first of a series of posts about what I
learned on the way.
![Solar panel mounted on the frame](mounted.jpg)
The summary is that a 55 W panel with 200 Wh of battery is enough to
power a Raspberry Pi 4 with SSD during the European winter. You still
need a mains power fallback, as a couple of days of grey weather will
deplete the battery.
The last 7d have been fairly sunny:
![Total power generation in Wh per day](totals.png)
This graph shows the power generated over a 16h window, so the peaks
are the total generation for that day. Total for the week was 741 Wh
or $0.15.

Binary file not shown.

After

Width:  |  Height:  |  Size: 102 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

View file

@ -0,0 +1,33 @@
+++
date = "2020-04-19T00:00:00+02:00"
title = "Tracking using a camera"
highlight = true
draft = false
tags = ["kieferbot", "ros"]
+++
Here's Kieferbot being tracked through a camera:
<video controls src="tracking.mp4"></video>
It took a few iterations but I settled on matching the colour of the
floor to create a floor mask, then [findCountours][fc] to find the
contours as a tree, and then searching the children of the root
contours. As the bot is black, the children were matched against a
'black pixels' mask, and the contour with the most black pixels
picked.
The camera is an Android phone running [IP Webcam][ipw] and sharing
the back camera as MJPEG over HTTP over Wifi at 10 FPS. It could be
higher, but the laptop doing the image processing has trouble keeping
up with 30 FPS. The latency looks good - visually less than 200 ms.
The tracking seems reliable. If the bot goes off the bottom of the
frame then other black areas are picked, but this can be detected by
checking for a jump in position.
Next step is to integrate the camera position, phone sensors, and
wheel velocity to get a controllable position.
[ipw]: https://play.google.com/store/apps/details?id=com.pas.webcam&hl=en
[fc]: https://docs.opencv.org/trunk/d4/d73/tutorial_py_contours_begin.html

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 178 KiB

View file

@ -0,0 +1,24 @@
---
title: "VE.Direct"
subtitle: "Parser and exporter for the Victron VE.Direct protocol"
summary: ""
authors: ['michaelh']
tags: []
categories: []
date: 2020-12-01T19:44:20+01:00
lastmod: 2020-12-01T19:44:20+01:00
featured: false
draft: false
projects: ['solarch']
---
I've released [vedirect](https://github.com/nzmichaelh/vedirect/), a
tool parses the Victron VE.Direct TEXT protocol and exports the
metrics over Prometheus and MQTT. This can be used to monitor your
solar installation and view statistics in tools like Grafana or Home
Assistant.
See the
[README](https://github.com/nzmichaelh/vedirect/blob/master/README.md)
for more. I'm using this to monitor the solar system used to power my
home server.

View file

@ -0,0 +1,11 @@
+++
date = "2020-10-09T00:02:42+02:00"
title = "Vouch for authentication"
highlight = true
draft = false
+++
I've started using [Vouch](https://github.com/vouch/vouch-proxy) for
SSO to my personal site. Quite happy with the experience - it
integrates well with Nginx, was straight forward to setup, and is
straight forward to enable for different paths on the site.

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

View file

@ -0,0 +1 @@
panel.png

View file

@ -0,0 +1,94 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "VW to ABRP via Home Assistant"
authors: ["michaelh"]
date: 2021-12-30T19:40:05+01:00
lastmod: 2021-12-30T19:40:05+01:00
featured: false
draft: false
---
I have a Volkswagen ID series car that I'm pretty happy with. The car automatically uploads telemetry such as the current battery state of charge and, with a bit of work, this can be pulled into [Home Assistant](https://www.home-assistant.io/) for viewing and then re-exported to [A Better Route Planner](https://abetterrouteplanner.com/) to give live range planning.
First, add [ha_vwid](https://github.com/raymondd78/ha_vwid) as a custom component to your Home Assistant installation. I did this by:
```sh
cd /data/hass/third_party
git clone https://github.com/raymondd78/ha_vwid
cd ../custom_components
ln -s ../third_party/ha_vwid/custom_components/vwid
systemctl restart hass
```
The data had steps in it that looked like VW was throttling my queries, so I reduced the poll rate as well:
```patch
--- a/custom_components/vwid/sensor.py
+++ b/custom_components/vwid/sensor.py
@@ -80,7 +80,7 @@ async def async_setup_entry(
_LOGGER,
name = "VW ID Sensor",
update_method = async_update_data,
- update_interval = timedelta(seconds=30),
+ update_interval = timedelta(seconds=121),
)
# Fetch initial data so we have data when entities subscribe
```
Next, go to the Home Assistant UI and enable the `Volkswagen ID` integration. You'll need your We Connect ID user name, password, and VIN. Once done you can add a panel showing the vehicle highlights:
![Home Assistant panel showing the vehicle data](panel.png)
Now that Home Assistant has the data, create a command that can post the data to the [Iternio Telemetry API](https://documenter.getpostman.com/view/7396339/SWTK5a8w):
```yaml
rest_command:
update_abrp:
method: POST
headers:
authorization: !secret abrp_api_key
content_type: "charset=utf-8; application/x-www-form-urlencoded"
url: >
{% set tlm = {
"utc": float(as_timestamp(utcnow())),
"soc": states('sensor.volkswagen_id_state_of_charge'),
"est_battery_range": float(states('sensor.volkswagen_id_current_range_in_km')),
"is_charging": int(states('sensor.volkswagen_id_charge_rate')) > 0,
} -%}
https://api.iternio.com/1/tlm/send?token={{token}}&tlm={{tlm|to_json|urlencode}}
```
Note that this takes the telemetry, encodes it as JSON, then posts it as a query parameter. You can add other types to the `tlm` dict.
See the API documentation on how to obtain an API key. Once you have this, add it to `secrets.yaml` like `abrp_api_key: APIKEY 12341234-1234-1234-1234-12312341234`.
Finally, log into ABRP and use the `ABRP OBD Connection > Link generic` section to get a token for your vehicle. Use this to create an automation rule that runs the REST command whenever the range changes or time passes:
```yaml
- alias: Push car to ABRP
trigger:
- platform: state
entity_id: sensor.volkswagen_id_current_range_in_km
to:
- platform: time_pattern
minutes: "/8"
action:
- service: rest_command.update_abrp
data:
token: the-token-you-get-from-the-link-generic-ui-in-abrp
```
As a bonus, if you enable the Home Assistant Prometheus integration then you can also graph the charging and time remaining:
![Grafana dashboard showing state of charge and time remaining](dash.png)
and then use an expression like
```
predict_linear((homeassistant_sensor_unit_minutes>0)[30m:2m], 0)
unless (homeassistant_sensor_unit_minutes==0)
```
to get a finer estimate of when the charge will complete and alert when it's almost done.

Binary file not shown.

After

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 142 KiB

View file

@ -0,0 +1,29 @@
---
title: "AT-09 BLE to UART notes"
authors: ['michaelh']
date: 2021-03-14T16:34:46+01:00
lastmod: 2021-03-14T16:34:46+01:00
image:
caption: ""
focal_point: ""
preview_only: false
projects: ['solarch']
---
I picked up a couple of AT-09 Bluetooth to UART bridges for my solar at home project. Both the BMS and inverter have different grounds than the rest of the system, so rather than worry about isolating the signals I plan to send them over Bluetooth instead.
The modules have a few gotchas:
- It seems to have an intra-character timeout of < 0.1 s. If you type in commands manually then the characters don't arrive fast enough and the module returns `ERROR`, so it's best to write a script instead.
- Any mutate command causes a reset which takes ~1 s, so it's best to wait for the module to come back by sending `AT` until you get `OK`.
- [This is the best manual I could find](http://denethor.wlu.ca/arduino/MLT-BT05-AT-commands-TRANSLATED.pdf) and [this is the best blog post](https://blog.yavilevich.com/2017/03/mlt-bt05-ble-module-a-clone-of-a-clone/).
`AT+HELP` gives a list of commands but it's incomplete. For reference, I used the following to configure the module:
* `AT+BAUD5` - set the baud rate to 19200. 4 is 9600.
* `AT+NAMEPhoenix 24/375` - set the display name.
* `AT+TYPE1` - require a pin to connect.
* `AT+PIN123123` - set the 6 digit pin.
Note that each line must end with a `\r\n`.

View file

@ -0,0 +1 @@
../../../project/ausdauer/ausdauer1.jpg

View file

@ -0,0 +1,20 @@
---
title: "Ausdauer: assembled"
summary: "I've almost completed the right hand side, and the left hand side is far enough along that I can assemble the whole rover!"
authors: ['michaelh']
tags: []
categories: []
date: 2021-01-02T17:17:27+01:00
lastmod: 2021-01-02T17:17:27+01:00
featured: false
draft: false
projects: ['ausdauer']
---
I've almost completed the right hand side, and the left hand side is far enough along that I can assemble the whole rover!
The remaining steps are:
1. Epoxy the steering wheel and differential inserts in. I didn't modify the print, and the 3D Jake insets are ~1 mm smaller in diameter.
2. Cut the grooves on the left hand side shafts.
3. Print the differential.

View file

@ -0,0 +1 @@
../../../project/ausdauer/assembled2.jpg

View file

@ -0,0 +1,18 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Ausdauer: mechanical assembly"
subtitle: "A build of the Sawppy rover"
authors: ['michaelh']
categories: []
date: 2021-01-05T20:50:15+01:00
lastmod: 2021-01-05T20:50:15+01:00
featured: false
draft: false
projects: ['ausdauer']
---
And that's the end of the mechanical assembly. The differential went on fine, and the epoxy is strong enough to hold in the insets. There's one last thing - I missed the insets on the end of the differential arm, so those are glued and curing
Next is the electrical assembly. That'll take a while as each cable will need to be cut and extended.

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 88 KiB

View file

@ -0,0 +1,109 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Brainslug"
summary: "Adding remote control to a plain amplifier"
authors: ['michaelh']
date: 2021-01-30T17:06:51+01:00
lastmod: 2021-01-30T17:06:51+01:00
featured: false
draft: false
---
I have a [Marantz][marantz] [PM6006][pm6006] amplifier which sounds great, but it's older tech and doesn't integrate with the rest of my home automation. In particular I'd like to have it follow the TV power state and automatically turn on when the TV turns on and turn off shortly after the TV turns off. This should reduce the overall power consumption as it's a class AB amplifier and draws ~50 W even when idle.
The solution was to add Wifi based control using [ESPHome][esphome]. The integration was pretty clean as all of the signals needed are on the easily accessible STANDBY board which has:
- The always on 5 V standby supply
- The main power relay
- The wired remote
I used an [Olimex][olimex] [ESP8266][modwifi] board that I had in the spare parts drawer. The Olimex has a few unused pads which meant the support components (a MC1700 regulator, filter capacitor, and diode for the remote control interface) could be soldered to the board without needing an extra stripboard.
![Olimex ESP8266 board with wires off to the standby board](esp.jpg)
The signals needed are readily available on the STANDBY board. J8508 is +5 V, J8502 is GND, and the top two pins on N8504 are the `RC5` and `POW_ON` relay drive connections. The schematic for the very similar PM6005 is readily available online.
`POW_ON` connects to `GPIO15` and `RC5` to `GPIO13` via a diode so the infrared remote will still work. The ESPHome configuration is:
```yaml
esphome:
name: pm6006
comment: PM6006 Amplifier
platform: esp8266
board: modwifi
wifi:
ssid: "your-ssid-here"
password: "your-password-here"
ap:
ssid: "PM6006 Fallback Hotspot"
password: "random-data"
power_save_mode: HIGH
captive_portal:
logger:
prometheus:
api:
password: "your-secret-here"
ota:
password: "your-secret-here"
status_led:
pin:
number: GPIO1
inverted: True
binary_sensor:
- platform: gpio
name: "PM6006 power sense"
id: pm6006_power_sense
pin:
number: 15
remote_transmitter:
pin:
number: GPIO13
inverted: True
carrier_duty_percent: 100%
switch:
- platform: template
name: "PM6006 power"
lambda: |-
if (id(pm6006_power_sense).state) {
return true;
} else {
return false;
}
turn_on_action:
remote_transmitter.transmit_rc5:
address: 0x10
command: 0x0C
repeat: 2
turn_off_action:
remote_transmitter.transmit_rc5:
address: 0x10
command: 0x0C
repeat: 2
```
Once flashed, the devices appears in [Home Assistant][hass] and can be controlled from there. The device appears as a single switch where the state reflects the main power relay state so any external changes (like using the remote control) or lost packets will still show the correct power state.
I had to patch ESPHome to support the remote transmitter inverted mode. I'll clean the patch up and send it upstream.
Marantz use the [RC-5][rc5] standard commands so I'll add other commands like volume control and input selection in the future.
I initially tried using a ESP32 board but the initial current draw was too high and caused the standby supply to collapse. The ESP8266 board draws about 70 mA once connected.
[marantz]: https://www.marantz.com/
[pm6006]: https://www.marantz.com/en-gb/shop/amplifier/pm6006ukspecialedition
[olimex]: https://www.olimex.com/
[modwifi]: https://www.olimex.com/Products/IoT/ESP8266/MOD-WIFI-ESP8266-DEV/open-source-hardware
[hass]: https://www.home-assistant.io/
[rc5]: https://en.wikipedia.org/wiki/RC-5
[esphome]: https://esphome.io/

View file

@ -0,0 +1,83 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Duckiebot debugging"
subtitle: ""
summary: ""
authors: []
tags: []
categories: []
date: 2021-09-26T10:13:19+02:00
lastmod: 2021-09-26T10:13:19+02:00
featured: false
draft: false
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
# Focal points: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight.
image:
caption: ""
focal_point: ""
preview_only: false
# Projects (optional).
# Associate this post with one or more of your projects.
# Simply enter your project's folder or file name without extension.
# E.g. `projects = ["internal-project"]` references `content/project/deep-learning/index.md`.
# Otherwise, set `projects = []`.
projects: []
---
I've picked up a Duckietown Duckiebot DB21M. Under the hood it's a Linux SBC running ROS that talks to the HUT I/O board. There's a nice host side set of utilities and Docker based tools that let you interact from a standard laptop.
So far I can't get the motors to spin. I had problems initially with the camera connector being in backwards, which meant the interface ROS node couldn't start, which dropped all interfaces, but that was found via `docker ps` and `docker logs`.
I'm not fond of the nylon fixings. They're very easy to strip. The supplied SD card seems to be faulty as my laptop doesn't recognise it, but I had a spare class A1 card that imaged fine. The Duckiebattery is cool - it looks like a standard no-name phone charging battery, but it's running custom firmware that reports the battery state over USB.
It seems the earlier DB17 used an PCA9685 based HAT from Adafruit, and these were integrated into the Hut?
The [firmware](https://github.com/duckietown/fw-device-hut/tree/jetson-nano) is ATMEGA based and seems to have I2C based registers that run the I/O.
Reading the firmware, there is LED 0 (0x40?) Motor 1 (0x60?)
`i2cdetect` doesn't detect these devices but it's skipping addresses.
`i2cset -y 1 0x40 0 0x20` gets an ACK.
The LEDs are on command 6 onwards. I can change the colour of the LEDs using `i2cset ...`.
So the HUT processor is working. The register layout is more complicated so I'll look at the motor supply.
The motor is sold by Sparkfun as a DG01D-E with pinout https://cdn.sparkfun.com/assets/learn_tutorials/1/1/7/6/assembly_encoder_pin_map.jpg which is:
* Motor +
* Motor -
* Encoder VCC
* Encoder A
* Encoder B
* Encoder GND
The next-door servo pins shows 4.7 V, and it's likely that's the same supply as the motor driver.
`rqt_graph` shows a range of nodes including `led_emitter_node` and `right_wheel_encoder_node`.
The code shows that you can run commands like `rosservice call /ente1/led_emitter_node/set_pattern "pattern_name: {data: CAR_SIGNAL_PRIORITY}"`
The flashing is intermittent. `dmesg` shows that the board is having issues with I2C:
```
[ 498.097932] tegra-i2c 7000c400.i2c: arb lost in communicate to add 0x40
[ 498.104813] tegra-i2c 7000c400.i2c: Un-recovered Arb lost
[ 500.587954] tegra-i2c 7000c400.i2c: arb lost in communicate to add 0x40
```
The TOF sensor is working, so it's not that. Seems to be on address 0x29.
What's at address 0x70?
The RS datasheet has a parts list at https://docs.rs-online.com/c57a/A700000007343652.pdf. The IMU is a MPU-9250 which is normally address 0x68 or 0x69.
0x70 may be a TCA9548 I2C multiplexer. Does the front bumper board also contain a multiplexer?
Or another PCA9685?
The LEDs seem to stop on a different colour, which is what WS2812 LEDs do when the signal is interrupted. Is the HUT resetting?

View file

@ -0,0 +1,129 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "HEYO BMS Notes"
authors: ['michaelh']
tags: ['solar']
date: 2021-02-06T17:00:36+01:00
lastmod: 2021-02-06T17:00:36+01:00
featured: false
draft: false
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
# Focal points: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight.
image:
caption: ""
focal_point: ""
preview_only: false
# Projects (optional).
# Associate this post with one or more of your projects.
# Simply enter your project's folder or file name without extension.
# E.g. `projects = ["internal-project"]` references `content/project/deep-learning/index.md`.
# Otherwise, set `projects = []`.
projects: ['solarch']
---
The HEYO BMS appears to be a DALY clone. My 8S 60A model has a selection of ports - on the top:
* NTC (3 pin)
* UART (6 pin)
* Unnamed 5 pin)
On the bottom:
* Unnamed (4 pin)
* Monitor (3 pin)
* Unnamed (2 pin)
It's likely the 2 pin unnamed port is the wake up switch, and the unnamed 5 pin is a RS 485 connection.
## UART
The Bluetooth module connects to the 6 pin UART connector with a 6 pin to USB mini B cable. Despite the connector, the signaling is 3.3 V UART at 9600 N81.
The pins use a confusing colour set. They are:
1. GND (black)
2. +3.3V (green)
3. N/C
4. N/C
5. TXD (white)
6. RXD (red)
The Bluetooth adapter uses BLE with a custom write service and a read service Example frames seen over the Bluetooth UART are:
To BMS:
```
d2 03 00 00 00 3e d7 b9 ?????>??
d2 03 00 a9 00 20 87 91 ????? ??
d2 03 00 00 00 3e d7 b9
d2 03 00 a9 00 20 87 91 ?????>??????? ??
```
From BMS:
```
d2 03 40 34 30 31 30 31 32 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 42 4d 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 65 13 ??@401012??????????????????????????BMS?????????????????????????????e?
d2 03 7c 0d 6e 0d 69 0d 59 0d d7 0d 0b 0d 0b 0d 0c 0d 0b 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 3d 00 28 00 28 00 00 00 00 00 00 00 00 00 00 01 0f 75 30 03 e8 0d d7 0d 0b 00 3d 00 3d 00 00 00 fa 00 08 00 01 00 00 00 00 00 01 00 01 0d 46 00 cc 00 00 00 00 00 00 00 00 00 00 0e e1 ??|?n?i?Y???????????????????????????????????????????????????????????=?(?(????????????u0???????=?=?????????????????F??????????????
```
Surprisingly this is not the same as the common [SMART BMS protocol](https://blog.ja-ke.tech/2020/02/07/ltt-power-bms-chinese-protocol.html). The overall framing looks straight forward:
* uint8 SOF: D2
* uint8 ???: 03
* uint8 Payload length: (40, 7C)
* Payload
* uint16 Checksum
The `0d 6e` and similar are likely big endian uint16 battery voltages in mV.
Next up I'll dig up a Windows machine and capture the serial data between the PC app and the BMS to see if it's the same.
## CRC
[CRC RevEng](https://reveng.sourceforge.io/) shows that the checksum is CRC-16/MODBUS:
```
./reveng -w 16 -l -s d203063132333435364c69 d2035200fa0e10000100080000000000010000000000ff012c012c0ea60ea60b54012c012c00e800e8731d731d784d784d0069006900000000006e006e000000000000000000ff00ff0c8000320000000000aa00285737
./reveng: warning: you have only given 2 samples
./reveng: warning: to reduce false positives, give 4 or more samples
width=16 poly=0x8005 init=0xffff refin=true refout=true xorout=0x0000 check=0x4b37 residue=0x0000 name="CRC-16/MODBUS"
```
# Windows app
Using Wireshark with USBpcap gives the serial stream from the Windows App to the BMS. A sample:
```
1612695069.430 OUT A5 40 90 08 00 00 00 00 00 00 00 00 7D
1612695069.647 IN A5 01 90 08 01 06 01 06 75 3A 00 5A 55
1612695069.906 OUT A5 40 91 08 00 00 00 00 00 00 00 00 7E
1612695070.143 IN A5 01 91 08 0C F9 02 0C AD 07 00 00 06
1612695070.191 OUT A5 40 92 08 00 00 00 00 00 00 00 00 7F
1612695070.447 IN A5 01 92 08 3D 01 3D 01 00 00 00 00 BC
1612695070.520 OUT A5 40 93 08 00 00 00 00 00 00 00 00 80
1612695070.655 IN A5 01 93 08 01 01 01 7E 00 00 09 4E 19
1612695070.739 OUT A5 40 94 08 00 00 00 00 00 00 00 00 81
1612695070.943 IN A5 01 94 08 08 01 01 00 00 00 00 00 4C
1612695071.066 OUT A5 40 95 08 00 00 00 00 00 00 00 00 82
1612695071.151 IN A5 01 95 08 01 0C F7 0C FA 0C F7 00 50 A5 01 95 08 02 0C F8 0C AF 0C AF 00 BF A5 01 95 08 03 0C AD 0C AD 0C AF 00 73
```
This is different again:
* uint8 SOF 0xA5
* uint8 node ID? 0x40 out, 0x01 from BMS
* uint8 register?
* uint8 length 0x08
* uint8[] body
* uint8 checksum
The checksum seems to be the sum of the payload.
Requests come from node `0x40` and always have an empty 8 byte payload.
Some requests like register `0x95` give multiple responses. `0x95` looks like the cell voltages: `0x01` then 3x 16 bit voltage in mV repeated 3 times.

View file

@ -0,0 +1,40 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "GPIO and Home Assistant"
date: 2021-02-28T17:41:07+01:00
lastmod: 2021-02-28T17:41:07+01:00
featured: false
draft: false
authors: ['michaelh']
projects: ['solarch']
---
As part of moving my home server to solar power, I need a way of switching over to mains if there's been a few grey days and the battery is getting low. I've attached a relay to the Raspberry Pi's GPIO to switch the charger input from solar to a [MEAN WELL 100 W supply](https://www.meanwell-web.com/en-gb/ac-dc-single-output-enclosed-power-supply-lrs--100--36) but integrating is surprisingly tricky:
- The [`rpi_gpio`](https://www.home-assistant.io/integrations/rpi_gpio/) module uses RPi.GPIO which isn't 64 bit clean and fails to compile on Ubuntu
- The [`remote_rpi_gpio`](https://www.home-assistant.io/integrations/remote_rpi_gpio/) module uses [pigpiod](http://abyz.me.uk/rpi/pigpio/pigpiod.html) which for some reason uses 20 % CPU when idle.
I settled on [`pi-mqtt-gpio`](https://github.com/flyte/pi-mqtt-gpio), as most of my other custom integrations are over MQTT. The config is:
```yaml
mqtt:
host: localhost
topic_prefix: host/keylime
discovery: true
gpio_modules:
- name: gpiod
module: gpiod
digital_outputs:
- name: mains_select
module: gpiod
pin: 17
on_payload: "ON"
off_payload: "OFF"
```
`discovery` is undocumented but enables Home Assistant [MQTT discovery](https://www.home-assistant.io/docs/mqtt/discovery/), so it's zero extra config.
This should be usable on non-Pi hosts as well due to using the gpiod module.

View file

@ -0,0 +1,21 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Solar limits"
authors: ['michaelh']
date: 2021-03-06T12:17:07+01:00
lastmod: 2021-03-06T12:17:07+01:00
featured: false
draft: false
projects: ['solarch']
---
Something unexpected with my solar power setup: the cable loss is limiting the power produced by the panel, but it's due to the voltage drop and not the power loss.
The cable is ~20 m of 1 mm^2^ flex for a total of 0.71 Ω. The peak power point of the panel is 34.3 V and the Victron charge controller needs 30.1 V to charge an 8S LiFePO4 battery.
This means the maximum current is `I = (34.3 - 30.1) / 0.71` = 5.9 A, which is `34.3 * 5.9` = 202 W generated, 24 W of loss, and 178 W delivered.
![Power delivered versus generated](sim.png)
Changing to 2.5 mm^2^ flex will cut the resistance to 0.28 Ω, ups the current to 9.2 A, and deliver 291 W.

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -0,0 +1,31 @@
import numpy as np
import matplotlib.pyplot as plt
Vpp = 34.3
Vmin = 30.1
P = np.arange(1, 315 + 1)
def delivered(r: float, p: float) -> float:
i = p / Vpp
vdrop = i * r
vc = Vpp - vdrop
if vc <= Vmin:
return 0
return vc * i
plt.plot(P, [delivered(0.71, p) for p in P], label='1 mm2')
plt.plot(P, [delivered(0.28, p) for p in P], color='r', label='2.5 mm2')
plt.plot(P, P, color='g', label='limit')
plt.xlim(0, max(P))
plt.ylim(0, max(P))
plt.legend()
plt.title('Delivered power')
plt.xlabel('Ppv')
plt.ylabel('Pdelivered')
plt.grid()
plt.savefig('sim.png', transparent=True, bbox_inches='tight')
#plt.show()

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

View file

@ -0,0 +1,97 @@
---
title: "Local SolaX data"
subtitle: ""
summary: ""
authors: []
tags: []
categories: []
date: 2021-12-05T15:49:08+01:00
lastmod: 2021-12-05T15:49:08+01:00
featured: false
draft: false
projects: []
---
I've recently installed a [SolaX X1 Mini](https://www.solaxpower.com/x1-mini/) grid-tied inverter. This comes with a Wifi adapter and cloud offering where you can view the current system performance. This post covers how to redirect the underlying MQTT connection so you can read data from the inverter without data leaving your network.
The steps are:
- Patch Mosquitto to accept packets with a zero packet identifier
- Configure Mosquitto to also listen on port 2901
- Change your DNS to map `mqtt001.solaxcloud.com` and `mqtt002.solaxcloud.com` to your MQTT broker
- Configure Home Assistant or similar to unpack the updates
The uplink is implemented using an unencrypted MQTT connection to `mqtt001.solaxcloud.com` on port 2901. The inverter fails over to `mqtt002.solaxcloud.com` if the first is unavailable.
The `PUBLISH` packets sent by the inverter are invalid as the packet identifier is set to zero. This can be worked around by patching [Mosquitto](https://mosquitto.org/) and [removing this check](https://github.com/eclipse/mosquitto/blob/3cbe805e71ac41a2a20cc9b2ea6b3b619f49554a/src/handle_publish.c#L107) from `handle_publish.c`. If you don't do this then Mosquitto will detect a protocol violation and close the connection.
On connection the inverter subscribes to a set of topics, requests the current time, and reports as 'up'. It then publishes the current state every five minutes. All topics contain the Wifi adapter serial number and all payloads are JSON.
An example update published on `loc/$WIFI_SERIAL_NUMBER` is:
```json
{
'type': 'X1-Boost-Air-Mini',
'SN': '$WIFI_SERIAL_NUMBER',
'ver': '2.033.20',
'Data': [
0.2, 0.0, 75.0, 0.0, 0.3, 228.8, 7, 18, 0.0, 1.1,
0, 17, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0,
49.99, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0.0, 0, 0, 0, 0, 0.0, 0, 0, 2,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0],
'Information': [
1.1, 4,
'X1-Boost-Air-Mini',
'$INVERTER_SERIAL_NUMBER',
1, 2.1, 0.0, 1.3, 0.0
]
}
```
`Data` contains the readings and these seem to correspond to the [direct API fields](https://github.com/GitHobi/solax/wiki/74_SolaxDirect.pm-Readings) decoded by [Hobi](https://github.com/GitHobi) and [used by](https://github.com/squishykid/solax/blob/master/solax/inverter.py) [squishykid](https://github.com/squishykid/). For example, in the readings above:
- The panels are delivering 0.2 A at 75 V
- The grid is at 228.8 V
- The system is delivering 8 W and has output 1.1 kWh over the system lifetime
These can be decoded in [Home Assistant](https://www.home-assistant.io/) using [MQTT sensor definitions](https://www.home-assistant.io/integrations/sensor.mqtt/) like:
```yaml
- platform: mqtt
name: "solax_power_now"
unique_id: "solax_power_now"
state_topic: "loc/$WIFI_SERIAL_NUMBER"
value_template: "{{ value_json.Data[6] }}"
expire_after: 900
unit_of_measurement: "W"
device_class: power
```
which will show as:
![Power history](featured.png)
## Notes
On connection, the inverter subscribes to:
* `respsynctime/$WIFI_SERIAL_NUMBER`
* `set/$WIFI_SERIAL_NUMBER`
* `set/$WIFI_SERIAL_NUMBER/init`
* `update/version/$WIFI_SERIAL_NUMBER`
* `base/down/$WIFI_SERIAL_NUMBER`
I suspect the `set` topic is used for remote configuration and `update` is used to update the firmware.
It then:
* publishes `reqsynctime/$WIFI_SERIAL_NUMBER`: `{'wifisn': '$WIFI_SERIAL_NUMBER'}`
* receives `respsynctime/$WIFI_SERIAL_NUMBER`: `{'month': '12', 'hour': '11', 'year': '2021', 'day': '4', 'taskId': '297868bb24194080bdf749ab26adc3d6', 'minute': '20', 'second': '30'}`
* publishes `Synctime/$WIFI_SERIAL_NUMBER` `{'code': '2', 'message': 'setting failed'}`
* publishes `base/up/$WIFI_SERIAL_NUMBER`: `{'type': 2, 'wifiSN': '$WIFI_SERIAL_NUMBER', 'domain': 'mqtt002.solaxcloud.com', 'port': 2901}`

Binary file not shown.

After

Width:  |  Height:  |  Size: 125 KiB

View file

@ -0,0 +1,32 @@
---
title: "ZX0"
authors: ['michaelh']
date: 2021-06-19T16:34:46+01:00
lastmod: 2021-06-19T16:34:46+01:00
projects: ['zx0']
---
ZX0 is my [Sinclar ZX81-like][zx81] hobby computer. The idea is to make something in the ZX81 form factor, use a [Raspberry Pi Zero][pizero] for emulation, and then write some interesting apps that run on the emulator.
Today I got the prototype keyboard working. This uses the ZX81 40 key layout and uses a SAMD21 to scan the keys and report the LEDs. The SAMD21 is running [Zephyr][zephyr], talks to the Pi over I2C, and emulates the [LM8333][lm8333] key matrix scanner.
In the future I should be able to use the built-in Linux driver but for now the Pi runs a simple program that sends [SMBus][smbus] commands to read the key FIFO and publishes the keys via [uinput][uinput].
![Board running an emulator](overall.jpg)
I found quite a few issues with my schematic:
- `SDA` and `SCL` were swapped. This was fixed in software.
- `RX` and `TX` were swapped. This was fixed by swapping the pins in the cable.
- The SAMD21 really needs an interrupt line to wake up the Pi. The work-around is to poll.
- The USB connector is too hard to hand solder. I've switched this for a chunkier Adafruit connector for future versions.
- The regulator has the wrong footprint and pin order. I couldn't get my first choice and ordered something that I thought was pin compatible, but I was wrong. The work-around is to pull the 3V3 line from the Pi.
Next step is to create a bootloader for the SAMD21 so I can program it from the Pi. I'm thinking of starting with the [Adafruit UF2 bootloader][uf2] and adapting the SAM-BA / BOSSA protocol to work over I2C.
[zx81]: https://en.wikipedia.org/wiki/ZX81
[pizero]: https://www.raspberrypi.org/products/raspberry-pi-zero/
[zephyr]: https://www.zephyrproject.org/
[lm8333]: https://www.ti.com/product/LM8333
[smbus]: https://en.wikipedia.org/wiki/System_Management_Bus
[uinput]: https://www.kernel.org/doc/html/latest/input/uinput.html
[uf2]: https://github.com/adafruit/uf2-samdx1

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View file

@ -0,0 +1,32 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "Gitjournal"
subtitle: ""
summary: ""
authors: []
tags: []
categories: []
date: 2022-06-26T12:26:02+02:00
lastmod: 2022-06-26T12:26:02+02:00
featured: false
draft: false
# Featured image
# To use, add an image named `featured.jpg/png` to your page's folder.
# Focal points: Smart, Center, TopLeft, Top, TopRight, Left, Right, BottomLeft, Bottom, BottomRight.
image:
caption: ""
focal_point: ""
preview_only: false
# Projects (optional).
# Associate this post with one or more of your projects.
# Simply enter your project's folder or file name without extension.
# E.g. `projects = ["internal-project"]` references `content/project/deep-learning/index.md`.
# Otherwise, set `projects = []`.
projects: []
---
[GitJournal](https://gitjournal.io/) is very cool. It's an Android app where you can write notes in Markdown and then sync up to your own Git repository.
I was using NextCloud social for small private notes but that's been abandoned. This setup is clean, text based, future proof, and allows self hosting. Nice!

BIN
content/post/2022/nppilot/figure8.mp4 (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -0,0 +1,28 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "nppilot using Ardupilot"
authors: ["michaelh"]
date: 2022-01-16T17:44:44+01:00
lastmod: 2022-01-16T17:44:44+01:00
projects: ["nppilot"]
---
I've been working on nppilot, the "never complete autopilot" project for some time now. The latest iteration uses a [Traxxas Revo 1/16][revo], an [OpenPilot Revolution][oprevo] for I/O, and a Raspberry Pi 3B running [ROS][ros] as the command computer.
And it works! Here's the car running a figure-8 pattern:
{{<video src="figure8.mp4" controls="yes" >}}
It doesn't do much at the moment, but that's more progress than the other reboots.
Some notes on the setup:
- I changed the spur gear down to 18T to reduce the top speed, get more speed control, and reduce the number of high speed crashes...
- Wifi with a range extender seems fine as a monitoring link
- I tried a Pi 4B, but my USB power bank can't supply enough current. This matches [benchmarks][pwr] where the 4B is 2.7 W at idle vs 1.2 W.
[revo]: https://traxxas.com/products/models/electric/erevo-vxl-116-tsm
[oprevo]: https://ardupilot.org/copter/docs/common-openpilot-revo-mini.html
[ros]: https://ros.org/
[pwr]: https://www.pidramble.com/wiki/benchmarks/power-consumption

View file

@ -0,0 +1,26 @@
---
title: "CH32V003 and Zephyr"
authors: ['michaelh']
date: 2023-01-29T11:45:23+01:00
lastmod: 2023-01-29T11:45:23+01:00
featured: false
draft: false
projects: ['ch32v003']
---
# CH32V003 and Zephyr
I've picked up a CH32V003 development board. Their claim to fame is being a
RISC-V 32 bit microcontroller with 16 KiB of flash for $0.10 in
quantity. I'd like to port Zephyr to it - there's no good reason as
the default Zephyr configuration is too big for 16 KiB of flash and 2
KiB of RAM, but stripped down it fits quite well.
I'll update this post as I go along.
## GPIOD traps
Be careful if you configure GPIOD at start up. The reset pin and SWD
pin are both on GPIOD, and if you set them to output at startup then
the chip can no longer be programmed.
My solution was to desolder and replace the chip.

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 77 KiB

View file

@ -0,0 +1,25 @@
---
# Documentation: https://sourcethemes.com/academic/docs/managing-content/
title: "XT60 based charger"
authors: ["michaelh"]
tags: ["hacks"]
date: 2023-06-04T17:54:35+02:00
lastmod: 2023-06-04T17:54:35+02:00
featured: false
draft: false
---
[charger](https://juju.nz/src/michaelh/hacks/src/branch/master/charger)
is a case for a [no-name car charger](https://www.aliexpress.com/item/1005005144919264.html) that lets you use model aircraft
batteries to charge your phone.
The charger is quite nice. It's panel mount and comes with a QC 3.0
port and two USB-C power delivery ports. The PD ports charge my
Pixel at more than 12 W.
I made this as we were going camping and wanted to keep our phones
charged. I've got quite a few 3S and 4S model aircraft batteries and
this was less wasteful than buying a power bank.
![Render of the case](charger.png)

View file

@ -0,0 +1,37 @@
---
title: "Faster posting"
date: 2023-12-26
---
TL;DR: the minimal template is:
```
---
title: "Faster posting"
date: 2023-12-26
---
Content with no initial title
```
Details:
I'm using Hugo, which is a static site generator.
Looks like it's possible to post from gitea. Let's try...
Step 1: install drone.io. The site builds, and this file is rendered, but it's not part of the index.
Step 2: add a minimal header with `draft` and `authors`.
Step 3: add a title and date.
Step 4: drone stops updating to the latest?
Step 5: drop the header
Step 6: re-add the header. The publish date was in the future.
Step 7: just the date.
Step 8: just the title.
Step 9: re-add the date.

View file

@ -0,0 +1,54 @@
---
title: Ampler eBike Bluetooth protocol
authors: [michaelh]
date: 2024-05-12
---
I have an [Ampler Stout][stout] eBike which exposes metrics as Bluetooth attributes over [GATT]. I'd
like to track the battery level and odomoter, so spent some time and decoded some of the attributes.
The bike exposes:
| Characteristic | Example data |
| ------------------------------------ | ------------------------------------------------------------------------------- |
| 340d1528-a89e-4d4e-9078-06d21096ea36 | 0x5b 0x00 0x00 0x00 0x11 0x02 0x00 0x00 0x04 0x01 0x00 0x00 0x00 0x00 0x00 0x00 |
| 340d1529-a89e-4d4e-9078-06d21096ea36 | 0x00 0x00 0x00 0x00 0xdf 0x14 0x00 0x00 0x9c 0x0a 0x90 0x00 |
| 340d1530-a89e-4d4e-9078-06d21096ea36 | 0xa0 0x00 0x90 0x01 0x02 0x00 0x06 0x00 0x64 0x00 0xfa 0x00 |
| 340d1536-a89e-4d4e-9078-06d21096ea36 | 0x01 |
| 340d1538-a89e-4d4e-9078-06d21096ea36 | 0x00 |
| 340d1542-a89e-4d4e-9078-06d21096ea36 | 0x58 0x02 |
| 340d1544-a89e-4d4e-9078-06d21096ea36 | 0x00 |
| 340d1545-a89e-4d4e-9078-06d21096ea36 | 0x0a 0x18 0xe2 0x64 |
| 340d1547-a89e-4d4e-9078-06d21096ea36 | 0xff 0x02 0x11 0x00 0x00 0x00 0x03 0x00 |
| 340d1548-a89e-4d4e-9078-06d21096ea36 | 0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00 |
| 340d1549-a89e-4d4e-9078-06d21096ea36 | 0x00 0x00 0x00 0x00 |
| 340d1550-a89e-4d4e-9078-06d21096ea36 | 0x33 |
The format appears to pack related values into the same characteristic. Values are little endian and
either half words or words. The units seem to be metric such as `m` for range and `m/s` for speed
with a power of 10 multiplier, such as the voltage being in decivolts:
| Characteristic | [Format] | Fields |
| ------------------------------------ | -------- | --------------------------------------------- |
| 340d1528-a89e-4d4e-9078-06d21096ea36 | HHhH | % charged, voltage (dV), temperature (dºC), ? |
| 340d1529-a89e-4d4e-9078-06d21096ea36 | III | ?, speed (mm/s), odometer (dm) |
| 340d1536-a89e-4d4e-9078-06d21096ea36 | B | assist level (0, 1, 2) |
| 340d1538-a89e-4d4e-9078-06d21096ea36 | ? (bool) | light |
| 340d1545-a89e-4d4e-9078-06d21096ea36 | I | ? increases over time 1692538885 |
The time value isn't clear but might be a POSIX time, i.e. roughly Sunday, 20 August 2023.
Decoding the example above gives:
| Characteristic | Fields |
| ------------------------------------ | ------------------------------------- |
| 340d1528-a89e-4d4e-9078-06d21096ea36 | 91 % charged, 52.9 V, 26.0 ºC, 0 |
| 340d1529-a89e-4d4e-9078-06d21096ea36 | 0, 5343 mm/s (19.2 km/h), 943.9900 km |
| 340d1536-a89e-4d4e-9078-06d21096ea36 | assist level 1 |
| 340d1538-a89e-4d4e-9078-06d21096ea36 | light off |
Next step is to implement a decoder, export this to Home Assistant, and collect it via Prometheus.
[format]: https://docs.python.org/3/library/struct.html#format-characters
[gatt]: https://learn.adafruit.com/introduction-to-bluetooth-low-energy/gatt
[stout]: https://amplerbikes.com/en-CH/e-bikes/stout

View file

@ -0,0 +1,29 @@
---
title: "ESP32 as a low power sensor"
date: 2024-04-20
---
Notes on using an ESP32 as a low power sensor:
Battery:
- I have some 18650's already
- Battery holder is 76 x 21 x 19
- LiPo drop by about 1 % per month
- 3000 mAh at 1 %/month is ~40 uA/h
ESP32:
- FireBeetle 2 ESP32-C6 is apparently 20 uA in deep sleep
- 60 x 25.4 x 7.3 mm
- Takes up to a 6 V panel
Panel:
- Could use a solar panel to top up the power
- A 5 V 65 mA panel is 68 x 36 mm
- Ideally the LiPo should stay cool, but the panel should get sun...
Box:
- Maximum of dimensions is 76 x 36 x 19 mm
- Purecrea have a small 77 x 52 x 28 mm inside dimension box

View file

@ -0,0 +1,98 @@
---
title: "Learning FPGAs #1"
date: 2024-01-01
---
I normally work at the system or electronic level, and one thing I've always wanted to learn is FPGAs and the corresponding HDLs.
To pull this together, I plan to implement the 6502 using Verilog on an OrangeCrab board. The board uses a ECP5-25F and is supported by Yosys.
## 6502
I chose the 6502 as it reminds me of the VIC-20 and C128 I used to own, and it has
a small, straight forward instruction set.
According to https://llx.com/Neil/a2/opcodes.html, most instructions have a `aaabbbcc` format, where `aaa` and `cc` determine the opcode and `bbb` is the addressing mode. https://www.pagetable.com/c64ref/6502/ has a nice 3-3-2 view of this.
The instructions are divided into groups based on `cc`:
- 00 is group 3
- 01 is group 1
- 10 is group 2
- 11 is reserved
## Group 1 (c = 01)
Covers 1/4th of the decode space, where `aaa` is:
- 000 ORA
- 001 AND
- 010 EOR
- 011 ADC
- 100 STA
- 101 LDA
- 110 CMP
- 111 SBC
and `bbb` is:
- 000 (zero page,X)
- 001 zero page
- 010 #immediate
- 011 absolute
- 100 (zero page),Y
- 101 zero page,X
- 110 absolute,Y
- 111 absolute,X
## Group 2 (c = 10)
- 000 ASL
- 001 ROL
- 010 LSR
- 011 ROR
- 100 STX
- 101 LDX
- 110 DEC
- 111 INC
where `bbb` is:
- 000 #immediate
- 001 zero page
- 010 accumulator
- 011 absolute
- 101 zero page,X
- 111 absolute,X
So zero page, absolute, zero page, X, and absolute, X are the same.
## Group 3 (c = 00)
- 001 BIT
- 010 JMP
- 011 JMP (abs)
- 100 STY
- 101 LDY
- 110 CPY
- 111 CPX
where `bbb` is:
- 000 #immediate
- 001 zero page
- 011 absolute
- 101 zero page,X
- 111 absolute,X
which is the same as group 2 except `accumulator`.
The conditional branches have the form `xxy 100 00`, i.e. b is 100 and c is 00, and x is:
- 00 negative
- 01 overflow
- 10 carry
- 11 zero
which is compared with `y`.
Next is to implement the ALU.

View file

@ -0,0 +1,11 @@
---
title: "FPGA and blinking lights"
date: 2024-01-13
---
Today I got the OrangeCrab `blink` example running on my board, yay!
My daily driver is a Pixelbook, so I resurected an old laptop and put Debian stable on it so I could have
a good set of USB ports. The only niggle is that you need to replug the board to get into the boot loader,
but you can add a module to the design that watches the boot button and resets when pressed.
Overally, I'm happy. Next step is to write some RTL.

Some files were not shown because too many files have changed in this diff Show more